diff --git a/package.json b/package.json index 5107e80..0ad21ce 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ ], "main": "build/webcrypto.js", "module": "build/webcrypto.es.js", + "react-native": "build/webcrypto.es.js", "types": "index.d.ts", "scripts": { "test": "mocha", @@ -55,24 +56,24 @@ "devDependencies": { "@peculiar/webcrypto-test": "^1.0.7", "@types/mocha": "^10.0.6", - "@types/node": "^20.11.30", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@types/node": "^20.12.12", + "@typescript-eslint/eslint-plugin": "^7.10.0", + "@typescript-eslint/parser": "^7.10.0", "eslint": "^8.57.0", "eslint-plugin-import": "^2.29.1", "mocha": "^10.4.0", - "rimraf": "^5.0.5", - "rollup": "^4.13.2", + "rimraf": "^5.0.7", + "rollup": "^4.17.2", "rollup-plugin-typescript2": "^0.36.0", "ts-node": "^10.9.2", - "typescript": "^5.4.3" + "typescript": "^5.4.5" }, "dependencies": { "@peculiar/asn1-schema": "^2.3.8", "@peculiar/json-schema": "^1.1.12", "pvtsutils": "^1.3.5", "tslib": "^2.6.2", - "webcrypto-core": "^1.7.9" + "webcrypto-core": "^1.8.0" }, "nyc": { "extension": [ @@ -101,4 +102,4 @@ ], "spec": "test/**/*.ts" } -} +} \ No newline at end of file diff --git a/src/mechs/aes/aes_cmac.ts b/src/mechs/aes/aes_cmac.ts index 8cfcf0d..71ccc12 100644 --- a/src/mechs/aes/aes_cmac.ts +++ b/src/mechs/aes/aes_cmac.ts @@ -1,5 +1,5 @@ import { Buffer } from "buffer"; -import * as crypto from "crypto"; +import crypto from "crypto"; import * as core from "webcrypto-core"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; diff --git a/src/mechs/ed25519/crypto.ts b/src/mechs/ed25519/crypto.ts new file mode 100644 index 0000000..ba54151 --- /dev/null +++ b/src/mechs/ed25519/crypto.ts @@ -0,0 +1,120 @@ +import crypto from "crypto"; +import { AsnConvert } from "@peculiar/asn1-schema"; +import { Convert } from "pvtsutils"; +import * as core from "webcrypto-core"; +import { Ed25519CryptoKey } from "./crypto_key"; +import { Ed25519PrivateKey } from "./private_key"; +import { Ed25519PublicKey } from "./public_key"; +import { CryptoKey } from "../../keys"; + +export class Ed25519Crypto { + public static privateKeyUsages: KeyUsage[] = ["sign", "deriveBits", "deriveKey"]; + public static publicKeyUsages: KeyUsage[] = ["verify"]; + + public static async generateKey(algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + const type = algorithm.name.toLowerCase() as "ed25519"; + const keys = crypto.generateKeyPairSync(type, { + publicKeyEncoding: { + format: "pem", + type: "spki", + }, + privateKeyEncoding: { + format: "pem", + type: "pkcs8", + }, + }); + + const keyAlg = { + name: type === "ed25519" ? "Ed25519" : "X25519", + }; + const privateKeyUsages = keyUsages.filter((usage) => this.privateKeyUsages.includes(usage)); + const publicKeyUsages = keyUsages.filter((usage) => this.publicKeyUsages.includes(usage)); + return { + privateKey: new Ed25519PrivateKey(keyAlg, extractable, privateKeyUsages, keys.privateKey), + publicKey: new Ed25519PublicKey(keyAlg, true, publicKeyUsages, keys.publicKey), + }; + } + + public static async sign(algorithm: Algorithm, key: Ed25519PrivateKey, data: Uint8Array): Promise { + const signature = crypto.sign(null, Buffer.from(data), key.data); + + return core.BufferSourceConverter.toArrayBuffer(signature); + } + + public static async verify(algorithm: Algorithm, key: Ed25519PublicKey, signature: Uint8Array, data: Uint8Array): Promise { + return crypto.verify(null, Buffer.from(data), key.data, signature); + } + + public static async exportKey(format: KeyFormat, key: Ed25519CryptoKey): Promise { + switch (format) { + case "jwk": + return key.toJWK(); + case "pkcs8": { + return core.PemConverter.toArrayBuffer(key.data.toString()); + } + case "spki": { + return core.PemConverter.toArrayBuffer(key.data.toString()); + } + case "raw": { + const jwk = key.toJWK(); + return Convert.FromBase64Url(jwk.x!); + } + default: + return Promise.reject(new core.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'")); + } + } + + public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + switch (format) { + case "jwk": { + const jwk = keyData as JsonWebKey; + if (jwk.d) { + // private key + const privateData = new core.asn1.EdPrivateKey(); + privateData.value = core.BufferSourceConverter.toArrayBuffer(Buffer.from(jwk.d, "base64url")); + const pkcs8 = new core.asn1.PrivateKeyInfo(); + pkcs8.privateKeyAlgorithm.algorithm = algorithm.name.toLowerCase() === "ed25519" + ? core.asn1.idEd25519 + : core.asn1.idX25519; + pkcs8.privateKey = AsnConvert.serialize(privateData); + const raw = AsnConvert.serialize(pkcs8); + const pem = core.PemConverter.fromBufferSource(raw, "PRIVATE KEY"); + return new Ed25519PrivateKey(algorithm, extractable, keyUsages, pem); + } else if (jwk.x) { + // public key + const pubKey = crypto.createPublicKey({ + format: "jwk", + key: jwk as crypto.JsonWebKey, + }); + const pem = pubKey.export({ format: "pem", type: "spki" }) as string; + return new Ed25519PublicKey(algorithm, extractable, keyUsages, pem); + } else { + throw new core.OperationError("keyData: Cannot import JWK. 'd' or 'x' must be presented"); + } + } + case "pkcs8": { + const pem = core.PemConverter.fromBufferSource(keyData as ArrayBuffer, "PRIVATE KEY"); + return new Ed25519PrivateKey(algorithm, extractable, keyUsages, pem); + } + case "spki": { + const pem = core.PemConverter.fromBufferSource(keyData as ArrayBuffer, "PUBLIC KEY"); + return new Ed25519PublicKey(algorithm, extractable, keyUsages, pem); + } + case "raw": { + const raw = keyData as ArrayBuffer; + const key = crypto.createPublicKey({ + format: "jwk", + key: { + kty: "OKP", + crv: algorithm.name.toLowerCase() === "ed25519" ? "Ed25519" : "X25519", + x: Convert.ToBase64Url(raw), + }, + }); + const pem = key.export({ format: "pem", type: "spki" }) as string; + return new Ed25519PublicKey(algorithm, extractable, keyUsages, pem); + } + default: + return Promise.reject(new core.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'")); + } + } +} diff --git a/src/mechs/ed25519/crypto_key.ts b/src/mechs/ed25519/crypto_key.ts new file mode 100644 index 0000000..4bf5261 --- /dev/null +++ b/src/mechs/ed25519/crypto_key.ts @@ -0,0 +1,21 @@ +import { CryptoKey } from "../../keys"; + +export class Ed25519CryptoKey extends CryptoKey { + + constructor(algorithm: Algorithm, extractable: boolean, usages: KeyUsage[], data: string) { + super(); + this.algorithm = algorithm; + this.extractable = extractable; + this.usages = usages; + this.data = Buffer.from(data); + } + + public toJWK(): JsonWebKey { + return { + kty: "OKP", + crv: this.algorithm.name, + key_ops: this.usages, + ext: this.extractable, + }; + } +} diff --git a/src/mechs/ed25519/ed25519.ts b/src/mechs/ed25519/ed25519.ts new file mode 100644 index 0000000..2f0af1a --- /dev/null +++ b/src/mechs/ed25519/ed25519.ts @@ -0,0 +1,37 @@ +import * as core from "webcrypto-core"; +import { Ed25519Crypto } from "./crypto"; +import { Ed25519CryptoKey } from "./crypto_key"; +import { Ed25519PrivateKey } from "./private_key"; +import { Ed25519PublicKey } from "./public_key"; +import { getCryptoKey, setCryptoKey } from "../storage"; + +export class Ed25519Provider extends core.Ed25519Provider { + public override async onGenerateKey(algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + const keys = await Ed25519Crypto.generateKey(algorithm, extractable, keyUsages); + return { + privateKey: setCryptoKey(keys.privateKey as Ed25519CryptoKey), + publicKey: setCryptoKey(keys.publicKey as Ed25519CryptoKey), + }; + } + + override async onSign(algorithm: Algorithm, key: Ed25519PrivateKey, data: ArrayBuffer): Promise { + const internalKey = getCryptoKey(key) as Ed25519PrivateKey; + const signature = Ed25519Crypto.sign(algorithm, internalKey, new Uint8Array(data)); + return signature; + } + + override onVerify(algorithm: Algorithm, key: Ed25519PublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + const internalKey = getCryptoKey(key) as Ed25519PublicKey; + return Ed25519Crypto.verify(algorithm, internalKey, new Uint8Array(signature), new Uint8Array(data)); + } + + override async onExportKey(format: KeyFormat, key: Ed25519CryptoKey): Promise { + const internalKey = getCryptoKey(key) as Ed25519CryptoKey; + return Ed25519Crypto.exportKey(format, internalKey); + } + + override async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + const internalKey = await Ed25519Crypto.importKey(format, keyData, algorithm, extractable, keyUsages); + return setCryptoKey(internalKey); + } +} diff --git a/src/mechs/ed25519/index.ts b/src/mechs/ed25519/index.ts new file mode 100644 index 0000000..ea53357 --- /dev/null +++ b/src/mechs/ed25519/index.ts @@ -0,0 +1,4 @@ +export * from "./ed25519"; +export * from "./x25519"; +export * from "./private_key"; +export * from "./public_key"; diff --git a/src/mechs/ed25519/private_key.ts b/src/mechs/ed25519/private_key.ts new file mode 100644 index 0000000..8639382 --- /dev/null +++ b/src/mechs/ed25519/private_key.ts @@ -0,0 +1,23 @@ +import crypto from "crypto"; +import { AsnConvert } from "@peculiar/asn1-schema"; +import * as core from "webcrypto-core"; +import { Ed25519CryptoKey } from "./crypto_key"; + +export class Ed25519PrivateKey extends Ed25519CryptoKey { + public override type = "private" as const; + + public override toJWK(): JsonWebKey { + const pubJwk = crypto.createPublicKey({ + key: this.data, + format: "pem", + }).export({ format: "jwk" }) as JsonWebKey; + const raw = core.PemConverter.toUint8Array(this.data.toString()); + const pkcs8 = AsnConvert.parse(raw, core.asn1.PrivateKeyInfo); + const d = AsnConvert.parse(pkcs8.privateKey, core.asn1.EdPrivateKey).value; + return { + ...super.toJWK(), + ...pubJwk, + d: Buffer.from(new Uint8Array(d)).toString("base64url"), + }; + } +} diff --git a/src/mechs/ed25519/public_key.ts b/src/mechs/ed25519/public_key.ts new file mode 100644 index 0000000..ca2c030 --- /dev/null +++ b/src/mechs/ed25519/public_key.ts @@ -0,0 +1,18 @@ +import crypto from "crypto"; +import { Ed25519CryptoKey } from "./crypto_key"; + +export class Ed25519PublicKey extends Ed25519CryptoKey { + public override type = "public" as const; + + public override toJWK(): JsonWebKey { + const jwk = crypto.createPublicKey({ + key: this.data, + format: "pem", + }).export({ format: "jwk" }) as JsonWebKey; + + return { + ...super.toJWK(), + ...jwk, + }; + } +} diff --git a/src/mechs/ed25519/x25519.ts b/src/mechs/ed25519/x25519.ts new file mode 100644 index 0000000..a25e778 --- /dev/null +++ b/src/mechs/ed25519/x25519.ts @@ -0,0 +1,54 @@ +import crypto from "crypto"; +import * as core from "webcrypto-core"; +import { Ed25519Crypto } from "./crypto"; +import { Ed25519CryptoKey } from "./crypto_key"; +import { CryptoKey } from "../../keys"; +import { getCryptoKey, setCryptoKey } from "../storage"; + +export class X25519Provider extends core.X25519Provider { + public override async onGenerateKey(algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + const keys = await Ed25519Crypto.generateKey(algorithm, extractable, keyUsages); + return { + privateKey: setCryptoKey(keys.privateKey as Ed25519CryptoKey), + publicKey: setCryptoKey(keys.publicKey as Ed25519CryptoKey), + }; + } + + public override async onDeriveBits(algorithm: EcdhKeyDeriveParams, baseKey: Ed25519CryptoKey, length: number): Promise { + const internalBaseKey = getCryptoKey(baseKey); + const internalPublicKey = getCryptoKey(algorithm.public); + const publicKey = crypto.createPublicKey({ + key: internalPublicKey.data.toString(), + format: "pem", + type: "spki", + }); + const privateKey = crypto.createPrivateKey({ + key: internalBaseKey.data.toString(), + format: "pem", + type: "pkcs8", + }); + const bits = crypto.diffieHellman({ + publicKey, + privateKey, + }); + + return new Uint8Array(bits).buffer.slice(0, length >> 3); + } + + public override async onExportKey(format: KeyFormat, key: Ed25519CryptoKey): Promise { + const internalKey = getCryptoKey(key); + return Ed25519Crypto.exportKey(format, internalKey as Ed25519CryptoKey); + } + + public override async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + const key = await Ed25519Crypto.importKey(format, keyData, algorithm, extractable, keyUsages); + return setCryptoKey(key); + } + + override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage | undefined): void { + super.checkCryptoKey(key, keyUsage); + if (!(getCryptoKey(key) instanceof Ed25519CryptoKey)) { + throw new TypeError("key: Is not a Ed25519CryptoKey"); + } + } +} diff --git a/src/mechs/index.ts b/src/mechs/index.ts index 238ad11..a472234 100644 --- a/src/mechs/index.ts +++ b/src/mechs/index.ts @@ -3,6 +3,7 @@ export * from "./des"; export * from "./rsa"; export * from "./ec"; export * from "./ed"; +export * from "./ed25519"; export * from "./sha"; export * from "./pbkdf"; export * from "./hmac"; diff --git a/src/mechs/rsa/rsa_es.ts b/src/mechs/rsa/rsa_es.ts index 23b1e98..09df67c 100644 --- a/src/mechs/rsa/rsa_es.ts +++ b/src/mechs/rsa/rsa_es.ts @@ -1,4 +1,4 @@ -import * as crypto from "crypto"; +import crypto from "crypto"; import { Convert } from "pvtsutils"; import * as core from "webcrypto-core"; import { RsaCrypto } from "./crypto"; diff --git a/src/subtle.ts b/src/subtle.ts index 898a6e4..a7dd8b3 100644 --- a/src/subtle.ts +++ b/src/subtle.ts @@ -1,4 +1,4 @@ -import * as crypto from "crypto"; +import crypto from "crypto"; import * as process from "process"; import * as core from "webcrypto-core"; import { @@ -8,6 +8,7 @@ import { EcdsaProvider, HkdfProvider, EdDsaProvider, EcdhEsProvider, + Ed25519Provider, X25519Provider, HmacProvider, Pbkdf2Provider, RsaEsProvider, RsaOaepProvider, RsaPssProvider, RsaSsaProvider, @@ -95,6 +96,9 @@ export class SubtleCrypto extends core.SubtleCrypto { //#region ECDH-ES this.providers.set(new EcdhEsProvider()); //#endregion + + this.providers.set(new Ed25519Provider()); + this.providers.set(new X25519Provider()); } } } diff --git a/test/crypto.ts b/test/crypto.ts index 7e6e3e7..b135c7e 100644 --- a/test/crypto.ts +++ b/test/crypto.ts @@ -305,4 +305,226 @@ context("Crypto", () => { assert.strictEqual((keys.privateKey.algorithm as RsaHashedKeyAlgorithm).modulusLength, 3072); }).timeout(5000); + + context("Ed25519", () => { + context("generateKey", () => { + it("should generate key pair", async () => { + const alg = { name: "ed25519" }; + const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]); + assert.ok("privateKey" in keys); + assert.ok("publicKey" in keys); + assert.strictEqual(keys.privateKey.algorithm.name, "Ed25519"); + assert.strictEqual(keys.privateKey.type, "private"); + assert.strictEqual(keys.privateKey.extractable, false); + assert.deepStrictEqual(keys.privateKey.usages, ["sign"]); + assert.strictEqual(keys.publicKey.algorithm.name, "Ed25519"); + assert.strictEqual(keys.publicKey.type, "public"); + assert.strictEqual(keys.publicKey.extractable, true); + assert.deepStrictEqual(keys.publicKey.usages, ["verify"]); + }); + }); + context("sign/verify", () => { + it("should sign and verify data", async () => { + const alg = { name: "ed25519" }; + const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]); + assert.ok("privateKey" in keys); + const data = Buffer.from("message"); + const signature = await crypto.subtle.sign(alg, keys.privateKey, data); + assert.ok(signature instanceof ArrayBuffer); + assert.strictEqual(signature.byteLength, 64); + const ok = await crypto.subtle.verify(alg, keys.publicKey, signature, data); + assert.ok(ok); + }); + }); + context("import/export", () => { + let keys: CryptoKeyPair; + before(async () => { + const alg = { name: "ed25519" }; + keys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]) as CryptoKeyPair; + }); + context("private key", () => { + it("JWK", async () => { + const jwk = await crypto.subtle.exportKey("jwk", keys.privateKey); + // { + // key_ops: [ 'sign' ], + // ext: true, + // crv: 'Ed25519', + // d: 'zAe58NtXQO0A_nNc7REZroi3CARzn31jFr80RSjcrwI', + // x: 'xONSvzKNx83TPrwuqLF6TxhlHR8aIfnVhbSAsJ2M-VI', + // kty: 'OKP' + // } + assert.strictEqual(jwk.kty, "OKP"); + assert.strictEqual(jwk.crv, "Ed25519"); + assert.ok(jwk.d); + assert.ok(jwk.x); + assert.strictEqual(jwk.key_ops?.length, 1); + assert.strictEqual(jwk.key_ops![0], "sign"); + assert.strictEqual(jwk.ext, true); + assert.strictEqual(Buffer.from(jwk.d, "base64url").byteLength, 32); + assert.strictEqual(Buffer.from(jwk.x, "base64url").byteLength, 32); + + const alg = { name: "ed25519" }; + const key = await crypto.subtle.importKey("jwk", jwk, alg, false, ["sign"]); + assert.strictEqual(key.type, "private"); + assert.strictEqual(key.extractable, false); + assert.deepStrictEqual(key.usages, ["sign"]); + assert.strictEqual(key.algorithm.name, "Ed25519"); + }); + it("PKCS8", async () => { + const alg = "ed25519"; + const pkcs8 = await crypto.subtle.exportKey("pkcs8", keys.privateKey); + const key = await crypto.subtle.importKey("pkcs8", pkcs8, alg, false, ["sign"]); + assert.strictEqual(key.type, "private"); + assert.strictEqual(key.extractable, false); + assert.deepStrictEqual(key.usages, ["sign"]); + assert.strictEqual(key.algorithm.name, "Ed25519"); + }); + }); + context("public key", () => { + it("JWK", async () => { + const jwk = await crypto.subtle.exportKey("jwk", keys.publicKey); + assert.strictEqual(jwk.kty, "OKP"); + assert.strictEqual(jwk.crv, "Ed25519"); + assert.ok(jwk.x); + assert.strictEqual(jwk.key_ops?.length, 1); + assert.strictEqual(jwk.key_ops![0], "verify"); + assert.strictEqual(jwk.ext, true); + + const alg = { name: "ed25519" }; + const key = await crypto.subtle.importKey("jwk", jwk, alg, true, ["verify"]); + assert.strictEqual(key.type, "public"); + assert.strictEqual(key.extractable, true); + assert.deepStrictEqual(key.usages, ["verify"]); + assert.strictEqual(key.algorithm.name, "Ed25519"); + }); + it("SPKI", async () => { + const alg = "ed25519"; + const spki = await crypto.subtle.exportKey("spki", keys.publicKey); + const key = await crypto.subtle.importKey("spki", spki, alg, true, ["verify"]); + assert.strictEqual(key.type, "public"); + assert.strictEqual(key.extractable, true); + assert.deepStrictEqual(key.usages, ["verify"]); + assert.strictEqual(key.algorithm.name, "Ed25519"); + }); + it("RAW", async () => { + const alg = "ed25519"; + const raw = await crypto.subtle.exportKey("raw", keys.publicKey); + const key = await crypto.subtle.importKey("raw", raw, alg, true, ["verify"]); + assert.strictEqual(key.type, "public"); + assert.strictEqual(key.extractable, true); + assert.deepStrictEqual(key.usages, ["verify"]); + assert.strictEqual(key.algorithm.name, "Ed25519"); + }); + }); + }); + context("Vector data", () => { + const privateKeyJwk = { + key_ops: ['sign'], + ext: true, + crv: 'Ed25519', + d: 'EOxUciT6spODKVW-JQXGcIN59oqLvkZU52g8i8bR7Wo', + x: 'Wn9sXjjBJX1BH0A_lVbR_nY8kITs06nkxFl9ZE9XgSg', + kty: 'OKP' + }; + + const publicKeyJwk = { + key_ops: ['verify'], + ext: true, + crv: 'Ed25519', + x: 'Wn9sXjjBJX1BH0A_lVbR_nY8kITs06nkxFl9ZE9XgSg', + kty: 'OKP' + }; + + context("import/export", () => { + it("should correctly import and export private key", async () => { + const alg = { name: "ed25519" }; + const importedPrivateKey = await crypto.subtle.importKey("jwk", privateKeyJwk, alg, true, ["sign"]); + const exportedPrivateKeyJwk = await crypto.subtle.exportKey("jwk", importedPrivateKey); + assert.deepStrictEqual(exportedPrivateKeyJwk, privateKeyJwk); + }); + + it("should correctly import and export public key", async () => { + const alg = { name: "ed25519" }; + const importedPublicKey = await crypto.subtle.importKey("jwk", publicKeyJwk, alg, true, ["verify"]); + const exportedPublicKeyJwk = await crypto.subtle.exportKey("jwk", importedPublicKey); + assert.deepStrictEqual(exportedPublicKeyJwk, publicKeyJwk); + }); + }); + + context("sign/verify", () => { + it("should sign and verify data", async () => { + const alg = { name: "ed25519" }; + const importedPrivateKey = await crypto.subtle.importKey("jwk", privateKeyJwk, alg, false, ["sign"]); + const importedPublicKey = await crypto.subtle.importKey("jwk", publicKeyJwk, alg, true, ["verify"]); + const data = Buffer.from("message"); + const signature = await crypto.subtle.sign(alg, importedPrivateKey, data); + const ok = await crypto.subtle.verify(alg, importedPublicKey, signature, data); + assert.ok(ok); + }); + }); + }); + }); + context("X25519", () => { + const privateKeyJwk = { + key_ops: ['deriveBits', 'deriveKey'], + ext: true, + crv: 'X25519', + d: 'AGHXWdGVQi8Is-A4uXYbfpTfDFwxGmJgCLFRHUjb0kM', + x: 'BLsolmWGd1aTexAd_O7MQnL9MpRPVKFO7t9k5Ri04lI', + kty: 'OKP' + }; + + const publicKeyJwk = { + key_ops: [], + ext: true, + crv: 'X25519', + x: 'BLsolmWGd1aTexAd_O7MQnL9MpRPVKFO7t9k5Ri04lI', + kty: 'OKP' + }; + + const derivedBitsBase64 = 'lWSsBfIyBlat6Q4vHS/MmKXN0Wraz7F82D8prcSRlHw='; + + context("generateKey", () => { + it("should generate key pair", async () => { + const alg = { name: "x25519" }; + const keys = await crypto.subtle.generateKey(alg, true, ["deriveBits", "deriveKey"]); + assert.ok("privateKey" in keys); + assert.ok("publicKey" in keys); + assert.strictEqual(keys.privateKey.algorithm.name, "X25519"); + assert.strictEqual(keys.privateKey.type, "private"); + assert.strictEqual(keys.privateKey.extractable, true); + assert.deepStrictEqual(keys.privateKey.usages, ["deriveBits", "deriveKey"]); + assert.strictEqual(keys.publicKey.algorithm.name, "X25519"); + assert.strictEqual(keys.publicKey.type, "public"); + assert.strictEqual(keys.publicKey.extractable, true); + assert.deepStrictEqual(keys.publicKey.usages, []); + }); + }); + + context("import/export", () => { + it("should correctly import and export private key", async () => { + const alg = { name: "x25519" }; + const importedPrivateKey = await crypto.subtle.importKey("jwk", privateKeyJwk, alg, true, ["deriveBits", "deriveKey"]); + const exportedPrivateKeyJwk = await crypto.subtle.exportKey("jwk", importedPrivateKey); + assert.deepStrictEqual(exportedPrivateKeyJwk, privateKeyJwk); + }); + + it("should correctly import and export public key", async () => { + const alg = { name: "x25519" }; + const importedPublicKey = await crypto.subtle.importKey("jwk", publicKeyJwk, alg, true, []); + const exportedPublicKeyJwk = await crypto.subtle.exportKey("jwk", importedPublicKey); + assert.deepStrictEqual(exportedPublicKeyJwk, publicKeyJwk); + }); + }); + + context("deriveBits", () => { + it("should derive bits", async () => { + const alg = { name: "x25519" }; + const importedPrivateKey = await crypto.subtle.importKey("jwk", privateKeyJwk, alg, false, ["deriveBits"]); + const importedPublicKey = await crypto.subtle.importKey("jwk", publicKeyJwk, alg, true, []); + const bits = await crypto.subtle.deriveBits({ name: "x25519", public: importedPublicKey } as EcdhKeyDeriveParams, importedPrivateKey, 256); + assert.strictEqual(Buffer.from(bits).toString("base64"), derivedBitsBase64); + }); + }); + }); }); diff --git a/yarn.lock b/yarn.lock index 0ae55df..f7fd764 100644 --- a/yarn.lock +++ b/yarn.lock @@ -21,7 +21,7 @@ dependencies: eslint-visitor-keys "^3.3.0" -"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": +"@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.6.1": version "4.10.0" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== @@ -61,9 +61,9 @@ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== "@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -153,80 +153,85 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rollup/rollup-android-arm-eabi@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.2.tgz#fbf098f49d96a8cac9056f22f5fd80906ef3af85" - integrity sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g== - -"@rollup/rollup-android-arm64@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.2.tgz#0d2448251040fce19a98eee505dff5b3c8ec9b98" - integrity sha512-GdxxXbAuM7Y/YQM9/TwwP+L0omeE/lJAR1J+olu36c3LqqZEBdsIWeQ91KBe6nxwOnb06Xh7JS2U5ooWU5/LgQ== - -"@rollup/rollup-darwin-arm64@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz#78db4d4da5b1b84c22adbe25c8a4961b3f22d3af" - integrity sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA== - -"@rollup/rollup-darwin-x64@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.2.tgz#fcc05af54379f8ee5c7e954987d4514c6fd0fb42" - integrity sha512-yUoEvnH0FBef/NbB1u6d3HNGyruAKnN74LrPAfDQL3O32e3k3OSfLrPgSJmgb3PJrBZWfPyt6m4ZhAFa2nZp2A== - -"@rollup/rollup-linux-arm-gnueabihf@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.2.tgz#2ce200efa1ef4a56ee2af7b453edc74a259d7d31" - integrity sha512-GYbLs5ErswU/Xs7aGXqzc3RrdEjKdmoCrgzhJWyFL0r5fL3qd1NPcDKDowDnmcoSiGJeU68/Vy+OMUluRxPiLQ== - -"@rollup/rollup-linux-arm64-gnu@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz#5a24aac882bff9abfda3f45f6f1db2166c342a4a" - integrity sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ== - -"@rollup/rollup-linux-arm64-musl@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.2.tgz#f1fb4c6f961d3f3397231a99e621d199200e4ea9" - integrity sha512-tK5eoKFkXdz6vjfkSTCupUzCo40xueTOiOO6PeEIadlNBkadH1wNOH8ILCPIl8by/Gmb5AGAeQOFeLev7iZDOA== - -"@rollup/rollup-linux-powerpc64le-gnu@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.13.2.tgz#46b2463d94ac3af3e0f7a2947b695397bc13b755" - integrity sha512-zvXvAUGGEYi6tYhcDmb9wlOckVbuD+7z3mzInCSTACJ4DQrdSLPNUeDIcAQW39M3q6PDquqLWu7pnO39uSMRzQ== - -"@rollup/rollup-linux-riscv64-gnu@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.2.tgz#47b932ee59a5395a3a341b0493e361d9e6032cf2" - integrity sha512-C3GSKvMtdudHCN5HdmAMSRYR2kkhgdOfye4w0xzyii7lebVr4riCgmM6lRiSCnJn2w1Xz7ZZzHKuLrjx5620kw== - -"@rollup/rollup-linux-s390x-gnu@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.13.2.tgz#8e14a1b3c3b9a4440c70a9c1ba12d32aa21f9712" - integrity sha512-l4U0KDFwzD36j7HdfJ5/TveEQ1fUTjFFQP5qIt9gBqBgu1G8/kCaq5Ok05kd5TG9F8Lltf3MoYsUMw3rNlJ0Yg== - -"@rollup/rollup-linux-x64-gnu@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz#270e939194b66df77bcb33dd9a5ddf7784bd7997" - integrity sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A== - -"@rollup/rollup-linux-x64-musl@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.2.tgz#e8dd0f3c2046acbda2934490b36552e856a3bc6a" - integrity sha512-M/JYAWickafUijWPai4ehrjzVPKRCyDb1SLuO+ZyPfoXgeCEAlgPkNXewFZx0zcnoIe3ay4UjXIMdXQXOZXWqA== - -"@rollup/rollup-win32-arm64-msvc@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.2.tgz#f8b65a4a7e7a6b383e7b14439129b2f474ff123c" - integrity sha512-2YWwoVg9KRkIKaXSh0mz3NmfurpmYoBBTAXA9qt7VXk0Xy12PoOP40EFuau+ajgALbbhi4uTj3tSG3tVseCjuA== - -"@rollup/rollup-win32-ia32-msvc@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.2.tgz#bc1c5a4fbc4337d6cb15da80a4de95fd53ab3573" - integrity sha512-2FSsE9aQ6OWD20E498NYKEQLneShWes0NGMPQwxWOdws35qQXH+FplabOSP5zEe1pVjurSDOGEVCE2agFwSEsw== - -"@rollup/rollup-win32-x64-msvc@4.13.2": - version "4.13.2" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.2.tgz#851959c4c1c3c6647aba1f388198c8243aed6917" - integrity sha512-7h7J2nokcdPePdKykd8wtc8QqqkqxIrUz7MHj6aNr8waBRU//NLDVnNjQnqQO6fqtjrtCdftpbTuOKAyrAQETQ== +"@rollup/rollup-android-arm-eabi@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz#1a32112822660ee104c5dd3a7c595e26100d4c2d" + integrity sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ== + +"@rollup/rollup-android-arm64@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz#5aeef206d65ff4db423f3a93f71af91b28662c5b" + integrity sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw== + +"@rollup/rollup-darwin-arm64@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz#6b66aaf003c70454c292cd5f0236ebdc6ffbdf1a" + integrity sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw== + +"@rollup/rollup-darwin-x64@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz#f64fc51ed12b19f883131ccbcea59fc68cbd6c0b" + integrity sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz#1a7641111be67c10111f7122d1e375d1226cbf14" + integrity sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A== + +"@rollup/rollup-linux-arm-musleabihf@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz#c93fd632923e0fee25aacd2ae414288d0b7455bb" + integrity sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg== + +"@rollup/rollup-linux-arm64-gnu@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz#fa531425dd21d058a630947527b4612d9d0b4a4a" + integrity sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A== + +"@rollup/rollup-linux-arm64-musl@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz#8acc16f095ceea5854caf7b07e73f7d1802ac5af" + integrity sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA== + +"@rollup/rollup-linux-powerpc64le-gnu@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz#94e69a8499b5cf368911b83a44bb230782aeb571" + integrity sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ== + +"@rollup/rollup-linux-riscv64-gnu@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz#7ef1c781c7e59e85a6ce261cc95d7f1e0b56db0f" + integrity sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg== + +"@rollup/rollup-linux-s390x-gnu@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz#f15775841c3232fca9b78cd25a7a0512c694b354" + integrity sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g== + +"@rollup/rollup-linux-x64-gnu@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz#b521d271798d037ad70c9f85dd97d25f8a52e811" + integrity sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ== + +"@rollup/rollup-linux-x64-musl@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz#9254019cc4baac35800991315d133cc9fd1bf385" + integrity sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q== + +"@rollup/rollup-win32-arm64-msvc@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz#27f65a89f6f52ee9426ec11e3571038e4671790f" + integrity sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA== + +"@rollup/rollup-win32-ia32-msvc@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz#a2fbf8246ed0bb014f078ca34ae6b377a90cb411" + integrity sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ== + +"@rollup/rollup-win32-x64-msvc@4.17.2": + version "4.17.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz#5a2d08b81e8064b34242d5cc9973ef8dd1e60503" + integrity sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w== "@tsconfig/node10@^1.0.7": version "1.0.8" @@ -253,11 +258,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== -"@types/json-schema@^7.0.12": - version "7.0.15" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" - integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== - "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" @@ -268,103 +268,93 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.6.tgz#818551d39113081048bdddbef96701b4e8bb9d1b" integrity sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg== -"@types/node@^20.11.30": - version "20.11.30" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.30.tgz#9c33467fc23167a347e73834f788f4b9f399d66f" - integrity sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw== +"@types/node@^20.12.12": + version "20.12.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" + integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== dependencies: undici-types "~5.26.4" -"@types/semver@^7.5.0": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - -"@typescript-eslint/eslint-plugin@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz#de61c3083842fc6ac889d2fc83c9a96b55ab8328" - integrity sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw== - dependencies: - "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/type-utils" "7.4.0" - "@typescript-eslint/utils" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" - debug "^4.3.4" +"@typescript-eslint/eslint-plugin@^7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz#07854a236f107bb45cbf4f62b89474cbea617f50" + integrity sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw== + dependencies: + "@eslint-community/regexpp" "^4.10.0" + "@typescript-eslint/scope-manager" "7.10.0" + "@typescript-eslint/type-utils" "7.10.0" + "@typescript-eslint/utils" "7.10.0" + "@typescript-eslint/visitor-keys" "7.10.0" graphemer "^1.4.0" - ignore "^5.2.4" + ignore "^5.3.1" natural-compare "^1.4.0" - semver "^7.5.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" -"@typescript-eslint/parser@^7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.4.0.tgz#540f4321de1e52b886c0fa68628af1459954c1f1" - integrity sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ== +"@typescript-eslint/parser@^7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.10.0.tgz#e6ac1cba7bc0400a4459e7eb5b23115bd71accfb" + integrity sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w== dependencies: - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/typescript-estree" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/scope-manager" "7.10.0" + "@typescript-eslint/types" "7.10.0" + "@typescript-eslint/typescript-estree" "7.10.0" + "@typescript-eslint/visitor-keys" "7.10.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz#acfc69261f10ece7bf7ece1734f1713392c3655f" - integrity sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw== +"@typescript-eslint/scope-manager@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz#054a27b1090199337a39cf755f83d9f2ce26546b" + integrity sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg== dependencies: - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/types" "7.10.0" + "@typescript-eslint/visitor-keys" "7.10.0" -"@typescript-eslint/type-utils@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz#cfcaab21bcca441c57da5d3a1153555e39028cbd" - integrity sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw== +"@typescript-eslint/type-utils@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz#8a75accce851d0a331aa9331268ef64e9b300270" + integrity sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g== dependencies: - "@typescript-eslint/typescript-estree" "7.4.0" - "@typescript-eslint/utils" "7.4.0" + "@typescript-eslint/typescript-estree" "7.10.0" + "@typescript-eslint/utils" "7.10.0" debug "^4.3.4" - ts-api-utils "^1.0.1" + ts-api-utils "^1.3.0" -"@typescript-eslint/types@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6" - integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw== +"@typescript-eslint/types@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.10.0.tgz#da92309c97932a3a033762fd5faa8b067de84e3b" + integrity sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg== -"@typescript-eslint/typescript-estree@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz#12dbcb4624d952f72c10a9f4431284fca24624f4" - integrity sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg== +"@typescript-eslint/typescript-estree@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz#6dcdc5de3149916a6a599fa89dde5c471b88b8bb" + integrity sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g== dependencies: - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/types" "7.10.0" + "@typescript-eslint/visitor-keys" "7.10.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - minimatch "9.0.3" - semver "^7.5.4" - ts-api-utils "^1.0.1" + minimatch "^9.0.4" + semver "^7.6.0" + ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.4.0.tgz#d889a0630cab88bddedaf7c845c64a00576257bd" - integrity sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg== +"@typescript-eslint/utils@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.10.0.tgz#8ee43e5608c9f439524eaaea8de5b358b15c51b3" + integrity sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.12" - "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.4.0" - "@typescript-eslint/types" "7.4.0" - "@typescript-eslint/typescript-estree" "7.4.0" - semver "^7.5.4" + "@typescript-eslint/scope-manager" "7.10.0" + "@typescript-eslint/types" "7.10.0" + "@typescript-eslint/typescript-estree" "7.10.0" -"@typescript-eslint/visitor-keys@7.4.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz#0c8ff2c1f8a6fe8d7d1a57ebbd4a638e86a60a94" - integrity sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA== +"@typescript-eslint/visitor-keys@7.10.0": + version "7.10.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz#2af2e91e73a75dd6b70b4486c48ae9d38a485a78" + integrity sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg== dependencies: - "@typescript-eslint/types" "7.4.0" - eslint-visitor-keys "^3.4.1" + "@typescript-eslint/types" "7.10.0" + eslint-visitor-keys "^3.4.3" "@ungap/structured-clone@^1.2.0": version "1.2.0" @@ -1261,7 +1251,7 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -ignore@^5.2.0, ignore@^5.2.4: +ignore@^5.2.0, ignore@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== @@ -1586,13 +1576,6 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@9.0.3, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1607,6 +1590,20 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.6: version "1.2.6" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz" @@ -1896,10 +1893,10 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" - integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== +rimraf@^5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" + integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== dependencies: glob "^10.3.7" @@ -1914,28 +1911,29 @@ rollup-plugin-typescript2@^0.36.0: semver "^7.5.4" tslib "^2.6.2" -rollup@^4.13.2: - version "4.13.2" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.13.2.tgz#ac57d2dc48e8f5562f5a6daadb9caee590069262" - integrity sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g== +rollup@^4.17.2: + version "4.17.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.17.2.tgz#26d1785d0144122277fdb20ab3a24729ae68301f" + integrity sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ== dependencies: "@types/estree" "1.0.5" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.13.2" - "@rollup/rollup-android-arm64" "4.13.2" - "@rollup/rollup-darwin-arm64" "4.13.2" - "@rollup/rollup-darwin-x64" "4.13.2" - "@rollup/rollup-linux-arm-gnueabihf" "4.13.2" - "@rollup/rollup-linux-arm64-gnu" "4.13.2" - "@rollup/rollup-linux-arm64-musl" "4.13.2" - "@rollup/rollup-linux-powerpc64le-gnu" "4.13.2" - "@rollup/rollup-linux-riscv64-gnu" "4.13.2" - "@rollup/rollup-linux-s390x-gnu" "4.13.2" - "@rollup/rollup-linux-x64-gnu" "4.13.2" - "@rollup/rollup-linux-x64-musl" "4.13.2" - "@rollup/rollup-win32-arm64-msvc" "4.13.2" - "@rollup/rollup-win32-ia32-msvc" "4.13.2" - "@rollup/rollup-win32-x64-msvc" "4.13.2" + "@rollup/rollup-android-arm-eabi" "4.17.2" + "@rollup/rollup-android-arm64" "4.17.2" + "@rollup/rollup-darwin-arm64" "4.17.2" + "@rollup/rollup-darwin-x64" "4.17.2" + "@rollup/rollup-linux-arm-gnueabihf" "4.17.2" + "@rollup/rollup-linux-arm-musleabihf" "4.17.2" + "@rollup/rollup-linux-arm64-gnu" "4.17.2" + "@rollup/rollup-linux-arm64-musl" "4.17.2" + "@rollup/rollup-linux-powerpc64le-gnu" "4.17.2" + "@rollup/rollup-linux-riscv64-gnu" "4.17.2" + "@rollup/rollup-linux-s390x-gnu" "4.17.2" + "@rollup/rollup-linux-x64-gnu" "4.17.2" + "@rollup/rollup-linux-x64-musl" "4.17.2" + "@rollup/rollup-win32-arm64-msvc" "4.17.2" + "@rollup/rollup-win32-ia32-msvc" "4.17.2" + "@rollup/rollup-win32-x64-msvc" "4.17.2" fsevents "~2.3.2" run-parallel@^1.1.9: @@ -1981,6 +1979,11 @@ semver@^7.5.4: dependencies: lru-cache "^6.0.0" +semver@^7.6.0: + version "7.6.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" + integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + serialize-javascript@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" @@ -2139,7 +2142,7 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -ts-api-utils@^1.0.1: +ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== @@ -2229,10 +2232,10 @@ typed-array-length@^1.0.4: for-each "^0.3.3" is-typed-array "^1.1.9" -typescript@^5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" - integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== +typescript@^5.4.5: + version "5.4.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" + integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== unbox-primitive@^1.0.2: version "1.0.2" @@ -2266,10 +2269,10 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== -webcrypto-core@^1.7.9: - version "1.7.9" - resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.9.tgz#a585f0032dbc88d202cff4f266cbef02ba48bd7a" - integrity sha512-FE+a4PPkOmBbgNDIyRmcHhgXn+2ClRl3JzJdDu/P4+B8y81LqKe6RAsI9b3lAOHe1T1BMkSjsRHTYRikImZnVA== +webcrypto-core@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.0.tgz#aaea17f3dd9c77c304e3c494eb27ca07cc72ca37" + integrity sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw== dependencies: "@peculiar/asn1-schema" "^2.3.8" "@peculiar/json-schema" "^1.1.12"