diff --git a/.eslintrc.json b/.eslintrc.json index 25f3e91..7fcb74a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -23,12 +23,19 @@ "@typescript-eslint/semi": 1, "@typescript-eslint/explicit-module-boundary-types": 0, "semi": "off", - "import/order": ["error", { - "groups": ["builtin", "external", "internal"], - "alphabetize": { - "order": "asc", - "caseInsensitive": true + "import/order": [ + "error", + { + "groups": [ + "builtin", + "external", + "internal" + ], + "alphabetize": { + "order": "asc", + "caseInsensitive": true + } } - }] + ] } } \ No newline at end of file diff --git a/.mocharc.yml b/.mocharc.yml new file mode 100644 index 0000000..71b066d --- /dev/null +++ b/.mocharc.yml @@ -0,0 +1,8 @@ +require: + - "tsconfig-paths/register" + - "ts-node/register" +extension: + - ts +spec: + - "packages/**/*.ts" +exit: true diff --git a/LICENSE.md b/LICENSE.md index 1eb26e2..7b3b056 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 Peculiar Ventures, LLC +Copyright (c) 2016-2022 Peculiar Ventures, LLC Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 186a7e5..0000000 --- a/index.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export declare class Crypto implements globalThis.Crypto { - public subtle: SubtleCrypto; - public getRandomValues(array: T): T; - public randomUUID(): string; -} - -export declare class CryptoKey implements globalThis.CryptoKey { - public algorithm: KeyAlgorithm; - public extractable: boolean; - public type: KeyType; - public usages: KeyUsage[]; -} diff --git a/lerna.json b/lerna.json new file mode 100644 index 0000000..24ee665 --- /dev/null +++ b/lerna.json @@ -0,0 +1,13 @@ +{ + "npmClient": "yarn", + "packages": [ + "packages/*" + ], + "version": "3.0.0", + "useWorkspaces": true, + "command": { + "publish": { + "registry": "https://npm.pkg.github.com/" + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index f0ffbdf..2efa0ea 100644 --- a/package.json +++ b/package.json @@ -1,106 +1,42 @@ { - "name": "@peculiar/webcrypto", - "version": "1.4.0", - "description": "A WebCrypto Polyfill for NodeJS", - "repository": { - "type": "git", - "url": "https://github.com/PeculiarVentures/webcrypto.git" - }, - "files": [ - "build/**/*.{ts,js}", - "index.d.ts", - "README.md", - "LICENSE.md" + "name": "webcrypto", + "private": true, + "description": "", + "workspaces": [ + "packages/*" ], - "main": "build/webcrypto.js", - "module": "build/webcrypto.es.js", - "types": "index.d.ts", "scripts": { "test": "mocha", - "coverage": "nyc npm test", - "coveralls": "nyc report --reporter=text-lcov | coveralls", - "build": "rollup -c", - "clear": "rimraf build/*", - "rebuild": "npm run clear && npm run build", - "lint": "eslint . --ext .ts", - "lint:fix": "eslint --fix . --ext .ts" + "lint": "eslint .", + "lint:fix": "eslint . --fix", + "build": "lerna run build", + "rebuild": "lerna run rebuild", + "pack": "lerna exec npm pack", + "clear": "lerna run clear", + "upgrade": "yarn upgrade-interactive --latest" }, - "keywords": [ - "webcrypto", - "crypto", - "sha", - "rsa", - "ec", - "aes", - "des", - "hmac", - "pbkdf2", - "eddsa", - "x25519", - "ed25519", - "x448", - "ed448", - "shake128", - "shake256" - ], - "author": "PeculiarVentures", - "contributors": [ - "Miroshin Stepan" - ], + "repository": { + "type": "git", + "url": "git+https://github.com/PeculiarVentures/webcrypto.git" + }, + "author": "", "license": "MIT", "bugs": { "url": "https://github.com/PeculiarVentures/webcrypto/issues" }, "homepage": "https://github.com/PeculiarVentures/webcrypto#readme", "devDependencies": { - "@peculiar/webcrypto-test": "^1.0.7", "@types/mocha": "^9.1.1", - "@types/node": "^17.0.32", - "@typescript-eslint/eslint-plugin": "^5.23.0", - "@typescript-eslint/parser": "^5.23.0", - "coveralls": "^3.1.1", - "eslint": "^8.15.0", - "eslint-plugin-import": "^2.26.0", - "mocha": "^10.0.0", - "nyc": "^15.1.0", - "rimraf": "^3.0.2", - "rollup": "^2.72.1", + "@types/node": "^17.0.27", + "@typescript-eslint/eslint-plugin": "^5.21.0", + "@typescript-eslint/parser": "^5.21.0", + "eslint": "^8.14.0", + "mocha": "^9.2.2", + "rollup": "^2.70.2", + "rollup-plugin-dts": "^4.2.1", "rollup-plugin-typescript2": "^0.31.2", "ts-node": "^10.7.0", - "typescript": "^4.6.4" - }, - "dependencies": { - "@peculiar/asn1-schema": "^2.1.6", - "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.0", - "webcrypto-core": "^1.7.4" - }, - "nyc": { - "extension": [ - ".ts", - ".tsx" - ], - "include": [ - "src/**/*.ts" - ], - "exclude": [ - "**/*.d.ts" - ], - "reporter": [ - "lcov", - "text-summary", - "html" - ] - }, - "engines": { - "node": ">=10.12.0" - }, - "mocha": { - "require": "ts-node/register", - "extension": [ - "ts" - ], - "spec": "test/**/*.ts" + "tsconfig-paths": "^3.14.1", + "typescript": "^4.6.3" } } diff --git a/packages/core/README.md b/packages/core/README.md new file mode 100644 index 0000000..5797bcc --- /dev/null +++ b/packages/core/README.md @@ -0,0 +1,11 @@ +# `@peculiar/webcypto-core` + +> TODO: description + +## Usage + +``` +const webcyptoCore = require('@peculiar/webcypto-core'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/core/package.json b/packages/core/package.json new file mode 100644 index 0000000..1f2d2bd --- /dev/null +++ b/packages/core/package.json @@ -0,0 +1,50 @@ +{ + "name": "@peculiar/webcrypto-core", + "version": "3.0.0", + "description": "Common layer to be used by crypto libraries based on WebCrypto API for input validation.", + "author": "PeculiarVentures", + "contributors": [ + "Miroshin Stepan" + ], + "homepage": "https://github.com/PeculiarVentures/webcrypto/tree/master/packages/core#readme", + "license": "MIT", + "main": "build/index.js", + "module": "build/index.es.js", + "types": "build/index.d.ts", + "files": [ + "build", + "README.md", + "LICENSE" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/PeculiarVentures/webcrypto.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/PeculiarVentures/webcrypto/issues" + }, + "keywords": [ + "webcrypto", + "crypto", + "polyfill", + "aes", + "rsa", + "sha", + "sha3", + "ec", + "shake" + ], + "dependencies": { + "@peculiar/asn1-schema": "^2.1.7", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/webcrypto-types": "^3.0.0", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } +} \ No newline at end of file diff --git a/packages/core/src/aes/base.ts b/packages/core/src/aes/base.ts new file mode 100644 index 0000000..76f11fc --- /dev/null +++ b/packages/core/src/aes/base.ts @@ -0,0 +1,31 @@ +import * as types from "@peculiar/webcrypto-types"; +import { ProviderCrypto } from "../provider"; +import { BaseCryptoKey } from "../crypto_key"; + +export abstract class AesProvider extends ProviderCrypto { + + public override checkGenerateKeyParams(algorithm: types.AesKeyGenParams) { + // length + this.checkRequiredProperty(algorithm, "length"); + if (typeof algorithm.length !== "number") { + throw new TypeError("length: Is not of type Number"); + } + switch (algorithm.length) { + case 128: + case 192: + case 256: + break; + default: + throw new TypeError("length: Must be 128, 192, or 256"); + } + } + + public override checkDerivedKeyParams(algorithm: types.AesKeyGenParams) { + this.checkGenerateKeyParams(algorithm); + } + + public abstract override onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onExportKey(format: types.KeyFormat, key: BaseCryptoKey, ...args: any[]): Promise; + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/cbc.ts b/packages/core/src/aes/cbc.ts new file mode 100644 index 0000000..8bddc8d --- /dev/null +++ b/packages/core/src/aes/cbc.ts @@ -0,0 +1,23 @@ +import * as types from "@peculiar/webcrypto-types"; +import { AesProvider } from "./base"; + +export abstract class AesCbcProvider extends AesProvider { + + public readonly name = "AES-CBC"; + + public usages: types.KeyUsages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public override checkAlgorithmParams(algorithm: types.AesCbcParams) { + this.checkRequiredProperty(algorithm, "iv"); + if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) { + throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + if (algorithm.iv.byteLength !== 16) { + throw new TypeError("iv: Must have length 16 bytes"); + } + } + + public abstract override onEncrypt(algorithm: types.AesCbcParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: types.AesCbcParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/cmac.ts b/packages/core/src/aes/cmac.ts new file mode 100644 index 0000000..63df4e7 --- /dev/null +++ b/packages/core/src/aes/cmac.ts @@ -0,0 +1,24 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { AesProvider } from "./base"; + +export abstract class AesCmacProvider extends AesProvider { + + public readonly name = "AES-CMAC"; + + public usages: types.KeyUsages = ["sign", "verify"]; + + public override checkAlgorithmParams(algorithm: types.AesCmacParams) { + this.checkRequiredProperty(algorithm, "length"); + if (typeof algorithm.length !== "number") { + throw new TypeError("length: Is not a Number"); + } + if (algorithm.length < 1) { + throw new OperationError("length: Must be more than 0"); + } + } + + public abstract override onSign(algorithm: types.AesCmacParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onVerify(algorithm: types.AesCmacParams, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/ctr.ts b/packages/core/src/aes/ctr.ts new file mode 100644 index 0000000..b1e29ca --- /dev/null +++ b/packages/core/src/aes/ctr.ts @@ -0,0 +1,33 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { AesProvider } from "./base"; + +export abstract class AesCtrProvider extends AesProvider { + + public readonly name = "AES-CTR"; + + public usages: types.KeyUsages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public override checkAlgorithmParams(algorithm: types.AesCtrParams) { + // counter + this.checkRequiredProperty(algorithm, "counter"); + if (!(algorithm.counter instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.counter))) { + throw new TypeError("counter: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + if (algorithm.counter.byteLength !== 16) { + throw new TypeError("iv: Must have length 16 bytes"); + } + // length + this.checkRequiredProperty(algorithm, "length"); + if (typeof algorithm.length !== "number") { + throw new TypeError("length: Is not a Number"); + } + if (algorithm.length < 1) { + throw new OperationError("length: Must be more than 0"); + } + } + + public abstract override onEncrypt(algorithm: types.AesCtrParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: types.AesCtrParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/ecb.ts b/packages/core/src/aes/ecb.ts new file mode 100644 index 0000000..5c85531 --- /dev/null +++ b/packages/core/src/aes/ecb.ts @@ -0,0 +1,13 @@ +import * as types from "@peculiar/webcrypto-types"; +import { AesProvider } from "./base"; + +export abstract class AesEcbProvider extends AesProvider { + + public readonly name = "AES-ECB"; + + public usages: types.KeyUsages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public abstract override onEncrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/gsm.ts b/packages/core/src/aes/gsm.ts new file mode 100644 index 0000000..ffc2c40 --- /dev/null +++ b/packages/core/src/aes/gsm.ts @@ -0,0 +1,41 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { AesProvider } from "./base"; + +export abstract class AesGcmProvider extends AesProvider { + + public readonly name = "AES-GCM"; + + public usages: types.KeyUsages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public override checkAlgorithmParams(algorithm: types.AesGcmParams) { + // iv + this.checkRequiredProperty(algorithm, "iv"); + if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) { + throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + if (algorithm.iv.byteLength < 1) { + throw new OperationError("iv: Must have length more than 0 and less than 2^64 - 1"); + } + // tagLength + if (!("tagLength" in algorithm)) { + algorithm.tagLength = 128; + } + switch (algorithm.tagLength) { + case 32: + case 64: + case 96: + case 104: + case 112: + case 120: + case 128: + break; + default: + throw new OperationError("tagLength: Must be one of 32, 64, 96, 104, 112, 120 or 128"); + } + } + + public abstract override onEncrypt(algorithm: types.AesGcmParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: types.AesGcmParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/aes/index.ts b/packages/core/src/aes/index.ts new file mode 100644 index 0000000..0955b47 --- /dev/null +++ b/packages/core/src/aes/index.ts @@ -0,0 +1,7 @@ +export * from "./base"; +export * from "./cbc"; +export * from "./cmac"; +export * from "./ctr"; +export * from "./ecb"; +export * from "./gsm"; +export * from "./kw"; diff --git a/packages/core/src/aes/kw.ts b/packages/core/src/aes/kw.ts new file mode 100644 index 0000000..7f48de4 --- /dev/null +++ b/packages/core/src/aes/kw.ts @@ -0,0 +1,10 @@ +import * as types from "@peculiar/webcrypto-types"; +import { AesProvider } from "./base"; + +export abstract class AesKwProvider extends AesProvider { + + public readonly name = "AES-KW"; + + public usages: types.KeyUsages = ["wrapKey", "unwrapKey"]; + +} diff --git a/packages/core/src/crypto.ts b/packages/core/src/crypto.ts new file mode 100644 index 0000000..7e4ef0b --- /dev/null +++ b/packages/core/src/crypto.ts @@ -0,0 +1,25 @@ +import { Convert } from "pvtsutils"; +import { SubtleCrypto } from "./subtle"; +import * as types from "@peculiar/webcrypto-types"; + +export abstract class Crypto implements types.Crypto { + + public abstract readonly subtle: SubtleCrypto; + + // @internal + public get [Symbol.toStringTag]() { + return "Crypto"; + } + + public abstract getRandomValues(array: T): T; + + public randomUUID(): string { + const b = this.getRandomValues(new Uint8Array(16)); + b[6] = (b[6] & 0x0f) | 0x40; + b[8] = (b[8] & 0x3f) | 0x80; + const uuid = Convert.ToHex(b).toLowerCase(); + + return `${uuid.substring(0, 8)}-${uuid.substring(8, 12)}-${uuid.substring(12, 16)}-${uuid.substring(16)}`; + } + +} diff --git a/packages/core/src/crypto_key.ts b/packages/core/src/crypto_key.ts new file mode 100644 index 0000000..741d6e8 --- /dev/null +++ b/packages/core/src/crypto_key.ts @@ -0,0 +1,30 @@ +import * as types from "@peculiar/webcrypto-types"; + +const KEY_TYPES = ["secret", "private", "public"]; + +export class BaseCryptoKey implements types.CryptoKey { + + public static create(this: new () => T, algorithm: types.KeyAlgorithm, type: types.KeyType, extractable: boolean, usages: types.KeyUsages): T { + const key = new this(); + key.algorithm = algorithm; + key.type = type; + key.extractable = extractable; + key.usages = usages; + + return key; + } + + public static isKeyType(data: any): data is types.KeyType { + return KEY_TYPES.indexOf(data) !== -1; + } + + public algorithm!: types.KeyAlgorithm; + public type!: types.KeyType; + public usages!: types.KeyUsages; + public extractable!: boolean; + + // @internal + public get [Symbol.toStringTag]() { + return "CryptoKey"; + } +} diff --git a/packages/core/src/des/base.ts b/packages/core/src/des/base.ts new file mode 100644 index 0000000..5844265 --- /dev/null +++ b/packages/core/src/des/base.ts @@ -0,0 +1,65 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; +import { BufferSource } from "pvtsutils"; + +export interface DesKeyAlgorithm extends types.KeyAlgorithm { + length: number; +} + +export interface DesParams extends types.Algorithm { + iv: BufferSource; +} + +export interface DesKeyGenParams extends types.Algorithm { + length: number; +} + +export interface DesDerivedKeyParams extends types.Algorithm { + length: number; +} + +export interface DesImportParams extends types.Algorithm { } + +export abstract class DesProvider extends ProviderCrypto { + + public usages: types.KeyUsages = ["encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public abstract keySizeBits: number; + public abstract ivSize: number; + + public override checkAlgorithmParams(algorithm: types.AesCbcParams) { + if (this.ivSize) { + this.checkRequiredProperty(algorithm, "iv"); + if (!(algorithm.iv instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.iv))) { + throw new TypeError("iv: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + if (algorithm.iv.byteLength !== this.ivSize) { + throw new TypeError(`iv: Must have length ${this.ivSize} bytes`); + } + } + } + + public override checkGenerateKeyParams(algorithm: DesKeyGenParams) { + // length + this.checkRequiredProperty(algorithm, "length"); + if (typeof algorithm.length !== "number") { + throw new TypeError("length: Is not of type Number"); + } + if (algorithm.length !== this.keySizeBits) { + throw new OperationError(`algorithm.length: Must be ${this.keySizeBits}`); + } + } + + public override checkDerivedKeyParams(algorithm: DesDerivedKeyParams) { + this.checkGenerateKeyParams(algorithm); + } + + public abstract override onGenerateKey(algorithm: DesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onExportKey(format: types.KeyFormat, key: BaseCryptoKey, ...args: any[]): Promise; + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: DesImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onEncrypt(algorithm: DesParams, key: BaseCryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: DesParams, key: BaseCryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/des/index.ts b/packages/core/src/des/index.ts new file mode 100644 index 0000000..955fdd1 --- /dev/null +++ b/packages/core/src/des/index.ts @@ -0,0 +1 @@ +export * from "./base"; diff --git a/packages/core/src/ec/base.ts b/packages/core/src/ec/base.ts new file mode 100644 index 0000000..bb50464 --- /dev/null +++ b/packages/core/src/ec/base.ts @@ -0,0 +1,29 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; + +export abstract class EllipticProvider extends ProviderCrypto { + + public abstract namedCurves: string[]; + + public override checkGenerateKeyParams(algorithm: types.EcKeyGenParams) { + // named curve + this.checkRequiredProperty(algorithm, "namedCurve"); + this.checkNamedCurve(algorithm.namedCurve); + } + + public checkNamedCurve(namedCurve: string) { + for (const item of this.namedCurves) { + if (item.toLowerCase() === namedCurve.toLowerCase()) { + return; + } + } + throw new OperationError(`namedCurve: Must be one of ${this.namedCurves.join(", ")}`); + } + + public abstract override onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onExportKey(format: types.KeyFormat, key: BaseCryptoKey, ...args: any[]): Promise; + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + +} diff --git a/packages/core/src/ec/curves.ts b/packages/core/src/ec/curves.ts new file mode 100644 index 0000000..c4197cc --- /dev/null +++ b/packages/core/src/ec/curves.ts @@ -0,0 +1,81 @@ +import { AsnConvert } from "@peculiar/asn1-schema"; +import * as schema from "packages/core/src/schema"; + +export interface EcCurveParams { + /** + * The name of the curve + */ + name: string; + /** + * The object identifier of the curve + */ + id: string; + /** + * Curve point size in bits + */ + size: number; +} + +export interface EcCurve extends EcCurveParams { + raw: ArrayBuffer; +} + +export class EcCurves { + + protected static items: EcCurve[] = []; + public static readonly names: string[] = []; + + private constructor() { } + + public static register(item: EcCurveParams) { + const oid = new schema.ObjectIdentifier(); + oid.value = item.id; + const raw = AsnConvert.serialize(oid); + + this.items.push({ + ...item, + raw, + }); + this.names.push(item.name); + } + + public static find(nameOrId: string): EcCurve | null { + nameOrId = nameOrId.toUpperCase(); + for (const item of this.items) { + if (item.name.toUpperCase() === nameOrId || item.id.toUpperCase() === nameOrId) { + return item; + } + } + + return null; + } + + public static get(nameOrId: string): EcCurve { + const res = this.find(nameOrId); + if (!res) { + throw new Error(`Unsupported EC named curve '${nameOrId}'`); + } + + return res; + } + +} + +EcCurves.register({ name: "P-256", id: schema.idSecp256r1, size: 256 }); +EcCurves.register({ name: "P-384", id: schema.idSecp384r1, size: 384 }); +EcCurves.register({ name: "P-521", id: schema.idSecp521r1, size: 521 }); +EcCurves.register({ name: "K-256", id: schema.idSecp256k1, size: 256 }); +EcCurves.register({ name: "brainpoolP160r1", id: schema.idBrainpoolP160r1, size: 160 }); +EcCurves.register({ name: "brainpoolP160t1", id: schema.idBrainpoolP160t1, size: 160 }); +EcCurves.register({ name: "brainpoolP192r1", id: schema.idBrainpoolP192r1, size: 192 }); +EcCurves.register({ name: "brainpoolP192t1", id: schema.idBrainpoolP192t1, size: 192 }); +EcCurves.register({ name: "brainpoolP224r1", id: schema.idBrainpoolP224r1, size: 224 }); +EcCurves.register({ name: "brainpoolP224t1", id: schema.idBrainpoolP224t1, size: 224 }); +EcCurves.register({ name: "brainpoolP256r1", id: schema.idBrainpoolP256r1, size: 256 }); +EcCurves.register({ name: "brainpoolP256t1", id: schema.idBrainpoolP256t1, size: 256 }); +EcCurves.register({ name: "brainpoolP320r1", id: schema.idBrainpoolP320r1, size: 320 }); +EcCurves.register({ name: "brainpoolP320t1", id: schema.idBrainpoolP320t1, size: 320 }); +EcCurves.register({ name: "brainpoolP384r1", id: schema.idBrainpoolP384r1, size: 384 }); +EcCurves.register({ name: "brainpoolP384t1", id: schema.idBrainpoolP384t1, size: 384 }); +EcCurves.register({ name: "brainpoolP512r1", id: schema.idBrainpoolP512r1, size: 512 }); +EcCurves.register({ name: "brainpoolP512t1", id: schema.idBrainpoolP512t1, size: 512 }); diff --git a/packages/core/src/ec/ecdh.ts b/packages/core/src/ec/ecdh.ts new file mode 100644 index 0000000..ea57478 --- /dev/null +++ b/packages/core/src/ec/ecdh.ts @@ -0,0 +1,33 @@ +import * as types from "@peculiar/webcrypto-types"; +import { OperationError } from "../errors"; +import { BaseCryptoKey } from "../crypto_key"; +import { EllipticProvider } from "./base"; + +export abstract class EcdhProvider extends EllipticProvider { + + public readonly name: string = "ECDH"; + + public usages: types.ProviderKeyUsages = { + privateKey: ["deriveBits", "deriveKey"], + publicKey: [], + }; + + public namedCurves = ["P-256", "P-384", "P-521", "K-256"]; + + public override checkAlgorithmParams(algorithm: types.EcdhKeyDeriveParams) { + // public + this.checkRequiredProperty(algorithm, "public"); + if (!(algorithm.public instanceof BaseCryptoKey)) { + throw new TypeError("public: Is not a CryptoKey"); + } + if (algorithm.public.type !== "public") { + throw new OperationError("public: Is not a public key"); + } + if (algorithm.public.algorithm.name !== this.name) { + throw new OperationError(`public: Is not ${this.name} key`); + } + } + + public abstract override onDeriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: BaseCryptoKey, length: number, ...args: any[]): Promise; + +} diff --git a/packages/core/src/ec/ecdh_es.ts b/packages/core/src/ec/ecdh_es.ts new file mode 100644 index 0000000..a025e7a --- /dev/null +++ b/packages/core/src/ec/ecdh_es.ts @@ -0,0 +1,7 @@ +import { EcdhProvider } from "./ecdh"; + +export abstract class EcdhEsProvider extends EcdhProvider { + public override readonly name: string = "ECDH-ES"; + + public override namedCurves = ["X25519", "X448"]; +} \ No newline at end of file diff --git a/packages/core/src/ec/ecdsa.ts b/packages/core/src/ec/ecdsa.ts new file mode 100644 index 0000000..ad9026d --- /dev/null +++ b/packages/core/src/ec/ecdsa.ts @@ -0,0 +1,25 @@ +import { Algorithm, CryptoKey, EcdsaParams, ProviderKeyUsages } from "@peculiar/webcrypto-types"; +import { EllipticProvider } from "./base"; + +export abstract class EcdsaProvider extends EllipticProvider { + + public readonly name: string = "ECDSA"; + + public readonly hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; + + public usages: ProviderKeyUsages = { + privateKey: ["sign"], + publicKey: ["verify"], + }; + + public namedCurves = ["P-256", "P-384", "P-521", "K-256"]; + + public override checkAlgorithmParams(algorithm: EcdsaParams) { + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as Algorithm, this.hashAlgorithms); + } + + public abstract override onSign(algorithm: EcdsaParams, key: CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onVerify(algorithm: EcdsaParams, key: CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/ec/eddsa.ts b/packages/core/src/ec/eddsa.ts new file mode 100644 index 0000000..6836fe6 --- /dev/null +++ b/packages/core/src/ec/eddsa.ts @@ -0,0 +1,18 @@ +import { CryptoKey, EcdsaParams, ProviderKeyUsages } from "@peculiar/webcrypto-types"; +import { EllipticProvider } from "./base"; + +export abstract class EdDsaProvider extends EllipticProvider { + + public readonly name: string = "EdDSA"; + + public usages: ProviderKeyUsages = { + privateKey: ["sign"], + publicKey: ["verify"], + }; + + public namedCurves = ["Ed25519", "Ed448"]; + + public abstract override onSign(algorithm: EcdsaParams, key: CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onVerify(algorithm: EcdsaParams, key: CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/ec/index.ts b/packages/core/src/ec/index.ts new file mode 100644 index 0000000..78ed944 --- /dev/null +++ b/packages/core/src/ec/index.ts @@ -0,0 +1,7 @@ +export * from "./base"; +export * from "./ecdsa"; +export * from "./ecdh"; +export * from "./ecdh_es"; +export * from "./eddsa"; +export * from "./curves"; +export * from "./utils"; diff --git a/packages/core/src/ec/utils.ts b/packages/core/src/ec/utils.ts new file mode 100644 index 0000000..54241a1 --- /dev/null +++ b/packages/core/src/ec/utils.ts @@ -0,0 +1,121 @@ +import { BufferSource, BufferSourceConverter } from "pvtsutils"; + +interface EcPoint { + x: BufferSource; + y: BufferSource; +} + +interface EcSignaturePoint { + r: BufferSource; + s: BufferSource; +} + +export class EcUtils { + + /** + * Decodes ANSI X9.62 encoded point + * @note Used by SunPKCS11 and SunJSSE + * @param data ANSI X9.62 encoded point + * @param pointSize Size of the point in bits + * @returns Decoded point with x and y coordinates + */ + public static decodePoint(data: BufferSource, pointSize: number): EcPoint { + const view = BufferSourceConverter.toUint8Array(data); + if ((view.length === 0) || (view[0] !== 4)) { + throw new Error("Only uncompressed point format supported"); + } + // Per ANSI X9.62, an encoded point is a 1 byte type followed by + // ceiling(log base 2 field-size / 8) bytes of x and the same of y. + const n = (view.length - 1) / 2; + if (n !== (Math.ceil(pointSize / 8))) { + throw new Error("Point does not match field size"); + } + + const xb = view.slice(1, n + 1); + const yb = view.slice(n + 1, n + 1 + n); + + return { x: xb, y: yb }; + } + + /** + * Encodes EC point to ANSI X9.62 encoded point + * @param point EC point + * @param pointSize Size of the point in bits + * @returns ANSI X9.62 encoded point + */ + public static encodePoint(point: EcPoint, pointSize: number): Uint8Array { + // get field size in bytes (rounding up) + const size = Math.ceil(pointSize / 8); + + // Check point data size + if (point.x.byteLength !== size || point.y.byteLength !== size) { + throw new Error("X,Y coordinates don't match point size criteria"); + } + + const x = BufferSourceConverter.toUint8Array(point.x); + const y = BufferSourceConverter.toUint8Array(point.y); + const res = new Uint8Array(size * 2 + 1); + res[0] = 4; + res.set(x, 1); + res.set(y, size + 1); + + return res; + } + + public static getSize(pointSize: number): number { + return Math.ceil(pointSize / 8); + } + + public static encodeSignature(signature: EcSignaturePoint, pointSize: number): Uint8Array { + const size = this.getSize(pointSize); + const r = BufferSourceConverter.toUint8Array(signature.r); + const s = BufferSourceConverter.toUint8Array(signature.s); + + const res = new Uint8Array(size * 2); + + res.set(this.padStart(r, size)); + res.set(this.padStart(s, size), size); + + return res; + } + + public static decodeSignature(data: BufferSource, pointSize: number): EcSignaturePoint { + const size = this.getSize(pointSize); + const view = BufferSourceConverter.toUint8Array(data); + if (view.length !== (size * 2)) { + throw new Error("Incorrect size of the signature"); + } + + const r = view.slice(0, size); + const s = view.slice(size); + + return { + r: this.trimStart(r), + s: this.trimStart(s), + } + } + + public static trimStart(data: Uint8Array): Uint8Array { + let i = 0; + while ((i < data.length - 1) && (data[i] === 0)) { + i++; + } + if (i === 0) { + return data; + } + + return data.slice(i, data.length); + } + + public static padStart(data: Uint8Array, size: number): Uint8Array { + if (size === data.length) { + return data; + } + + const res = new Uint8Array(size); + res.set(data, size - data.length) + + return res; + } + +} diff --git a/packages/core/src/errors/algorithm.ts b/packages/core/src/errors/algorithm.ts new file mode 100644 index 0000000..eb4d46f --- /dev/null +++ b/packages/core/src/errors/algorithm.ts @@ -0,0 +1,4 @@ +import { CryptoError } from "./crypto"; + +export class AlgorithmError extends CryptoError { +} diff --git a/packages/core/src/errors/crypto.ts b/packages/core/src/errors/crypto.ts new file mode 100644 index 0000000..e7a3bfb --- /dev/null +++ b/packages/core/src/errors/crypto.ts @@ -0,0 +1,2 @@ +export class CryptoError extends Error { +} diff --git a/packages/core/src/errors/index.ts b/packages/core/src/errors/index.ts new file mode 100644 index 0000000..7412060 --- /dev/null +++ b/packages/core/src/errors/index.ts @@ -0,0 +1,5 @@ +export * from "./algorithm"; +export * from "./crypto"; +export * from "./not_implemented"; +export * from "./operation"; +export * from "./required_property"; diff --git a/packages/core/src/errors/not_implemented.ts b/packages/core/src/errors/not_implemented.ts new file mode 100644 index 0000000..e294900 --- /dev/null +++ b/packages/core/src/errors/not_implemented.ts @@ -0,0 +1,7 @@ +import { CryptoError } from "./crypto"; + +export class UnsupportedOperationError extends CryptoError { + constructor(methodName?: string) { + super(`Unsupported operation: ${methodName ? `${methodName}` : ""}`); + } +} diff --git a/packages/core/src/errors/operation.ts b/packages/core/src/errors/operation.ts new file mode 100644 index 0000000..578ed16 --- /dev/null +++ b/packages/core/src/errors/operation.ts @@ -0,0 +1,4 @@ +import { CryptoError } from "./crypto"; + +export class OperationError extends CryptoError { +} diff --git a/packages/core/src/errors/required_property.ts b/packages/core/src/errors/required_property.ts new file mode 100644 index 0000000..04fe3c3 --- /dev/null +++ b/packages/core/src/errors/required_property.ts @@ -0,0 +1,7 @@ +import { CryptoError } from "./crypto"; + +export class RequiredPropertyError extends CryptoError { + constructor(propName: string) { + super(`${propName}: Missing required property`); + } +} diff --git a/packages/core/src/hkdf/hkdf.ts b/packages/core/src/hkdf/hkdf.ts new file mode 100644 index 0000000..dcd7d20 --- /dev/null +++ b/packages/core/src/hkdf/hkdf.ts @@ -0,0 +1,41 @@ +import * as types from "@peculiar/webcrypto-types"; +import { BufferSourceConverter } from "pvtsutils"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; + +export abstract class HkdfProvider extends ProviderCrypto { + + public name = "HKDF"; + public hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; + public usages: types.KeyUsages = ["deriveKey", "deriveBits"]; + + public override checkAlgorithmParams(algorithm: types.HkdfParams) { + // hash + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + + // salt + this.checkRequiredProperty(algorithm, "salt"); + if (!BufferSourceConverter.isBufferSource(algorithm.salt)) { + throw new TypeError("salt: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + + // info + this.checkRequiredProperty(algorithm, "info"); + if (!BufferSourceConverter.isBufferSource(algorithm.info)) { + throw new TypeError("salt: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + } + + public override checkImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]) { + super.checkImportKey(format, keyData, algorithm, extractable, keyUsages); + if (extractable) { + // If extractable is not false, then throw a SyntaxError + throw new SyntaxError("extractable: Must be 'false'"); + } + } + + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onDeriveBits(algorithm: types.HkdfParams, baseKey: BaseCryptoKey, length: number, ...args: any[]): Promise; + +} diff --git a/src/mechs/hkdf/index.ts b/packages/core/src/hkdf/index.ts similarity index 100% rename from src/mechs/hkdf/index.ts rename to packages/core/src/hkdf/index.ts diff --git a/packages/core/src/hmac/index.ts b/packages/core/src/hmac/index.ts new file mode 100644 index 0000000..4e18895 --- /dev/null +++ b/packages/core/src/hmac/index.ts @@ -0,0 +1,56 @@ +import * as types from "@peculiar/webcrypto-types"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; + +export abstract class HmacProvider extends ProviderCrypto { + + public name = "HMAC"; + + public hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; + + public usages: types.KeyUsages = ["sign", "verify"]; + + /** + * Returns default size in bits by hash algorithm name + * @param algName Name of the hash algorithm + */ + public getDefaultLength(algName: string) { + switch (algName.toUpperCase()) { + // Chrome, Safari and Firefox returns 512 + case "SHA-1": + case "SHA-256": + case "SHA-384": + case "SHA-512": + return 512; + default: + throw new Error(`Unknown algorithm name '${algName}'`); + } + } + + public override checkGenerateKeyParams(algorithm: types.HmacKeyGenParams) { + // hash + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + + // length + if ("length" in algorithm) { + if (typeof algorithm.length !== "number") { + throw new TypeError("length: Is not a Number"); + } + if (algorithm.length < 1) { + throw new RangeError("length: Number is out of range"); + } + } + } + + public override checkImportParams(algorithm: types.HmacImportParams) { + // hash + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + } + + public abstract override onGenerateKey(algorithm: types.PreparedHashedAlgorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onExportKey(format: types.KeyFormat, key: BaseCryptoKey, ...args: any[]): Promise; + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.HmacImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + +} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts new file mode 100644 index 0000000..83926e7 --- /dev/null +++ b/packages/core/src/index.ts @@ -0,0 +1,17 @@ +export * from "./errors"; +export * from "./aes"; +export * from "./des"; +export * from "./rsa"; +export * from "./ec"; +export * from "./hmac"; +export * from "./pbkdf"; +export * from "./hkdf"; +export * from "./shake"; +export * from "./crypto"; +export * from "./provider"; +export * from "./storage"; +export * from "./subtle"; +export * from "./crypto_key"; +export * from "./utils"; +export * from "./jwk_utils"; +export * from "./schema"; diff --git a/packages/core/src/jwk_utils.ts b/packages/core/src/jwk_utils.ts new file mode 100644 index 0000000..6fa77bd --- /dev/null +++ b/packages/core/src/jwk_utils.ts @@ -0,0 +1,26 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; + +const REQUIRED_FIELDS = ["crv", "e", "k", "kty", "n", "x", "y"]; + +export class JwkUtils { + + public static async thumbprint(hash: types.AlgorithmIdentifier, jwk: types.JsonWebKey, crypto: types.Crypto): Promise { + const data = this.format(jwk, true); + + return crypto.subtle.digest(hash, Convert.FromBinary(JSON.stringify(data))); + } + + public static format(jwk: types.JsonWebKey, remove = false): types.JsonWebKey { + let res = Object.entries(jwk); + if (remove) { + res = res.filter(o => REQUIRED_FIELDS.includes(o[0])); + } + + res = res.sort(([keyA], [keyB]) => + keyA > keyB ? 1 : keyA < keyB ? -1 : 0); + + return Object.fromEntries(res) as types.JsonWebKey; + } + +} diff --git a/src/mechs/pbkdf/index.ts b/packages/core/src/pbkdf/index.ts similarity index 100% rename from src/mechs/pbkdf/index.ts rename to packages/core/src/pbkdf/index.ts diff --git a/packages/core/src/pbkdf/pbkdf2.ts b/packages/core/src/pbkdf/pbkdf2.ts new file mode 100644 index 0000000..7945025 --- /dev/null +++ b/packages/core/src/pbkdf/pbkdf2.ts @@ -0,0 +1,45 @@ +import * as types from "@peculiar/webcrypto-types"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; + +export abstract class Pbkdf2Provider extends ProviderCrypto { + + public name = "PBKDF2"; + + public hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; + + public usages: types.KeyUsages = ["deriveBits", "deriveKey"]; + + public override checkAlgorithmParams(algorithm: types.Pbkdf2Params) { + // hash + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + + // salt + this.checkRequiredProperty(algorithm, "salt"); + if (!(algorithm.salt instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.salt))) { + throw new TypeError("salt: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + + // iterations + this.checkRequiredProperty(algorithm, "iterations"); + if (typeof algorithm.iterations !== "number") { + throw new TypeError("iterations: Is not a Number"); + } + if (algorithm.iterations < 1) { + throw new TypeError("iterations: Is less than 1"); + } + } + + public override checkImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]) { + super.checkImportKey(format, keyData, algorithm, extractable, keyUsages); + if (extractable) { + // If extractable is not false, then throw a SyntaxError + throw new SyntaxError("extractable: Must be 'false'"); + } + } + + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onDeriveBits(algorithm: types.Pbkdf2Params, baseKey: BaseCryptoKey, length: number, ...args: any[]): Promise; + +} diff --git a/packages/core/src/provider.ts b/packages/core/src/provider.ts new file mode 100644 index 0000000..5140f98 --- /dev/null +++ b/packages/core/src/provider.ts @@ -0,0 +1,270 @@ +import * as types from "@peculiar/webcrypto-types"; +import { BufferSourceConverter } from "pvtsutils"; +import { AlgorithmError, CryptoError, OperationError, RequiredPropertyError, UnsupportedOperationError } from "./errors"; +import { isJWK } from "./utils"; + +export interface IProviderCheckOptions { + keyUsage?: boolean; +} + +export abstract class ProviderCrypto { + + /** + * Name of the algorithm + */ + public abstract readonly name: string; + + /** + * Key usages for secret key or key pair + */ + public abstract readonly usages: types.ProviderKeyUsages; + + //#region Digest + public async digest(algorithm: types.Algorithm, data: ArrayBuffer, ...args: any[]): Promise; + public async digest(...args: any[]): Promise { + this.checkDigest.apply(this, args as unknown as any); + return this.onDigest.apply(this, args as unknown as any); + } + public checkDigest(algorithm: types.Algorithm, data: ArrayBuffer) { + this.checkAlgorithmName(algorithm); + } + public async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + throw new UnsupportedOperationError("digest"); + } + //#endregion + + //#region Generate key + public async generateKey(algorithm: types.RsaHashedKeyGenParams | types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise; + public async generateKey(algorithm: types.AesKeyGenParams | types.HmacKeyGenParams | types.Pbkdf2Params, extractable: boolean, keyUsages: types.KeyUsage[]): Promise; + public async generateKey(algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async generateKey(...args: any[]): Promise { + this.checkGenerateKey.apply(this, args as unknown as any); + return this.onGenerateKey.apply(this, args as unknown as any); + } + public checkGenerateKey(algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkGenerateKeyParams(algorithm); + if (!(keyUsages && keyUsages.length)) { + throw new TypeError(`Usages cannot be empty when creating a key.`); + } + let allowedUsages: types.KeyUsages; + if (Array.isArray(this.usages)) { + allowedUsages = this.usages; + } else { + allowedUsages = this.usages.privateKey.concat(this.usages.publicKey); + } + this.checkKeyUsages(keyUsages, allowedUsages); + } + public checkGenerateKeyParams(algorithm: types.Algorithm) { + // nothing + } + public async onGenerateKey(algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + throw new UnsupportedOperationError("generateKey"); + } + //#endregion + + //#region Sign + public async sign(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public async sign(...args: any[]): Promise { + this.checkSign.apply(this, args as unknown as any); + return this.onSign.apply(this, args as unknown as any); + } + public checkSign(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkAlgorithmParams(algorithm); + this.checkCryptoKey(key, "sign"); + } + public async onSign(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise { + throw new UnsupportedOperationError("sign"); + } + //#endregion + + //#region Verify + public async verify(algorithm: types.Algorithm, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + public async verify(...args: any[]): Promise { + this.checkVerify.apply(this, args as unknown as any); + return this.onVerify.apply(this, args as unknown as any); + } + public checkVerify(algorithm: types.Algorithm, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkAlgorithmParams(algorithm); + this.checkCryptoKey(key, "verify"); + } + public async onVerify(algorithm: types.Algorithm, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise { + throw new UnsupportedOperationError("verify"); + } + //#endregion + + //#region Encrypt + public async encrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, options?: IProviderCheckOptions, ...args: any[]): Promise; + public async encrypt(...args: any[]): Promise { + this.checkEncrypt.apply(this, args as unknown as any); + return this.onEncrypt.apply(this, args as unknown as any); + } + public checkEncrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, options: IProviderCheckOptions = {}, ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkAlgorithmParams(algorithm); + this.checkCryptoKey(key, options.keyUsage ? "encrypt" : void 0); + } + public async onEncrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise { + throw new UnsupportedOperationError("encrypt"); + } + //#endregion + + //#region Decrypt + public async decrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, options?: IProviderCheckOptions, ...args: any[]): Promise; + public async decrypt(...args: any[]): Promise { + this.checkDecrypt.apply(this, args as unknown as any); + return this.onDecrypt.apply(this, args as unknown as any); + } + public checkDecrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, options: IProviderCheckOptions = {}, ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkAlgorithmParams(algorithm); + this.checkCryptoKey(key, options.keyUsage ? "decrypt" : void 0); + } + public async onDecrypt(algorithm: types.Algorithm, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise { + throw new UnsupportedOperationError("decrypt"); + } + //#endregion + + //#region Derive bits + public async deriveBits(algorithm: types.Algorithm, baseKey: types.CryptoKey, length: number, options?: IProviderCheckOptions, ...args: any[]): Promise; + public async deriveBits(...args: any[]): Promise { + this.checkDeriveBits.apply(this, args as unknown as any); + return this.onDeriveBits.apply(this, args as unknown as any); + } + public checkDeriveBits(algorithm: types.Algorithm, baseKey: types.CryptoKey, length: number, options: IProviderCheckOptions = {}, ...args: any[]) { + this.checkAlgorithmName(algorithm); + this.checkAlgorithmParams(algorithm); + this.checkCryptoKey(baseKey, options.keyUsage ? "deriveBits" : void 0); + if (length % 8 !== 0) { + throw new OperationError("length: Is not multiple of 8"); + } + } + public async onDeriveBits(algorithm: types.Algorithm, baseKey: types.CryptoKey, length: number, ...args: any[]): Promise { + throw new UnsupportedOperationError("deriveBits"); + } + //#endregion + + //#region Export key + public async exportKey(format: types.KeyFormat, key: types.CryptoKey, ...args: any[]): Promise; + public async exportKey(...args: any[]): Promise { + this.checkExportKey.apply(this, args as unknown as any); + return this.onExportKey.apply(this, args as unknown as any); + } + public checkExportKey(format: types.KeyFormat, key: types.CryptoKey, ...args: any[]) { + this.checkKeyFormat(format); + this.checkCryptoKey(key); + + if (!key.extractable) { + throw new CryptoError("key: Is not extractable"); + } + } + public async onExportKey(format: types.KeyFormat, key: types.CryptoKey, ...args: any[]): Promise { + throw new UnsupportedOperationError("exportKey"); + } + //#endregion + + //#region Import key + public async importKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async importKey(...args: any[]): Promise { + this.checkImportKey.apply(this, args as unknown as any); + return this.onImportKey.apply(this, args as unknown as any); + } + public checkImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]) { + this.checkKeyFormat(format); + this.checkKeyData(format, keyData); + this.checkAlgorithmName(algorithm); + this.checkImportParams(algorithm); + + // check key usages + if (Array.isArray(this.usages)) { + // symmetric provider + this.checkKeyUsages(keyUsages, this.usages); + } else { + // asymmetric provider + // TODO: implement + } + } + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + throw new UnsupportedOperationError("importKey"); + } + //#endregion + + public checkAlgorithmName(algorithm: types.Algorithm) { + if (algorithm.name.toLowerCase() !== this.name.toLowerCase()) { + throw new AlgorithmError("Unrecognized name"); + } + } + + public checkAlgorithmParams(algorithm: types.Algorithm) { + // nothing + } + + public checkDerivedKeyParams(algorithm: types.Algorithm) { + // nothing + } + + public checkKeyUsages(usages: types.KeyUsages, allowed: types.KeyUsages) { + for (const usage of usages) { + if (allowed.indexOf(usage) === -1) { + throw new TypeError("Cannot create a key using the specified key usages"); + } + } + } + + public checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { + this.checkAlgorithmName(key.algorithm); + if (keyUsage && key.usages.indexOf(keyUsage) === -1) { + throw new CryptoError(`key does not match that of operation`); + } + } + + public checkRequiredProperty(data: object, propName: string) { + if (!(propName in data)) { + throw new RequiredPropertyError(propName); + } + } + + public checkHashAlgorithm(algorithm: types.Algorithm, hashAlgorithms: string[]) { + for (const item of hashAlgorithms) { + if (item.toLowerCase() === algorithm.name.toLowerCase()) { + return; + } + } + throw new OperationError(`hash: Must be one of ${hashAlgorithms.join(", ")}`); + } + + public checkImportParams(algorithm: types.Algorithm) { + // nothing + } + + public checkKeyFormat(format: any) { + switch (format) { + case "raw": + case "pkcs8": + case "spki": + case "jwk": + break; + default: + throw new TypeError("format: Is invalid value. Must be 'jwk', 'raw', 'spki', or 'pkcs8'"); + } + } + + public checkKeyData(format: types.KeyFormat, keyData: any) { + if (!keyData) { + throw new TypeError("keyData: Cannot be empty on empty on key importing"); + } + if (format === "jwk") { + if (!isJWK(keyData)) { + throw new TypeError("keyData: Is not JsonWebToken"); + } + } else if (!BufferSourceConverter.isBufferSource(keyData)) { + throw new TypeError("keyData: Is not ArrayBufferView or ArrayBuffer"); + } + } + + protected prepareData(data: any) { + return BufferSourceConverter.toArrayBuffer(data); + } +} diff --git a/packages/core/src/rsa/base.ts b/packages/core/src/rsa/base.ts new file mode 100644 index 0000000..1ff71e4 --- /dev/null +++ b/packages/core/src/rsa/base.ts @@ -0,0 +1,43 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { BaseCryptoKey } from "../crypto_key"; +import { ProviderCrypto } from "../provider"; + +export abstract class RsaProvider extends ProviderCrypto { + + public hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"]; + + public override checkGenerateKeyParams(algorithm: types.RsaHashedKeyGenParams) { + // hash + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + + // public exponent + this.checkRequiredProperty(algorithm, "publicExponent"); + if (!(algorithm.publicExponent && algorithm.publicExponent instanceof Uint8Array)) { + throw new TypeError("publicExponent: Missing or not a Uint8Array"); + } + const publicExponent = Convert.ToBase64(algorithm.publicExponent); + if (!(publicExponent === "Aw==" || publicExponent === "AQAB")) { + throw new TypeError("publicExponent: Must be [3] or [1,0,1]"); + } + + // modulus length + this.checkRequiredProperty(algorithm, "modulusLength"); + if (algorithm.modulusLength % 8 + || algorithm.modulusLength < 256 + || algorithm.modulusLength > 16384) { + throw new TypeError("The modulus length must be a multiple of 8 bits and >= 256 and <= 16384"); + } + } + + public override checkImportParams(algorithm: types.RsaHashedImportParams) { + this.checkRequiredProperty(algorithm, "hash"); + this.checkHashAlgorithm(algorithm.hash as types.Algorithm, this.hashAlgorithms); + } + + public abstract override onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public abstract override onExportKey(format: types.KeyFormat, key: BaseCryptoKey, ...args: any[]): Promise; + public abstract override onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + +} diff --git a/packages/core/src/rsa/index.ts b/packages/core/src/rsa/index.ts new file mode 100644 index 0000000..1d308a1 --- /dev/null +++ b/packages/core/src/rsa/index.ts @@ -0,0 +1,4 @@ +export * from "./base"; +export * from "./ssa"; +export * from "./pss"; +export * from "./oaep"; diff --git a/packages/core/src/rsa/oaep.ts b/packages/core/src/rsa/oaep.ts new file mode 100644 index 0000000..6bf8385 --- /dev/null +++ b/packages/core/src/rsa/oaep.ts @@ -0,0 +1,24 @@ +import * as types from "@peculiar/webcrypto-types"; +import { RsaProvider } from "./base"; + +export abstract class RsaOaepProvider extends RsaProvider { + + public readonly name = "RSA-OAEP"; + + public usages: types.ProviderKeyUsages = { + privateKey: ["decrypt", "unwrapKey"], + publicKey: ["encrypt", "wrapKey"], + }; + + public override checkAlgorithmParams(algorithm: types.RsaOaepParams) { + // label + if (algorithm.label + && !(algorithm.label instanceof ArrayBuffer || ArrayBuffer.isView(algorithm.label))) { + throw new TypeError("label: Is not of type '(ArrayBuffer or ArrayBufferView)'"); + } + } + + public abstract override onEncrypt(algorithm: types.RsaOaepParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onDecrypt(algorithm: types.RsaOaepParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/rsa/pss.ts b/packages/core/src/rsa/pss.ts new file mode 100644 index 0000000..be6ccdd --- /dev/null +++ b/packages/core/src/rsa/pss.ts @@ -0,0 +1,26 @@ +import * as types from "@peculiar/webcrypto-types"; +import { RsaProvider } from "./base"; + +export abstract class RsaPssProvider extends RsaProvider { + + public readonly name = "RSA-PSS"; + + public usages: types.ProviderKeyUsages = { + privateKey: ["sign"], + publicKey: ["verify"], + }; + + public override checkAlgorithmParams(algorithm: types.RsaPssParams) { + this.checkRequiredProperty(algorithm, "saltLength"); + if (typeof algorithm.saltLength !== "number") { + throw new TypeError("saltLength: Is not a Number"); + } + if (algorithm.saltLength < 0) { + throw new RangeError("saltLength: Must be positive number"); + } + } + + public abstract override onSign(algorithm: types.RsaPssParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onVerify(algorithm: types.RsaPssParams, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/rsa/ssa.ts b/packages/core/src/rsa/ssa.ts new file mode 100644 index 0000000..4dd4965 --- /dev/null +++ b/packages/core/src/rsa/ssa.ts @@ -0,0 +1,18 @@ +import * as types from "@peculiar/webcrypto-types"; +import { RsaProvider } from "./base"; + +export interface RsaSsaParams extends types.Algorithm { } + +export abstract class RsaSsaProvider extends RsaProvider { + + public readonly name = "RSASSA-PKCS1-v1_5"; + + public usages: types.ProviderKeyUsages = { + privateKey: ["sign"], + publicKey: ["verify"], + }; + + public abstract override onSign(algorithm: RsaSsaParams, key: types.CryptoKey, data: ArrayBuffer, ...args: any[]): Promise; + public abstract override onVerify(algorithm: RsaSsaParams, key: types.CryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise; + +} diff --git a/packages/core/src/schema/asn1/algorithm_identifier.ts b/packages/core/src/schema/asn1/algorithm_identifier.ts new file mode 100644 index 0000000..0631bdd --- /dev/null +++ b/packages/core/src/schema/asn1/algorithm_identifier.ts @@ -0,0 +1,31 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; + +// RFC 5280 +// https://tools.ietf.org/html/rfc5280#section-4.1.1.2 +// +// AlgorithmIdentifier ::= SEQUENCE { +// algorithm OBJECT IDENTIFIER, +// parameters ANY DEFINED BY algorithm OPTIONAL } +// -- contains a value of the type +// -- registered for use with the +// -- algorithm object identifier value + +export type ParametersType = ArrayBuffer | null; + +export class AlgorithmIdentifier { + + @AsnProp({ + type: AsnPropTypes.ObjectIdentifier, + }) + public algorithm!: string; + + @AsnProp({ + type: AsnPropTypes.Any, + optional: true, + }) + public parameters?: ParametersType; + + constructor(params?: Partial) { + Object.assign(this, params); + } +} diff --git a/packages/core/src/schema/asn1/converters/index.ts b/packages/core/src/schema/asn1/converters/index.ts new file mode 100644 index 0000000..c9c6ef5 --- /dev/null +++ b/packages/core/src/schema/asn1/converters/index.ts @@ -0,0 +1 @@ +export * from "./integer_without_paddings"; diff --git a/packages/core/src/schema/asn1/converters/integer_without_paddings.ts b/packages/core/src/schema/asn1/converters/integer_without_paddings.ts new file mode 100644 index 0000000..aee0026 --- /dev/null +++ b/packages/core/src/schema/asn1/converters/integer_without_paddings.ts @@ -0,0 +1,20 @@ +import { IAsnConverter } from "@peculiar/asn1-schema"; +import * as asn1 from "asn1js"; + +export const AsnIntegerWithoutPaddingConverter: IAsnConverter = { + fromASN: (value: any) => { + const bytes = new Uint8Array(value.valueBlock.valueHex); + return (bytes[0] === 0) + ? bytes.buffer.slice(1) + : bytes.buffer; + }, + toASN: (value: ArrayBuffer): any => { + const bytes = new Uint8Array(value); + if (bytes[0] > 127) { + const newValue = new Uint8Array(bytes.length + 1); + newValue.set(bytes, 1); + return new asn1.Integer({ valueHex: newValue.buffer } as any); + } + return new asn1.Integer({ valueHex: value } as any); + }, +}; diff --git a/packages/core/src/schema/asn1/ec_private_key.ts b/packages/core/src/schema/asn1/ec_private_key.ts new file mode 100644 index 0000000..bb0d0a3 --- /dev/null +++ b/packages/core/src/schema/asn1/ec_private_key.ts @@ -0,0 +1,55 @@ +import * as types from "@peculiar/webcrypto-types"; +import { AsnIntegerConverter, AsnProp, AsnPropTypes, AsnSerializer } from "@peculiar/asn1-schema"; +import { IJsonConvertible } from "@peculiar/json-schema"; +import { Convert } from "pvtsutils"; +import { EcPublicKey } from "./ec_public_key"; + +// RFC 5915 +// https://tools.ietf.org/html/rfc5915#section-3 +// +// ECPrivateKey ::= SEQUENCE { +// version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), +// privateKey OCTET STRING, +// parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, +// publicKey [1] BIT STRING OPTIONAL +// } + +export class EcPrivateKey implements IJsonConvertible { + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerConverter }) + public version = 1; + + @AsnProp({ type: AsnPropTypes.OctetString }) + public privateKey = new ArrayBuffer(0); + + @AsnProp({ context: 0, type: AsnPropTypes.Any, optional: true }) + public parameters?: ArrayBuffer; + + @AsnProp({ context: 1, type: AsnPropTypes.BitString, optional: true }) + public publicKey?: ArrayBuffer; + + public fromJSON(json: any): this { + if (!("d" in json)) { + throw new Error("d: Missing required property"); + } + this.privateKey = Convert.FromBase64Url(json.d); + + if ("x" in json) { + const publicKey = new EcPublicKey(); + publicKey.fromJSON(json); + + this.publicKey = AsnSerializer.toASN(publicKey).valueBlock.valueHex; + } + + return this; + } + public toJSON() { + const jwk: types.JsonWebKey = {}; + jwk.d = Convert.ToBase64Url(this.privateKey); + if (this.publicKey) { + Object.assign(jwk, new EcPublicKey(this.publicKey).toJSON()); + } + return jwk; + } + +} diff --git a/packages/core/src/schema/asn1/ec_public_key.ts b/packages/core/src/schema/asn1/ec_public_key.ts new file mode 100644 index 0000000..233ba07 --- /dev/null +++ b/packages/core/src/schema/asn1/ec_public_key.ts @@ -0,0 +1,63 @@ +import { AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from "@peculiar/asn1-schema"; +import { IJsonConvertible } from "@peculiar/json-schema"; +import { combine, Convert } from "pvtsutils"; + +// RFC 5480 +// https://tools.ietf.org/html/rfc5480#section-2.2 +// +// ECPoint ::= OCTET STRING + +@AsnType({ type: AsnTypeTypes.Choice }) +export class EcPublicKey implements IJsonConvertible { + + @AsnProp({ type: AsnPropTypes.OctetString }) + public value = new ArrayBuffer(0); + + constructor(value?: ArrayBuffer) { + if (value) { + this.value = value; + } + } + + public toJSON() { + let bytes = new Uint8Array(this.value); + + if (bytes[0] !== 0x04) { + throw new Error("Wrong ECPoint. Current version supports only Uncompressed (0x04) point"); + } + + bytes = new Uint8Array(this.value.slice(1)); + const size = bytes.length / 2; + + const offset = 0; + const json = { + x: Convert.ToBase64Url(bytes.buffer.slice(offset, offset + size)), + y: Convert.ToBase64Url(bytes.buffer.slice(offset + size, offset + size + size)), + }; + + return json; + } + + public fromJSON(json: any): this { + if (!("x" in json)) { + throw new Error("x: Missing required property"); + } + if (!("y" in json)) { + throw new Error("y: Missing required property"); + } + + const x = Convert.FromBase64Url(json.x); + const y = Convert.FromBase64Url(json.y); + + const value = combine( + new Uint8Array([0x04]).buffer, // uncompressed bit + x, + y, + ); + + this.value = new Uint8Array(value).buffer; + + return this; + } + +} diff --git a/packages/core/src/schema/asn1/ec_signature.ts b/packages/core/src/schema/asn1/ec_signature.ts new file mode 100644 index 0000000..b1de9d4 --- /dev/null +++ b/packages/core/src/schema/asn1/ec_signature.ts @@ -0,0 +1,51 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { BufferSourceConverter, BufferSource } from "pvtsutils"; +import { EcUtils } from "../../ec/utils"; +import { AsnIntegerWithoutPaddingConverter } from "./converters"; + +// RFC 3279 +// https://tools.ietf.org/html/rfc3279#section-2.2.3 +// +// ECDSA-Sig-Value ::= SEQUENCE { +// r INTEGER, +// s INTEGER +// } + +export class EcDsaSignature { + + /** + * Create EcDsaSignature from X9.62 signature + * @param value X9.62 signature + * @returns EcDsaSignature + */ + public static fromWebCryptoSignature(value: BufferSource): EcDsaSignature { + const pointSize = value.byteLength / 2; + + const point = EcUtils.decodeSignature(value, pointSize * 8); + const ecSignature = new EcDsaSignature(); + ecSignature.r = BufferSourceConverter.toArrayBuffer(point.r); + ecSignature.s = BufferSourceConverter.toArrayBuffer(point.s); + + return ecSignature; + } + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerWithoutPaddingConverter }) + public r = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerWithoutPaddingConverter }) + public s = new ArrayBuffer(0); + + /** + * Converts ECDSA signature into X9.62 signature format + * @param pointSize EC point size in bits + * @returns ECDSA signature in X9.62 signature format + */ + public toWebCryptoSignature(pointSize?: number): ArrayBuffer { + pointSize ??= Math.max(this.r.byteLength, this.s.byteLength) * 8; + + const signature = EcUtils.encodeSignature(this, pointSize); + + return signature.buffer; + } + +} diff --git a/packages/core/src/schema/asn1/ed_private_key.ts b/packages/core/src/schema/asn1/ed_private_key.ts new file mode 100644 index 0000000..78f70ac --- /dev/null +++ b/packages/core/src/schema/asn1/ed_private_key.ts @@ -0,0 +1,27 @@ +import { AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from "@peculiar/asn1-schema"; +import { IJsonConvertible } from "@peculiar/json-schema"; +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; + +@AsnType({ type: AsnTypeTypes.Choice }) +export class EdPrivateKey implements IJsonConvertible { + + @AsnProp({ type: AsnPropTypes.OctetString }) + public value = new ArrayBuffer(0); + + public fromJSON(json: any): this { + if (!json.d) { + throw new Error("d: Missing required property"); + } + this.value = Convert.FromBase64Url(json.d); + + return this; + } + public toJSON() { + const jwk: types.JsonWebKey = { + d: Convert.ToBase64Url(this.value), + }; + + return jwk; + } +} diff --git a/packages/core/src/schema/asn1/ed_public_key.ts b/packages/core/src/schema/asn1/ed_public_key.ts new file mode 100644 index 0000000..bd770e6 --- /dev/null +++ b/packages/core/src/schema/asn1/ed_public_key.ts @@ -0,0 +1,40 @@ +import { AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from "@peculiar/asn1-schema"; +import { IJsonConvertible } from "@peculiar/json-schema"; +import { Convert } from "pvtsutils"; + +// RFC 8410 +// https://datatracker.ietf.org/doc/html/rfc8410 +// +// PublicKey ::= BIT STRING + +@AsnType({ type: AsnTypeTypes.Choice }) +export class EdPublicKey implements IJsonConvertible { + + @AsnProp({ type: AsnPropTypes.BitString }) + public value = new ArrayBuffer(0); + + constructor(value?: ArrayBuffer) { + if (value) { + this.value = value; + } + } + + public toJSON() { + const json = { + x: Convert.ToBase64Url(this.value), + }; + + return json; + } + + public fromJSON(json: any): this { + if (!("x" in json)) { + throw new Error("x: Missing required property"); + } + + this.value = Convert.FromBase64Url(json.x); + + return this; + } + +} diff --git a/packages/core/src/schema/asn1/index.ts b/packages/core/src/schema/asn1/index.ts new file mode 100644 index 0000000..08cf577 --- /dev/null +++ b/packages/core/src/schema/asn1/index.ts @@ -0,0 +1,14 @@ +export * from "./object_identifier"; +export * from "./algorithm_identifier"; +export * from "./private_key_info"; +export * from "./public_key_info"; +export * from "./rsa_private_key"; +export * from "./rsa_public_key"; +export * from "./ec_private_key"; +export * from "./ec_public_key"; +export * from "./ec_signature"; +export * from "./one_asymmetric_key"; +export * from "./ed_private_key"; +export * from "./ed_public_key"; +export * from "./rfc8410"; +export * as converters from "./converters"; diff --git a/packages/core/src/schema/asn1/object_identifier.ts b/packages/core/src/schema/asn1/object_identifier.ts new file mode 100644 index 0000000..3c4895b --- /dev/null +++ b/packages/core/src/schema/asn1/object_identifier.ts @@ -0,0 +1,14 @@ +import { AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from "@peculiar/asn1-schema"; + +@AsnType({ type: AsnTypeTypes.Choice }) +export class ObjectIdentifier { + + @AsnProp({type: AsnPropTypes.ObjectIdentifier}) + public value!: string; + + constructor(value?: string) { + if (value) { + this.value = value; + } + } +} diff --git a/packages/core/src/schema/asn1/one_asymmetric_key.ts b/packages/core/src/schema/asn1/one_asymmetric_key.ts new file mode 100644 index 0000000..8231ade --- /dev/null +++ b/packages/core/src/schema/asn1/one_asymmetric_key.ts @@ -0,0 +1,26 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { PrivateKeyInfo } from "./private_key_info"; + +/** + * ```asn + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] IMPLICIT PublicKey OPTIONAL ]], + * ... + * } + * + * PrivateKey ::= OCTET STRING + * + * PublicKey ::= BIT STRING + * ``` + */ +export class OneAsymmetricKey extends PrivateKeyInfo { + + @AsnProp({ context: 1, implicit: true, type: AsnPropTypes.BitString, optional: true }) + public publicKey?: ArrayBuffer; + +} \ No newline at end of file diff --git a/packages/core/src/schema/asn1/private_key_info.ts b/packages/core/src/schema/asn1/private_key_info.ts new file mode 100644 index 0000000..2aee630 --- /dev/null +++ b/packages/core/src/schema/asn1/private_key_info.ts @@ -0,0 +1,35 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { AlgorithmIdentifier } from "./algorithm_identifier"; + +// RFC 5208 +// https://tools.ietf.org/html/rfc5208#section-5 +// +// PrivateKeyInfo ::= SEQUENCE { +// version Version, +// privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, +// privateKey PrivateKey, +// attributes [0] IMPLICIT Attributes OPTIONAL } +// +// Version ::= INTEGER +// +// PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier +// +// PrivateKey ::= OCTET STRING +// +// Attributes ::= SET OF Attribute + +export class PrivateKeyInfo { + + @AsnProp({ type: AsnPropTypes.Integer }) + public version = 0; + + @AsnProp({ type: AlgorithmIdentifier }) + public privateKeyAlgorithm = new AlgorithmIdentifier(); + + @AsnProp({ type: AsnPropTypes.OctetString }) + public privateKey = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Any, optional: true }) + public attributes?: ArrayBuffer; + +} diff --git a/packages/core/src/schema/asn1/public_key_info.ts b/packages/core/src/schema/asn1/public_key_info.ts new file mode 100644 index 0000000..ad34e2a --- /dev/null +++ b/packages/core/src/schema/asn1/public_key_info.ts @@ -0,0 +1,19 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { AlgorithmIdentifier } from "./algorithm_identifier"; + +// RFC 5280 +// https://tools.ietf.org/html/rfc5280#section-4.1 +// +// SubjectPublicKeyInfo ::= SEQUENCE { +// algorithm AlgorithmIdentifier, +// subjectPublicKey BIT STRING + +export class PublicKeyInfo { + + @AsnProp({ type: AlgorithmIdentifier }) + public publicKeyAlgorithm = new AlgorithmIdentifier(); + + @AsnProp({ type: AsnPropTypes.BitString }) + public publicKey = new ArrayBuffer(0); + +} diff --git a/packages/core/src/schema/asn1/rfc8410/curve_private_key.ts b/packages/core/src/schema/asn1/rfc8410/curve_private_key.ts new file mode 100644 index 0000000..c312cf1 --- /dev/null +++ b/packages/core/src/schema/asn1/rfc8410/curve_private_key.ts @@ -0,0 +1,24 @@ +import { AsnProp, AsnPropTypes, AsnType, AsnTypeTypes } from "@peculiar/asn1-schema"; +import { JsonProp, JsonPropTypes } from "@peculiar/json-schema"; +import { JsonBase64UrlArrayBufferConverter } from "../../json/converters"; + +/** + * ASN.1 + * ``` + * CurvePrivateKey ::= OCTET STRING + * ``` + * + * JSON + * ```json + * { + * "d": "base64url" + * } + * ``` + */ +@AsnType({ type: AsnTypeTypes.Choice }) +export class CurvePrivateKey { + + @AsnProp({ type: AsnPropTypes.OctetString }) + @JsonProp({ type: JsonPropTypes.String, converter: JsonBase64UrlArrayBufferConverter }) + public d!: ArrayBuffer; +} diff --git a/packages/core/src/schema/asn1/rfc8410/index.ts b/packages/core/src/schema/asn1/rfc8410/index.ts new file mode 100644 index 0000000..e859f46 --- /dev/null +++ b/packages/core/src/schema/asn1/rfc8410/index.ts @@ -0,0 +1,2 @@ +export * from "./curve_private_key"; +export * from "./object_identifiers"; diff --git a/packages/core/src/schema/asn1/rfc8410/object_identifiers.ts b/packages/core/src/schema/asn1/rfc8410/object_identifiers.ts new file mode 100644 index 0000000..f48112a --- /dev/null +++ b/packages/core/src/schema/asn1/rfc8410/object_identifiers.ts @@ -0,0 +1,152 @@ +/** + * ``` + * secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) + * prime(1) 7 } + * ``` + */ +export const idSecp256r1 = "1.2.840.10045.3.1.7"; +/** + * ``` + * ellipticCurve OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) } + * ``` + */ +export const idEllipticCurve = "1.3.132.0"; +/** + * ``` + * secp384r1 OBJECT IDENTIFIER ::= { ellipticCurve 34 } + * ``` + */ +export const idSecp384r1 = `${idEllipticCurve}.34`; +/** + * ``` + * secp521r1 OBJECT IDENTIFIER ::= { ellipticCurve 35 } + * ``` + */ +export const idSecp521r1 = `${idEllipticCurve}.35`; +/** + * ``` + * secp256k1 OBJECT IDENTIFIER ::= { ellipticCurve 10 } + * ``` + */ +export const idSecp256k1 = `${idEllipticCurve}.10`; +/** + * ``` + * ecStdCurvesAndGeneration OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) teletrust(36) algorithm(3) + * signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8) + * } + * ellipticCurve OBJECT IDENTIFIER ::= { ecStdCurvesAndGeneration 1 } + * versionOne OBJECT IDENTIFIER ::= { ellipticCurve 1 } + * ``` + */ +export const idVersionOne = "1.3.36.3.3.2.8.1.1"; +/** + * ``` + * brainpoolP160r1 OBJECT IDENTIFIER ::= { versionOne 1 } + * ``` + */ +export const idBrainpoolP160r1 = `${idVersionOne}.1`; +/** + * ``` + * brainpoolP160t1 OBJECT IDENTIFIER ::= { versionOne 2 } + * ``` + */ +export const idBrainpoolP160t1 = `${idVersionOne}.2`; +/** + * ``` + * brainpoolP192r1 OBJECT IDENTIFIER ::= { versionOne 3 } + * ``` + */ +export const idBrainpoolP192r1 = `${idVersionOne}.3`; +/** + * ``` + * brainpoolP192t1 OBJECT IDENTIFIER ::= { versionOne 4 } + * ``` + */ +export const idBrainpoolP192t1 = `${idVersionOne}.4`; +/** + * ``` + * brainpoolP224r1 OBJECT IDENTIFIER ::= { versionOne 5 } + * ``` + */ +export const idBrainpoolP224r1 = `${idVersionOne}.5`; +/** + * ``` + * brainpoolP224t1 OBJECT IDENTIFIER ::= { versionOne 6 } + * ``` + */ +export const idBrainpoolP224t1 = `${idVersionOne}.6`; +/** + * ``` + * brainpoolP256r1 OBJECT IDENTIFIER ::= { versionOne 7 } + * ``` + */ +export const idBrainpoolP256r1 = `${idVersionOne}.7`; +/** + * ``` + * brainpoolP256t1 OBJECT IDENTIFIER ::= { versionOne 8 } + * ``` + */ +export const idBrainpoolP256t1 = `${idVersionOne}.8`; +/** + * ``` + * brainpoolP320r1 OBJECT IDENTIFIER ::= { versionOne 9 } + * ``` + */ +export const idBrainpoolP320r1 = `${idVersionOne}.9`; +/** + * ``` + * brainpoolP320t1 OBJECT IDENTIFIER ::= { versionOne 10 } + * ``` + */ +export const idBrainpoolP320t1 = `${idVersionOne}.10`; +/** + * ``` + * brainpoolP384r1 OBJECT IDENTIFIER ::= { versionOne 11 } + * ``` + */ +export const idBrainpoolP384r1 = `${idVersionOne}.11`; +/** + * ``` + * brainpoolP384t1 OBJECT IDENTIFIER ::= { versionOne 12 } + * ``` + */ +export const idBrainpoolP384t1 = `${idVersionOne}.12`; +/** + * ``` + * brainpoolP512r1 OBJECT IDENTIFIER ::= { versionOne 13 } + * ``` + */ +export const idBrainpoolP512r1 = `${idVersionOne}.13`; +/** + * ``` + * brainpoolP512t1 OBJECT IDENTIFIER ::= { versionOne 14 } + * ``` + */ +export const idBrainpoolP512t1 = `${idVersionOne}.14`; +/** + * ``` + * id-X25519 OBJECT IDENTIFIER ::= { 1 3 101 110 } + * ``` + */ +export const idX25519 = "1.3.101.110"; +/** + * ``` + * id-X448 OBJECT IDENTIFIER ::= { 1 3 101 111 } + * ``` + */ +export const idX448 = "1.3.101.111"; +/** + * ``` + * id-Ed25519 OBJECT IDENTIFIER ::= { 1 3 101 112 } + * ``` + */ +export const idEd25519 = "1.3.101.112"; +/** + * ``` + * id-Ed448 OBJECT IDENTIFIER ::= { 1 3 101 113 } + * ``` + */ +export const idEd448 = "1.3.101.113"; diff --git a/packages/core/src/schema/asn1/rsa_private_key.ts b/packages/core/src/schema/asn1/rsa_private_key.ts new file mode 100644 index 0000000..108b954 --- /dev/null +++ b/packages/core/src/schema/asn1/rsa_private_key.ts @@ -0,0 +1,61 @@ +import { AsnIntegerConverter, AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { JsonProp } from "@peculiar/json-schema"; +import { AsnIntegerArrayBufferConverter, JsonBase64UrlArrayBufferConverter } from "../json/converters"; + +// RFC 3437 +// https://tools.ietf.org/html/rfc3447#appendix-A.1.2 +// +// RSAPrivateKey ::= SEQUENCE { +// version Version, +// modulus INTEGER, -- n +// publicExponent INTEGER, -- e +// privateExponent INTEGER, -- d +// prime1 INTEGER, -- p +// prime2 INTEGER, -- q +// exponent1 INTEGER, -- d mod (p-1) +// exponent2 INTEGER, -- d mod (q-1) +// coefficient INTEGER, -- (inverse of q) mod p +// otherPrimeInfos OtherPrimeInfos OPTIONAL +// } + +export class RsaPrivateKey { + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerConverter }) + public version = 0; + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "n", converter: JsonBase64UrlArrayBufferConverter }) + public modulus = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "e", converter: JsonBase64UrlArrayBufferConverter }) + public publicExponent = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "d", converter: JsonBase64UrlArrayBufferConverter }) + public privateExponent = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "p", converter: JsonBase64UrlArrayBufferConverter }) + public prime1 = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "q", converter: JsonBase64UrlArrayBufferConverter }) + public prime2 = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "dp", converter: JsonBase64UrlArrayBufferConverter }) + public exponent1 = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "dq", converter: JsonBase64UrlArrayBufferConverter }) + public exponent2 = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "qi", converter: JsonBase64UrlArrayBufferConverter }) + public coefficient = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Any, optional: true }) + public otherPrimeInfos?: ArrayBuffer; + +} diff --git a/packages/core/src/schema/asn1/rsa_public_key.ts b/packages/core/src/schema/asn1/rsa_public_key.ts new file mode 100644 index 0000000..287abe0 --- /dev/null +++ b/packages/core/src/schema/asn1/rsa_public_key.ts @@ -0,0 +1,23 @@ +import { AsnProp, AsnPropTypes } from "@peculiar/asn1-schema"; +import { JsonProp } from "@peculiar/json-schema"; +import { JsonBase64UrlArrayBufferConverter, AsnIntegerArrayBufferConverter } from "../json/converters"; + +// RFC 3437 +// https://tools.ietf.org/html/rfc3447#appendix-A.1.1 +// +// RSAPublicKey ::= SEQUENCE { +// modulus INTEGER, -- n +// publicExponent INTEGER, -- e +// } + +export class RsaPublicKey { + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "n", converter: JsonBase64UrlArrayBufferConverter }) + public modulus = new ArrayBuffer(0); + + @AsnProp({ type: AsnPropTypes.Integer, converter: AsnIntegerArrayBufferConverter }) + @JsonProp({ name: "e", converter: JsonBase64UrlArrayBufferConverter }) + public publicExponent = new ArrayBuffer(0); + +} diff --git a/packages/core/src/schema/index.ts b/packages/core/src/schema/index.ts new file mode 100644 index 0000000..34f29ef --- /dev/null +++ b/packages/core/src/schema/index.ts @@ -0,0 +1,2 @@ +export * from "./asn1"; +export * from "./json"; \ No newline at end of file diff --git a/packages/core/src/schema/json/converters/base64_url.ts b/packages/core/src/schema/json/converters/base64_url.ts new file mode 100644 index 0000000..8b3ed07 --- /dev/null +++ b/packages/core/src/schema/json/converters/base64_url.ts @@ -0,0 +1,7 @@ +import { IJsonConverter } from "@peculiar/json-schema"; +import { Convert, BufferSourceConverter } from "pvtsutils"; + +export const JsonBase64UrlArrayBufferConverter: IJsonConverter = { + fromJSON: (value: string) => Convert.FromBase64Url(value), + toJSON: (value: ArrayBuffer) => Convert.ToBase64Url(new Uint8Array(value)), +}; diff --git a/packages/core/src/schema/json/converters/index.ts b/packages/core/src/schema/json/converters/index.ts new file mode 100644 index 0000000..da971ca --- /dev/null +++ b/packages/core/src/schema/json/converters/index.ts @@ -0,0 +1,2 @@ +export * from "./base64_url"; +export * from "./integer_converter"; diff --git a/packages/core/src/schema/json/converters/integer_converter.ts b/packages/core/src/schema/json/converters/integer_converter.ts new file mode 100644 index 0000000..485aa7f --- /dev/null +++ b/packages/core/src/schema/json/converters/integer_converter.ts @@ -0,0 +1,11 @@ +import { IAsnConverter } from "@peculiar/asn1-schema"; +import * as asn1 from "asn1js"; + +export const AsnIntegerArrayBufferConverter: IAsnConverter = { + fromASN: (value: asn1.Integer) => { + return value.convertFromDER().valueBlock.valueHexView.slice().buffer; + }, + toASN: (value: ArrayBuffer) => { + return new asn1.Integer({ valueHex: value }).convertToDER(); + }, +}; diff --git a/packages/core/src/schema/json/index.ts b/packages/core/src/schema/json/index.ts new file mode 100644 index 0000000..7a5887f --- /dev/null +++ b/packages/core/src/schema/json/index.ts @@ -0,0 +1 @@ +export * from "./converters"; diff --git a/packages/core/src/shake/base.ts b/packages/core/src/shake/base.ts new file mode 100644 index 0000000..8eaf449 --- /dev/null +++ b/packages/core/src/shake/base.ts @@ -0,0 +1,37 @@ +import { ProviderCrypto } from "../provider"; +import * as types from "@peculiar/webcrypto-types"; + +export interface ShakeParams extends types.Algorithm { + /** + * Output length in bytes + */ + length?: number; +} + +export abstract class ShakeProvider extends ProviderCrypto { + + public usages = []; + public defaultLength = 0; + + public override digest(algorithm: types.Algorithm, data: ArrayBuffer, ...args: any[]): Promise; + public override digest(...args: any[]): Promise { + args[0] = { length: this.defaultLength, ...args[0] }; + + return super.digest.apply(this, args as unknown as any); + } + + public override checkDigest(algorithm: ShakeParams, data: ArrayBuffer): void { + super.checkDigest(algorithm, data); + + const length = algorithm.length || 0; + if (typeof length !== "number") { + throw new TypeError("length: Is not a Number"); + } + if (length < 0) { + throw new TypeError("length: Is negative"); + } + } + + public abstract override onDigest(algorithm: Required, data: ArrayBuffer): Promise; + +} diff --git a/packages/core/src/shake/index.ts b/packages/core/src/shake/index.ts new file mode 100644 index 0000000..b3ce4a9 --- /dev/null +++ b/packages/core/src/shake/index.ts @@ -0,0 +1,3 @@ +export * from "./base"; +export * from "./shake128"; +export * from "./shake256"; diff --git a/packages/core/src/shake/shake128.ts b/packages/core/src/shake/shake128.ts new file mode 100644 index 0000000..ee04517 --- /dev/null +++ b/packages/core/src/shake/shake128.ts @@ -0,0 +1,6 @@ +import { ShakeProvider } from "./base"; + +export abstract class Shake128Provider extends ShakeProvider { + public override name = "shake128"; + public override defaultLength = 16; +} diff --git a/packages/core/src/shake/shake256.ts b/packages/core/src/shake/shake256.ts new file mode 100644 index 0000000..32f7198 --- /dev/null +++ b/packages/core/src/shake/shake256.ts @@ -0,0 +1,6 @@ +import { ShakeProvider } from "./base"; + +export abstract class Shake256Provider extends ShakeProvider { + public override name = "shake256"; + public override defaultLength = 32; +} diff --git a/packages/core/src/storage.ts b/packages/core/src/storage.ts new file mode 100644 index 0000000..65081fc --- /dev/null +++ b/packages/core/src/storage.ts @@ -0,0 +1,39 @@ +import { ProviderCrypto } from "./provider"; + +export class ProviderStorage { + private items: { [algorithmName: string]: ProviderCrypto } = {}; + + public get(algorithmName: string): ProviderCrypto | null { + return this.items[algorithmName.toLowerCase()] || null; + } + + public set(provider: ProviderCrypto) { + this.items[provider.name.toLowerCase()] = provider; + } + + public removeAt(algorithmName: string) { + const provider = this.get(algorithmName.toLowerCase()); + if (provider) { + delete this.items[algorithmName]; + } + return provider; + } + + public has(name: string) { + return !!this.get(name); + } + + public get length() { + return Object.keys(this.items).length; + } + + public get algorithms() { + const algorithms: string[] = []; + for (const key in this.items) { + const provider = this.items[key]; + algorithms.push(provider.name); + } + return algorithms.sort(); + } + +} diff --git a/packages/core/src/subtle.ts b/packages/core/src/subtle.ts new file mode 100644 index 0000000..526396c --- /dev/null +++ b/packages/core/src/subtle.ts @@ -0,0 +1,250 @@ +import * as types from "@peculiar/webcrypto-types"; +import { BufferSource, BufferSourceConverter, Convert } from "pvtsutils"; +import { AlgorithmError } from "./errors"; +import { ProviderCrypto } from "./provider"; +import { ProviderStorage } from "./storage"; +import { BaseCryptoKey } from './crypto_key'; + +export class SubtleCrypto implements types.SubtleCrypto { + + public static isHashedAlgorithm(data: any): data is types.HashedAlgorithm { + return data + && typeof data === "object" + && "name" in data + && "hash" in data + ? true + : false; + } + + public providers = new ProviderStorage(); + + // @internal + public get [Symbol.toStringTag]() { + return "SubtleCrypto"; + } + + public async digest(algorithm: types.AlgorithmIdentifier, data: BufferSource, ...args: any[]): Promise; + public async digest(...args: any[]): Promise { + this.checkRequiredArguments(args, 2, "digest"); + const [algorithm, data, ...params] = args; + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(data); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.digest(preparedAlgorithm, preparedData, ...params); + + return result; + } + + public async generateKey(algorithm: types.RsaHashedKeyGenParams | types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async generateKey(algorithm: types.AesKeyGenParams | types.HmacKeyGenParams | types.Pbkdf2Params, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async generateKey(algorithm: types.AlgorithmIdentifier, extractable: boolean, keyUsages: Iterable, ...args: any[]): Promise; + public async generateKey(...args: any[]): Promise { + this.checkRequiredArguments(args, 3, "generateKey"); + const [algorithm, extractable, keyUsages, ...params] = args; + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.generateKey({ ...preparedAlgorithm, name: provider.name }, extractable, keyUsages, ...params); + + return result; + } + + public async sign(algorithm: types.AlgorithmIdentifier, key: types.CryptoKey, data: BufferSource, ...args: any[]): Promise; + public async sign(...args: any[]): Promise { + this.checkRequiredArguments(args, 3, "sign"); + const [algorithm, key, data, ...params] = args; + this.checkCryptoKey(key); + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(data); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.sign({ ...preparedAlgorithm, name: provider.name }, key, preparedData, ...params); + + return result; + } + + public async verify(algorithm: types.AlgorithmIdentifier, key: types.CryptoKey, signature: BufferSource, data: BufferSource, ...args: any[]): Promise; + public async verify(...args: any[]): Promise { + this.checkRequiredArguments(args, 4, "verify"); + const [algorithm, key, signature, data, ...params] = args; + this.checkCryptoKey(key); + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(data); + const preparedSignature = BufferSourceConverter.toArrayBuffer(signature); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.verify({ ...preparedAlgorithm, name: provider.name }, key, preparedSignature, preparedData, ...params); + + return result; + } + + public async encrypt(algorithm: types.AlgorithmIdentifier, key: types.CryptoKey, data: BufferSource, ...args: any[]): Promise; + public async encrypt(...args: any[]): Promise { + this.checkRequiredArguments(args, 3, "encrypt"); + const [algorithm, key, data, ...params] = args; + this.checkCryptoKey(key); + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(data); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.encrypt({ ...preparedAlgorithm, name: provider.name }, key, preparedData, { keyUsage: true }, ...params); + + return result; + } + + public async decrypt(algorithm: types.AlgorithmIdentifier, key: types.CryptoKey, data: BufferSource, ...args: any[]): Promise; + public async decrypt(...args: any[]): Promise { + this.checkRequiredArguments(args, 3, "decrypt"); + const [algorithm, key, data, ...params] = args; + this.checkCryptoKey(key); + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(data); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.decrypt({ ...preparedAlgorithm, name: provider.name }, key, preparedData, { keyUsage: true }, ...params); + + return result; + } + + public async deriveBits(algorithm: types.AlgorithmIdentifier, baseKey: types.CryptoKey, length: number, ...args: any[]): Promise; + public async deriveBits(...args: any[]): Promise { + this.checkRequiredArguments(args, 3, "deriveBits"); + const [algorithm, baseKey, length, ...params] = args; + this.checkCryptoKey(baseKey); + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + + const provider = this.getProvider(preparedAlgorithm.name); + const result = await provider.deriveBits({ ...preparedAlgorithm, name: provider.name }, baseKey, length, { keyUsage: true }, ...params); + + return result; + } + + public async deriveKey(algorithm: types.AlgorithmIdentifier, baseKey: types.CryptoKey, derivedKeyType: types.AlgorithmIdentifier, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async deriveKey(...args: any[]): Promise { + this.checkRequiredArguments(args, 5, "deriveKey"); + const [algorithm, baseKey, derivedKeyType, extractable, keyUsages, ...params] = args; + // check derivedKeyType + const preparedDerivedKeyType = this.prepareAlgorithm(derivedKeyType); + const importProvider = this.getProvider(preparedDerivedKeyType.name); + importProvider.checkDerivedKeyParams(preparedDerivedKeyType); + + // derive bits + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const provider = this.getProvider(preparedAlgorithm.name); + provider.checkCryptoKey(baseKey, "deriveKey"); + const derivedBits = await provider.deriveBits({ ...preparedAlgorithm, name: provider.name }, baseKey, (derivedKeyType as any).length || 512, { keyUsage: false }, ...params); + + // import derived key + return this.importKey("raw", derivedBits, derivedKeyType, extractable, keyUsages, ...params); + } + + public async exportKey(format: "raw" | "spki" | "pkcs8", key: types.CryptoKey, ...args: any[]): Promise; + public async exportKey(format: "jwk", key: types.CryptoKey, ...args: any[]): Promise; + public async exportKey(format: types.KeyFormat, key: types.CryptoKey, ...args: any[]): Promise; + public async exportKey(...args: any[]): Promise { + this.checkRequiredArguments(args, 2, "exportKey"); + const [format, key, ...params] = args; + this.checkCryptoKey(key); + + const provider = this.getProvider(key.algorithm.name); + const result = await provider.exportKey(format, key, ...params); + + return result; + } + public async importKey(format: types.KeyFormat, keyData: types.JsonWebKey | BufferSource, algorithm: types.AlgorithmIdentifier, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise; + public async importKey(...args: any[]): Promise { + this.checkRequiredArguments(args, 5, "importKey"); + const [format, keyData, algorithm, extractable, keyUsages, ...params] = args; + + const preparedAlgorithm = this.prepareAlgorithm(algorithm); + const provider = this.getProvider(preparedAlgorithm.name); + + if (["pkcs8", "spki", "raw"].indexOf(format) !== -1) { + const preparedData = BufferSourceConverter.toArrayBuffer(keyData as BufferSource); + + return provider.importKey(format, preparedData, { ...preparedAlgorithm, name: provider.name }, extractable, keyUsages, ...params); + } else { + if (!(keyData as types.JsonWebKey).kty) { + throw new TypeError("keyData: Is not JSON"); + } + } + return provider.importKey(format, keyData as types.JsonWebKey, { ...preparedAlgorithm, name: provider.name }, extractable, keyUsages, ...params); + } + + public async wrapKey(format: types.KeyFormat, key: types.CryptoKey, wrappingKey: types.CryptoKey, wrapAlgorithm: types.AlgorithmIdentifier, ...args: any[]): Promise { + let keyData = await this.exportKey(format, key, ...args); + if (format === "jwk") { + const json = JSON.stringify(keyData); + keyData = Convert.FromUtf8String(json); + } + + // encrypt key data + const preparedAlgorithm = this.prepareAlgorithm(wrapAlgorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(keyData as ArrayBuffer); + const provider = this.getProvider(preparedAlgorithm.name); + return provider.encrypt({ ...preparedAlgorithm, name: provider.name }, wrappingKey, preparedData, { keyUsage: false }, ...args); + } + + public async unwrapKey(format: types.KeyFormat, wrappedKey: BufferSource, unwrappingKey: types.CryptoKey, unwrapAlgorithm: types.AlgorithmIdentifier, unwrappedKeyAlgorithm: types.AlgorithmIdentifier, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + // decrypt wrapped key + const preparedAlgorithm = this.prepareAlgorithm(unwrapAlgorithm); + const preparedData = BufferSourceConverter.toArrayBuffer(wrappedKey); + const provider = this.getProvider(preparedAlgorithm.name); + let keyData = await provider.decrypt({ ...preparedAlgorithm, name: provider.name }, unwrappingKey, preparedData, { keyUsage: false }, ...args); + if (format === "jwk") { + try { + keyData = JSON.parse(Convert.ToUtf8String(keyData)); + } catch (e) { + const error = new TypeError("wrappedKey: Is not a JSON"); + (error as any).internal = e; + throw error; + } + } + + // import key + return this.importKey(format, keyData, unwrappedKeyAlgorithm, extractable, keyUsages, ...args); + } + + protected checkRequiredArguments(args: any[], size: number, methodName: string) { + if (args.length < size) { + throw new TypeError(`Failed to execute '${methodName}' on 'SubtleCrypto': ${size} arguments required, but only ${args.length} present`); + } + } + + protected prepareAlgorithm(algorithm: types.AlgorithmIdentifier): types.Algorithm | types.HashedAlgorithm { + if (typeof algorithm === "string") { + return { + name: algorithm, + } as types.Algorithm; + } + if (SubtleCrypto.isHashedAlgorithm(algorithm)) { + const preparedAlgorithm = { ...algorithm }; + preparedAlgorithm.hash = this.prepareAlgorithm(algorithm.hash); + return preparedAlgorithm as types.HashedAlgorithm; + } + return { ...algorithm }; + } + + protected getProvider(name: string): ProviderCrypto { + const provider = this.providers.get(name); + if (!provider) { + throw new AlgorithmError("Unrecognized name"); + } + return provider; + } + + protected checkCryptoKey(key: types.CryptoKey): asserts key is BaseCryptoKey { + if (!(key instanceof BaseCryptoKey)) { + throw new TypeError(`Key is not of type 'CryptoKey'`); + } + } + +} diff --git a/packages/core/src/utils/index.ts b/packages/core/src/utils/index.ts new file mode 100644 index 0000000..3e21201 --- /dev/null +++ b/packages/core/src/utils/index.ts @@ -0,0 +1,2 @@ +export * from "./pem_converter"; +export * from "./is_jwk"; diff --git a/packages/core/src/utils/is_jwk.ts b/packages/core/src/utils/is_jwk.ts new file mode 100644 index 0000000..7d68a82 --- /dev/null +++ b/packages/core/src/utils/is_jwk.ts @@ -0,0 +1,5 @@ +import * as types from "@peculiar/webcrypto-types"; + +export function isJWK(data: any): data is types.JsonWebKey { + return typeof data === "object" && "kty" in data; +} diff --git a/packages/core/src/utils/pem_converter.ts b/packages/core/src/utils/pem_converter.ts new file mode 100644 index 0000000..d64bb9c --- /dev/null +++ b/packages/core/src/utils/pem_converter.ts @@ -0,0 +1,106 @@ +import { BufferSource, Convert } from "pvtsutils"; + +/** + * PEM converter + */ +export class PemConverter { + + /** + * Converts PEM to Array buffer + * @param pem PEM string + */ + public static toArrayBuffer(pem: string) { + const base64 = pem + .replace(/-{5}(BEGIN|END) .*-{5}/g, "") + .replace("\r", "") + .replace("\n", ""); + return Convert.FromBase64(base64); + } + + /** + * Converts PEM to Uint8Array + * @param pem PEM string + */ + public static toUint8Array(pem: string) { + const bytes = this.toArrayBuffer(pem); + return new Uint8Array(bytes); + } + + /** + * Converts buffer source to PEM + * @param buffer Buffer source + * @param tag PEM tag name + */ + public static fromBufferSource(buffer: BufferSource, tag: string) { + const base64 = Convert.ToBase64(buffer); + let sliced: string; + let offset = 0; + const rows: string[] = []; + while (true) { + sliced = base64.slice(offset, offset = offset + 64); + if (sliced.length) { + rows.push(sliced); + if (sliced.length < 64) { + break; + } + } else { + break; + } + } + + const upperCaseTag = tag.toUpperCase(); + return `-----BEGIN ${upperCaseTag}-----\n${rows.join("\n")}\n-----END ${upperCaseTag}-----`; + } + + /** + * Returns `true` if incoming data is PEM string, otherwise `false` + * @param data Data + */ + public static isPEM(data: string) { + // tslint:disable-next-line:max-line-length + return /-----BEGIN .+-----[A-Za-z0-9+\/\+\=\s\n]+-----END .+-----/i.test(data); + } + + /** + * Returns tag name from PEM string + * @param pem PEM string + */ + public static getTagName(pem: string) { + if (!this.isPEM(pem)) { + throw new Error("Bad parameter. Incoming data is not right PEM"); + } + const res = /-----BEGIN (.+)-----/.exec(pem); + if (!res) { + throw new Error("Cannot get tag from PEM"); + } + + return res[1]; + } + + /** + * Returns `true` if tag name from PEM matches to tagName parameter + * @param pem PEM string + * @param tagName Tag name for comparison + */ + public static hasTagName(pem: string, tagName: string) { + const tag = this.getTagName(pem); + return tagName.toLowerCase() === tag.toLowerCase(); + } + + public static isCertificate(pem: string) { + return this.hasTagName(pem, "certificate"); + } + + public static isCertificateRequest(pem: string) { + return this.hasTagName(pem, "certificate request"); + } + + public static isCRL(pem: string) { + return this.hasTagName(pem, "x509 crl"); + } + + public static isPublicKey(pem: string) { + return this.hasTagName(pem, "public key"); + } + +} diff --git a/packages/core/test/aes.spec.ts b/packages/core/test/aes.spec.ts new file mode 100644 index 0000000..19c3fe5 --- /dev/null +++ b/packages/core/test/aes.spec.ts @@ -0,0 +1,257 @@ +import * as assert from "assert"; +import * as core from "@peculiar/webcrypto-core"; + +// tslint:disable:max-classes-per-file + +context("AES", () => { + + context("AES-CBC", () => { + + const provider = Reflect.construct(core.AesCbcProvider, []) as core.AesCbcProvider; + + context("checkGenerateKeyParams", () => { + + it("error if `length` is not present", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ name: "AES-CBC" } as any); + }, Error); + }); + + it("error if `length` has wrong type", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ name: "AES-CBC", length: "s" } as any); + }, TypeError); + }); + + it("error if `length` has wrong value", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ name: "AES-CBC", length: 1 } as any); + }, TypeError); + }); + + [128, 192, 256].forEach((length) => { + it(`correct length:${length}`, () => { + provider.checkGenerateKeyParams({ name: "AES-CBC", length } as any); + }); + }); + + }); + + }); + + context("AES-CBC", () => { + + const provider = Reflect.construct(core.AesCbcProvider, []) as core.AesCbcProvider; + + context("checkAlgorithmParams", () => { + + it("error if parameter `iv` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if parameter `iv` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: "wrong type", + } as any); + }, TypeError); + }); + + it("error if parameter `iv` has wrong length", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: new Uint8Array(20), + } as any); + }, TypeError); + }); + + it("correct parameter `iv`", () => { + provider.checkAlgorithmParams({ + iv: new Uint8Array(16), + } as any); + }); + + }); + + }); + + context("AES-CMAC", () => { + + const provider = Reflect.construct(core.AesCmacProvider, []) as core.AesCmacProvider; + + context("checkAlgorithmParams", () => { + + it("error if parameter `length` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if parameter `length` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + length: "128", + } as any); + }, TypeError); + }); + + it("error if parameter `length` less than 1", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + length: 0, + } as any); + }, core.OperationError); + }); + + it("correct parameter `length`", () => { + provider.checkAlgorithmParams({ + length: 1, + } as any); + }); + + }); + + }); + + context("AES-CTR", () => { + + const provider = Reflect.construct(core.AesCtrProvider, []) as core.AesCtrProvider; + + context("checkAlgorithmParams", () => { + + it("error if parameter `counter` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + length: 1, + } as any); + }, Error); + }); + + it("error if parameter `counter` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + counter: "wrong type", + length: 1, + } as any); + }, TypeError); + }); + + it("error if parameter `counter` has wrong length", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + counter: new ArrayBuffer(10), + length: 1, + } as any); + }, TypeError); + }); + + it("counter is ArrayBuffer", () => { + provider.checkAlgorithmParams({ + counter: new ArrayBuffer(16), + length: 1, + } as any); + }); + + it("counter is ArrayBufferView", () => { + provider.checkAlgorithmParams({ + counter: new Uint8Array(16), + length: 1, + } as any); + }); + + it("error if parameter `length` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + counter: new Uint8Array(16), + } as any); + }, Error); + }); + + it("error if parameter `length` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + counter: new Uint8Array(16), + length: "1", + } as any); + }, TypeError); + }); + + it("error if parameter `length` less than 1", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + counter: new Uint8Array(16), + length: 0, + } as any); + }, core.OperationError); + }); + + it("correct parameter `length`", () => { + provider.checkAlgorithmParams({ + counter: new Uint8Array(16), + length: 1, + } as any); + }); + + }); + + }); + + context("AES-GCM", () => { + + const provider = Reflect.construct(core.AesGcmProvider, []) as core.AesGcmProvider; + + context("checkAlgorithmParams", () => { + + it("error if parameter `iv` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if parameter `iv` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: "wrong type", + } as any); + }, TypeError); + }); + + it("error if parameter `iv` has wrong length", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: new Uint8Array(0), + } as any); + }, core.OperationError); + }); + + it("correct parameter `iv`", () => { + provider.checkAlgorithmParams({ + iv: new ArrayBuffer(1), + } as any); + }); + + it("error if parameter `tagLength` has wrong value", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: new ArrayBuffer(1), + tagLength: 33, + } as any); + }, core.OperationError); + }); + + [32, 64, 96, 104, 112, 120, 128].forEach((tagLength) => { + it(`correct tagLength: ${tagLength}`, () => { + provider.checkAlgorithmParams({ + iv: new ArrayBuffer(1), + tagLength, + } as any); + }); + }); + + }); + + }); + +}); diff --git a/packages/core/test/crypto.spec.ts b/packages/core/test/crypto.spec.ts new file mode 100644 index 0000000..3e07f03 --- /dev/null +++ b/packages/core/test/crypto.spec.ts @@ -0,0 +1,21 @@ +import * as assert from "assert"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; + +context("Crypto", () => { + + it("Crypto matches to globalThis.Crypto", () => { + class MyCrypto extends core.Crypto { + public subtle = new core.SubtleCrypto(); + public getRandomValues(array: T): T { + throw new Error("Method not implemented."); + } + + } + + let crypto: types.Crypto; + crypto = new MyCrypto(); + assert.ok(crypto); + }); + +}); diff --git a/packages/core/test/des.spec.ts b/packages/core/test/des.spec.ts new file mode 100644 index 0000000..6506814 --- /dev/null +++ b/packages/core/test/des.spec.ts @@ -0,0 +1,90 @@ +import * as types from "@peculiar/webcrypto-types"; +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +class DesTestProvider extends core.DesProvider { + public keySizeBits = 64; + public ivSize = 8; + public name = "DES-TEST"; + + public onGenerateKey(algorithm: import("../src/des").DesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + public onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey): Promise { + throw new Error("Method not implemented."); + } + public onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: import("../src/des").DesImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + public onEncrypt(algorithm: import("../src/des").DesParams, key: core.BaseCryptoKey, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } + public onDecrypt(algorithm: import("../src/des").DesParams, key: core.BaseCryptoKey, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } +} + +context("DES", () => { + + const provider = new DesTestProvider(); + + context("checkAlgorithmParams", () => { + + it("error if `iv` is not present", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + } as any); + }, Error); + }); + + it("error if `iv` has wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: "wrong type", + } as any); + }, TypeError); + }); + + it("error if `iv` has wrong length", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ + iv: new ArrayBuffer(9), + } as any); + }, TypeError); + }); + + it("correct `iv` length", () => { + provider.checkAlgorithmParams({ + iv: new Uint8Array(8), + } as any); + }); + + }); + + context("checkGenerateKeyParams", () => { + + it("error if `length` is not present", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({} as any); + }, Error); + }); + + it("error if `length` has wrong type", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ length: "8" } as any); + }, TypeError); + }); + + it("error if `length` has wrong value", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ length: 8 } as any); + }, core.OperationError); + }); + + it("correct value", () => { + provider.checkGenerateKeyParams({ length: 64 } as any); + }); + + }); + +}); diff --git a/packages/core/test/ec.spec.ts b/packages/core/test/ec.spec.ts new file mode 100644 index 0000000..512d898 --- /dev/null +++ b/packages/core/test/ec.spec.ts @@ -0,0 +1,231 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; +import { Convert } from "pvtsutils"; + +// tslint:disable:max-classes-per-file + +context("EC", () => { + + context("EcUtils", () => { + context("public point", () => { + it("encode/decode point without padding", () => { + const point = { + x: new Uint8Array([1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4]), + y: new Uint8Array([5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8]), + }; + const encoded = core.EcUtils.encodePoint(point, 160); + + assert.strictEqual(Convert.ToHex(encoded), "0401010101010202020202030303030304040404040505050505060606060607070707070808080808"); + + const decoded = core.EcUtils.decodePoint(encoded, 160); + assert.strictEqual(Convert.ToHex(decoded.x), Convert.ToHex(point.x)); + assert.strictEqual(Convert.ToHex(decoded.y), Convert.ToHex(point.y)); + }); + it("decode uncompressed point ", () => { + const uncompressedPoint = new Uint8Array(Convert.FromHex("0400010101010202020202030303030304040404040005050505060606060607070707070808080808")); + const decoded = core.EcUtils.decodePoint(uncompressedPoint, 160); + assert.strictEqual(Convert.ToHex(decoded.x), "0001010101020202020203030303030404040404"); + assert.strictEqual(Convert.ToHex(decoded.y), "0005050505060606060607070707070808080808"); + }); + }); + context("signature point", () => { + it("encode/decode", () => { + const encodedHex = "00f3e308185c2d6cb59ec216ba8ce31e0a27db431be250807e604cd858494eb9d1de066b0dc7964f64b31e2f8da7f00741b5ba7e3972fe476099d53f5c5a39905a1f009fc215304c42100a0eec7b9d0bbc5f59c838b604bcceb6ebffd4870c83e76d8eca92e689032caddc69aa87a833216163589f97ce6cb4d10c84b7d6a949e73ca1c5"; + const decoded = core.EcUtils.decodeSignature(Convert.FromHex(encodedHex), 521); + assert.strictEqual(Convert.ToHex(decoded.r), "f3e308185c2d6cb59ec216ba8ce31e0a27db431be250807e604cd858494eb9d1de066b0dc7964f64b31e2f8da7f00741b5ba7e3972fe476099d53f5c5a39905a1f"); + assert.strictEqual(Convert.ToHex(decoded.s), "9fc215304c42100a0eec7b9d0bbc5f59c838b604bcceb6ebffd4870c83e76d8eca92e689032caddc69aa87a833216163589f97ce6cb4d10c84b7d6a949e73ca1c5"); + + const encoded = core.EcUtils.encodeSignature(decoded, 521); + assert.strictEqual(Convert.ToHex(encoded), encodedHex); + }); + }); + }); + + context("Base", () => { + + class EcTestProvider extends core.EllipticProvider { + public namedCurves = ["P-1", "P-2"]; + public name = "ECC"; + public usages: types.ProviderKeyUsages = { + privateKey: ["sign"], + publicKey: ["verify"], + }; + public onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + public onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey): Promise { + throw new Error("Method not implemented."); + } + public onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + } + + const provider = new EcTestProvider(); + + context("checkGenerateKeyParams", () => { + + it("error if `namedCurve` is missing", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({} as any); + }, Error); + }); + + it("error if `namedCurve` is not of type String", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ namedCurve: 123 } as any); + }, TypeError); + }); + + it("error if `namedCurve` is not value from list", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ namedCurve: "P-256" } as any); + }, core.OperationError); + }); + + it("correct `namedCurve`", () => { + provider.checkGenerateKeyParams({ namedCurve: "P-2" } as any); + }); + + }); + + }); + + context("ECDH", () => { + + const provider = Reflect.construct(core.EcdhProvider, []) as core.EcdhProvider; + + context("", () => { + + context("checkAlgorithmParams", () => { + + it("error if `public` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if `public` is not instance of CryptoKey", () => { + assert.throws(() => { + const key = {}; + provider.checkAlgorithmParams({ public: key } as any); + }, Error); + }); + + it("error if `public` is not public CryptoKey", () => { + assert.throws(() => { + const key = new core.BaseCryptoKey(); + key.type = "secret"; + provider.checkAlgorithmParams({ public: key } as any); + }, Error); + }); + + it("error if `public` is wrong CryptoKey alg", () => { + assert.throws(() => { + const key = new core.BaseCryptoKey(); + key.type = "public"; + key.algorithm = { name: "ECDSA" }; + provider.checkAlgorithmParams({ public: key } as any); + }, Error); + }); + + it("correct `public`", () => { + const key = new core.BaseCryptoKey(); + key.type = "public"; + key.algorithm = { name: "ECDH" }; + provider.checkAlgorithmParams({ public: key } as any); + }); + + }); + + }); + + }); + + context("ECDSA", () => { + + const provider = Reflect.construct(core.EcdsaProvider, []) as core.EcdsaProvider; + + context("checkAlgorithmParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if `hash` has wrong value", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "wrong" } } as any); + }, core.OperationError); + }); + + it("correct `hash`", () => { + provider.checkAlgorithmParams({ hash: { name: "SHA-1" } } as any); + }); + + }); + + }); + + context("ECDH-ES", () => { + class TestEcdhEsProvider extends core.EcdhEsProvider { + public async onDeriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: core.BaseCryptoKey, length: number, ...args: any[]): Promise { + return null as any; + } + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + return null as any; + } + public async onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey, ...args: any[]): Promise { + return null as any; + } + public async onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + return null as any; + } + } + const provider = new TestEcdhEsProvider(); + + context("generateKey", () => { + ["X25519", "x448"].forEach((namedCurve) => { + it(namedCurve, async () => { + const keys = await provider.generateKey({ name: "ECDH-ES", namedCurve } as types.EcKeyGenParams, false, ["deriveBits", "deriveKey"]); + assert.strictEqual(keys, null); + }); + }); + }); + + }); + + context("EdDSA", () => { + class TestEdDsaProvider extends core.EdDsaProvider { + public async onSign(algorithm: types.EcdsaParams, key: core.BaseCryptoKey, data: ArrayBuffer, ...args: any[]): Promise { + return null as any; + } + public async onVerify(algorithm: types.EcdsaParams, key: core.BaseCryptoKey, signature: ArrayBuffer, data: ArrayBuffer, ...args: any[]): Promise { + return true; + } + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + return null as any; + } + public onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey, ...args: any[]): Promise { + return null as any; + } + public onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { + return null as any; + } + } + const provider = new TestEdDsaProvider(); + + context("generateKey", () => { + ["Ed25519", "ed448"].forEach((namedCurve) => { + it(namedCurve, async () => { + const keys = await provider.generateKey({ name: "EdDSA", namedCurve } as types.EcKeyGenParams, false, ["sign", "verify"]); + assert.strictEqual(keys, null); + }); + }); + }); + + }); + +}); diff --git a/packages/core/test/ed.spec.ts b/packages/core/test/ed.spec.ts new file mode 100644 index 0000000..d28079e --- /dev/null +++ b/packages/core/test/ed.spec.ts @@ -0,0 +1,63 @@ +import { AsnConvert, AsnSerializer } from "@peculiar/asn1-schema"; +import * as assert from "assert"; +import { Convert } from "pvtsutils"; +import * as schema from "packages/core/src/schema"; + +context("ED", () => { + + context("asn", () => { + + it("spki - jwk", () => { + const pem = "MCowBQYDK2VwAyEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE="; + + const keyInfo = AsnConvert.parse(Convert.FromBase64(pem), schema.PublicKeyInfo); + const key = new schema.EdPublicKey(keyInfo.publicKey); + const jwk = key.toJSON(); + + const key2 = new schema.EdPublicKey(); + key2.fromJSON(jwk); + assert.strictEqual( + Convert.ToBase64(AsnSerializer.serialize(key2)), + Convert.ToBase64(AsnSerializer.serialize(key)), + ); + }); + + context("pkcs8 -jwk", () => { + + it("without public key", () => { + const pem = "MC4CAQAwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhC"; + + const keyInfo = AsnConvert.parse(Convert.FromBase64(pem), schema.OneAsymmetricKey); + assert.strictEqual(keyInfo.publicKey, undefined); + const key = AsnConvert.parse(keyInfo.privateKey, schema.EdPrivateKey); + const jwk = key.toJSON(); + + const key2 = new schema.EdPrivateKey(); + key2.fromJSON(jwk); + assert.strictEqual( + Convert.ToBase64(AsnSerializer.serialize(key2)), + Convert.ToBase64(AsnSerializer.serialize(key)), + ); + }); + + it("with public key", () => { + const pem = "MHICAQEwBQYDK2VwBCIEINTuctv5E1hK1bbY8fdp+K06/nwoy/HU++CXqI9EdVhCoB8wHQYKKoZIhvcNAQkJFDEPDA1DdXJkbGUgQ2hhaXJzgSEAGb9ECWmEzf6FQbrBZ9w7lshQhqowtrbLDFw4rXAxZuE="; + + const keyInfo = AsnConvert.parse(Convert.FromBase64(pem), schema.OneAsymmetricKey); + assert.ok(keyInfo.publicKey); + const key = AsnConvert.parse(keyInfo.privateKey, schema.EdPrivateKey); + const jwk = key.toJSON(); + + const key2 = new schema.EdPrivateKey(); + key2.fromJSON(jwk); + assert.strictEqual( + Convert.ToBase64(AsnSerializer.serialize(key2)), + Convert.ToBase64(AsnSerializer.serialize(key)), + ); + }); + + }); + + }); + +}); diff --git a/packages/core/test/hkdf.spec.ts b/packages/core/test/hkdf.spec.ts new file mode 100644 index 0000000..16a29e7 --- /dev/null +++ b/packages/core/test/hkdf.spec.ts @@ -0,0 +1,66 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +context("HKDF", () => { + + const provider = Reflect.construct(core.HkdfProvider, []) as core.HkdfProvider; + + context("checkAlgorithmParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ salt: new Uint8Array(4), info: new Uint8Array(4) } as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "WRONG" }, salt: new Uint8Array(4), info: new Uint8Array(4) } as any); + }, core.OperationError); + }); + + it("error if `salt` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, info: new Uint8Array(4) } as any); + }, Error); + }); + + it("error if `salt` wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: "wrong", info: new Uint8Array(4) } as any); + }, TypeError); + }); + + it("error if `info` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4) } as any); + }, Error); + }); + + it("error if `info` wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, info: "wrong", salt: new Uint8Array(4) } as any); + }, TypeError); + }); + + it("correct value", () => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4), info: new Uint8Array(4) } as any); + }); + + }); + + context("checkImportKey", () => { + + it("throw error if extractable is true", () => { + assert.throws(() => { + provider.checkImportKey("raw", new ArrayBuffer(0), { name: "HKDF" }, true, ["deriveBits"]); + }, SyntaxError); + }); + + it("correct extractable value", () => { + provider.checkImportKey("raw", new ArrayBuffer(0), { name: "HKDF" }, false, ["deriveBits"]); + }); + + }); + +}); diff --git a/packages/core/test/hmac.spec.ts b/packages/core/test/hmac.spec.ts new file mode 100644 index 0000000..cbc796d --- /dev/null +++ b/packages/core/test/hmac.spec.ts @@ -0,0 +1,88 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +context("HMAC", () => { + + const provider = Reflect.construct(core.HmacProvider, []) as core.HmacProvider; + + context("checkGenerateKeyParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({} as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ hash: { name: "WRONG" } } as any); + }, core.OperationError); + }); + + it("error if `length` is not of type Number", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ hash: { name: "SHA-256" }, length: "128" } as any); + }, TypeError); + }); + + it("error if `length` is less than 1", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ hash: { name: "SHA-256" }, length: 0 } as any); + }, RangeError); + }); + + it("default length", () => { + provider.checkGenerateKeyParams({ hash: { name: "SHA-256" } } as any); + }); + + it("custom length", () => { + provider.checkGenerateKeyParams({ hash: { name: "SHA-256", length: 128 } } as any); + }); + + }); + + context("getDefaultLength", () => { + + it("SHA-1", () => { + const len = provider.getDefaultLength("SHA-1"); + assert.equal(len, 512); + }); + + it("SHA-256", () => { + const len = provider.getDefaultLength("SHA-256"); + assert.equal(len, 512); + }); + + it("SHA-384", () => { + const len = provider.getDefaultLength("SHA-384"); + assert.equal(len, 512); + }); + + it("SHA-512", () => { + const len = provider.getDefaultLength("SHA-512"); + assert.equal(len, 512); + }); + + it("error if unknown name", () => { + assert.throws(() => { + provider.getDefaultLength("SHA-521"); + }, Error); + }); + + }); + + context("checkImportParams", () => { + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkImportParams({} as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkImportParams({ hash: { name: "WRONG" } } as any); + }, core.OperationError); + }); + }); + +}); diff --git a/packages/core/test/jwk_utils.spec.ts b/packages/core/test/jwk_utils.spec.ts new file mode 100644 index 0000000..d24a476 --- /dev/null +++ b/packages/core/test/jwk_utils.spec.ts @@ -0,0 +1,50 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; +import * as crypto from "crypto"; +import { Convert } from "pvtsutils"; + +// crypto.webcrypto +const ctx = crypto.webcrypto ? context : context.skip; + +ctx("JWK utils", () => { + + it("format with odd removing", () => { + const jwk: types.JsonWebKey = { + n: "n value", + ext: true, + e: "e value", + }; + + const formattedJwk = core.JwkUtils.format(jwk, true); + assert.strictEqual(JSON.stringify(formattedJwk), JSON.stringify({ + e: "e value", + n: "n value", + })); + }); + + it("format without removing", () => { + const jwk: types.JsonWebKey = { + n: "n value", + ext: true, + e: "e value", + }; + + const formattedJwk = core.JwkUtils.format(jwk, false); + assert.strictEqual(JSON.stringify(formattedJwk), JSON.stringify({ + e: "e value", + ext: true, + n: "n value", + })); + }); + + it("thumbprint", async () => { + const digest = await core.JwkUtils.thumbprint("SHA-256", { + e: "e value", + n: "n value", + }, crypto.webcrypto as any); + + assert.strictEqual(Convert.ToBase64(digest), "MkHJT3yHfy0O9t4OHK/331Pb3HNa4LRG62yPa4NNnSc="); + }); + +}); diff --git a/packages/core/test/key.spec.ts b/packages/core/test/key.spec.ts new file mode 100644 index 0000000..c61698d --- /dev/null +++ b/packages/core/test/key.spec.ts @@ -0,0 +1,15 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +context("CryptoKey", () => { + + context("isKeyType", () => { + it("correct key type", () => { + assert.equal(core.BaseCryptoKey.isKeyType("secret"), true); + }); + it("incorrect key type", () => { + assert.equal(core.BaseCryptoKey.isKeyType("Secret"), false); + }); + }); + +}); diff --git a/packages/core/test/pbkdf.spec.ts b/packages/core/test/pbkdf.spec.ts new file mode 100644 index 0000000..3c30027 --- /dev/null +++ b/packages/core/test/pbkdf.spec.ts @@ -0,0 +1,72 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +context("HMAC", () => { + + const provider = Reflect.construct(core.Pbkdf2Provider, []) as core.Pbkdf2Provider; + + context("checkAlgorithmParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ salt: new Uint8Array(4), iterations: 1000 } as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "WRONG" }, salt: new Uint8Array(4), iterations: 1000 } as any); + }, core.OperationError); + }); + + it("error if `salt` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, iterations: 1000 } as any); + }, Error); + }); + + it("error if `salt` wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: "wrong", iterations: 1000 } as any); + }, TypeError); + }); + + it("error if `iterations` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4) } as any); + }, Error); + }); + + it("error if `iterations` wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4), iterations: "123" } as any); + }, TypeError); + }); + + it("error if `iterations` less than 1", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4), iterations: 0 } as any); + }, TypeError); + }); + + it("correct value", () => { + provider.checkAlgorithmParams({ hash: { name: "SHA-256" }, salt: new Uint8Array(4), iterations: 1000 } as any); + }); + + }); + + context("checkImportKey", () => { + + it("throw error if extractable is true", () => { + assert.throws(() => { + provider.checkImportKey("raw", new ArrayBuffer(0), { name: "PBKDF2" }, true, ["deriveBits"]); + }, SyntaxError); + }); + + it("correct extractable value", () => { + provider.checkImportKey("raw", new ArrayBuffer(0), { name: "PBKDF2" }, false, ["deriveBits"]); + }); + + }); + +}); diff --git a/packages/core/test/pem_converter.spec.ts b/packages/core/test/pem_converter.spec.ts new file mode 100644 index 0000000..bb03205 --- /dev/null +++ b/packages/core/test/pem_converter.spec.ts @@ -0,0 +1,112 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; +import { Convert } from "pvtsutils"; + +context("PemConverter", () => { + + // tslint:disable-next-line:max-line-length + const bytes = Convert.FromHex("30819f300d06092a864886f70d010101050003818d0030818902818100f615b745314ffe4669255dfe68953184bb8e5db54eecd35b4c51ee899ce7e60aaf19cc765d924f94be93d6809ba506fab26b9f8ef0cf6ab2aec1942da222992f8dad2e621845f014f9e831a529665faf0a9b8ca97356a602ce8d17cd3469aafa2de82546773540fa480510d1906c78c87b81850c26fdaeccce37cd5fdeba7e050203010001"); + // tslint:disable-next-line:prefer-template + const vector = "-----BEGIN PUBLIC KEY-----\n" + + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD2FbdFMU/+RmklXf5olTGEu45d\n" + + "tU7s01tMUe6JnOfmCq8ZzHZdkk+UvpPWgJulBvqya5+O8M9qsq7BlC2iIpkvja0u\n" + + "YhhF8BT56DGlKWZfrwqbjKlzVqYCzo0XzTRpqvot6CVGdzVA+kgFENGQbHjIe4GF\n" + + "DCb9rszON81f3rp+BQIDAQAB\n" + + "-----END PUBLIC KEY-----"; + + it("fromBufferSource", () => { + const pem = core.PemConverter.fromBufferSource(bytes, "public key"); + + assert.equal(pem, vector); + }); + + it("fromBufferSource multiple 64", () => { + const pem = core.PemConverter.fromBufferSource(Buffer.from("1234567890abcdef1234567890abcdef1234567890abcdef"), "public key"); + + assert.equal(pem, "-----BEGIN PUBLIC KEY-----\n" + + "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWYxMjM0NTY3ODkwYWJjZGVm\n" + + "-----END PUBLIC KEY-----"); + }); + + it("toArrayBuffer", () => { + const buf = core.PemConverter.toArrayBuffer(vector); + + assert.equal(Convert.ToHex(buf), Convert.ToHex(bytes)); + }); + + it("toUint8Array", () => { + const buf = core.PemConverter.toUint8Array(vector); + + assert.equal(Convert.ToHex(buf), Convert.ToHex(bytes)); + }); + + context("isPEM", () => { + // tslint:disable-next-line:prefer-template + const pem = "-----BEGIN CERTIFICATE------\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\n" + + "-----END CERTIFICATE------"; + + it("return true if correct PEM", () => { + assert.equal(core.PemConverter.isPEM(pem), true); + }); + + it("return true if inline PEM", () => { + assert.equal(core.PemConverter.isPEM(pem.replace(/\n/g, "")), true); + }); + + it("return false if correct PEM", () => { + // tslint:disable-next-line:prefer-template + const wrongPem = "----- BEGIN CERTIFICATE ------\n" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\n" + + "----- END CERTIFICATE ------"; + assert.equal(core.PemConverter.isPEM(wrongPem), false); + }); + + }); + + context("getTagName", () => { + + it("get tag name from spki", () => { + const tagName = core.PemConverter.getTagName(vector); + assert.equal(tagName, "PUBLIC KEY"); + }); + + it("throw error if data is wrong PEM", () => { + assert.throws(() => core.PemConverter.getTagName("----- BEGIN CERTIFICATE ------")); + }); + + }); + + context("hasTagName", () => { + + it("return true if tag names are equal", () => { + assert.equal(core.PemConverter.hasTagName(vector, "public key"), true); + }); + + it("return false if tag names are not equal", () => { + assert.equal(core.PemConverter.hasTagName(vector, "PRIVATE KEY"), false); + }); + + }); + + it("isCertificate", () => { + const pem = core.PemConverter.fromBufferSource(new Uint8Array([1, 0, 1]), "certificate"); + assert.equal(core.PemConverter.isCertificate(pem), true); + }); + + it("isCRL", () => { + const pem = core.PemConverter.fromBufferSource(new Uint8Array([1, 0, 1]), "X509 CRL"); + assert.equal(core.PemConverter.isCRL(pem), true); + }); + + it("isCertificateRequest", () => { + const pem = core.PemConverter.fromBufferSource(new Uint8Array([1, 0, 1]), "certificate request"); + assert.equal(core.PemConverter.isCertificateRequest(pem), true); + }); + + it("isPublicKey", () => { + const pem = core.PemConverter.fromBufferSource(new Uint8Array([1, 0, 1]), "public key"); + assert.equal(core.PemConverter.isPublicKey(pem), true); + }); + +}); diff --git a/packages/core/test/provider.spec.ts b/packages/core/test/provider.spec.ts new file mode 100644 index 0000000..6e24728 --- /dev/null +++ b/packages/core/test/provider.spec.ts @@ -0,0 +1,174 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; + +class TestProvider extends core.ProviderCrypto { + public name = "CUSTOM-ALG"; + public usages: types.KeyUsage[] = ["sign"]; +} + +class TestAsymmetricProvider extends core.ProviderCrypto { + public name = "CUSTOM-ALG"; + public usages: types.ProviderKeyPairUsage = { + privateKey: ["sign"], + publicKey: ["verify"], + }; +} + +context("ProviderCrypto", () => { + + const crypto = new TestProvider(); + + context("checkGenerateKey", () => { + + it("error if `keyUsages` argument is empty list", () => { + assert.throws(() => { + crypto.checkGenerateKey({ name: "CUSTOM-ALG" }, true, []); + }, TypeError); + }); + + it("check usages for symmetric key", () => { + const aProv = new TestAsymmetricProvider(); + aProv.checkGenerateKey({ name: "CUSTOM-ALG" }, true, ["sign", "verify"]); + }); + + }); + + context("digest", () => { + + it("correct data", async () => { + await assert.rejects( + crypto.digest({ name: "custom-alg" }, new ArrayBuffer(0)), + core.UnsupportedOperationError, + ); + }); + + it("wrong name of algorithm", async () => { + await assert.rejects( + crypto.digest({ name: "wrong" }, new ArrayBuffer(0)), + ); + }); + + }); + + context("generateKey", () => { + + it("correct data", async () => { + await assert.rejects( + crypto.generateKey({ name: "custom-alg" }, true, ["sign"]), + core.UnsupportedOperationError, + ); + }); + + it("wrong name of algorithm", async () => { + await assert.rejects( + crypto.generateKey({ name: "wrong" }, false, ["sign"]), + ); + }); + + it("wrong key usages", async () => { + await assert.rejects( + crypto.generateKey({ name: "custom-alg" }, false, ["verify"]), + ); + }); + + }); + + context("sign", () => { + + const correctKey = core.BaseCryptoKey.create( + { name: "custom-alg" }, + "secret", + false, + ["sign"], + ); + + it("correct data", async () => { + await assert.rejects( + crypto.sign( + { name: "custom-alg" }, + correctKey, + new ArrayBuffer(0), + ), + core.UnsupportedOperationError, + ); + }); + + it("wrong name of algorithm", async () => { + await assert.rejects( + crypto.sign( + { name: "wrong" }, + correctKey, + new ArrayBuffer(0), + ), + ); + }); + + it("wrong key type", async () => { + await assert.rejects( + crypto.sign( + { name: "custom-alg" }, + {} as core.BaseCryptoKey, + new ArrayBuffer(0), + ), + TypeError, + ); + }); + + it("wrong key algorithm", async () => { + await assert.rejects( + crypto.sign( + { name: "custom-alg" }, + core.BaseCryptoKey.create( + { name: "wrong" }, + "secret", + true, + ["sign", "decrypt"], + ), + new ArrayBuffer(0), + ), + core.AlgorithmError, + ); + }); + + it("wrong key usage", async () => { + await assert.rejects( + crypto.sign( + { name: "custom-alg" }, + core.BaseCryptoKey.create( + { name: "custom-alg" }, + "secret", + true, + ["verify"], + ), + new ArrayBuffer(0), + ), + core.CryptoError, + ); + }); + + }); + + context("checkDeriveBits", () => { + + it("error if length is not multiple 8", () => { + const algorithm: types.Algorithm = { name: "custom-alg" }; + const key = core.BaseCryptoKey.create(algorithm, "secret", false, ["deriveBits"]); + assert.throws(() => { + crypto.checkDeriveBits(algorithm, key, 7); + }, core.OperationError); + }); + + }); + + context("checkKeyFormat", () => { + + it("error if wrong value", () => { + assert.throws(() => { + crypto.checkKeyFormat("wrong"); + }, TypeError); + }); + + }); + +}); diff --git a/packages/core/test/rsa.spec.ts b/packages/core/test/rsa.spec.ts new file mode 100644 index 0000000..f2cfa0c --- /dev/null +++ b/packages/core/test/rsa.spec.ts @@ -0,0 +1,186 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as assert from "assert"; + +context("RSA", () => { + + context("RSASSA-PKCS1-v1_5", () => { + + const provider = Reflect.construct(core.RsaSsaProvider, []) as core.RsaSsaProvider; + + context("checkGenerateKeyParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 2048, + } as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-WRONG" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 2048, + } as any); + }, Error); + }); + + it("error if `publicExponent` is missing", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + modulusLength: 2048, + } as any); + }, Error); + }); + + it("error if `publicExponent` is wrong of type", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: [1, 0, 1], + modulusLength: 2048, + } as any); + }, TypeError); + }); + + it("error if `publicExponent` is value", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 1, 0]), + modulusLength: 2048, + } as any); + }, TypeError); + }); + + it("error if `modulusLength` is missing", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 0, 1]), + } as any); + }, Error); + }); + + it("error if `modulusLength` is wrong value", () => { + it("not multiple of 8 bits", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 12345, + } as any); + }, TypeError); + }); + it("less than 256", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 256 - 8, + } as any); + }, TypeError); + }); + it("more than 16384", () => { + assert.throws(() => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 16384 + 8, + } as any); + }, TypeError); + }); + }); + + it("correct value", () => { + provider.checkGenerateKeyParams({ + hash: { name: "SHA-256" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 4096, + } as any); + }); + + }); + + context("checkImportParams", () => { + + it("error if `hash` is missing", () => { + assert.throws(() => { + provider.checkImportParams({ + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 2048, + } as any); + }, Error); + }); + + it("error if `hash` is wrong", () => { + assert.throws(() => { + provider.checkImportParams({ + hash: { name: "SHA-WRONG" }, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 2048, + } as any); + }, Error); + }); + + }); + + }); + + context("RSA-OAEP", () => { + + const provider = Reflect.construct(core.RsaOaepProvider, []) as core.RsaOaepProvider; + + context("checkAlgorithmParams", () => { + + it("error if `label` is wrong type", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ label: "WRONG" } as any); + }, TypeError); + }); + + it("correct `label`", () => { + provider.checkAlgorithmParams({ label: new Uint8Array(4) } as any); + }); + + }); + + }); + + context("RSA-PSS", () => { + + const provider = Reflect.construct(core.RsaPssProvider, []) as core.RsaPssProvider; + + context("checkAlgorithmParams", () => { + + it("error if `saltLength` is missing", () => { + assert.throws(() => { + provider.checkAlgorithmParams({} as any); + }, Error); + }); + + it("error if `saltLength` is not of type Number", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ saltLength: "123" } as any); + }, TypeError); + }); + + it("error if `saltLength` is less than 0", () => { + assert.throws(() => { + provider.checkAlgorithmParams({ saltLength: -1 } as any); + }, RangeError); + }); + + it("correct `saltLength`", () => { + provider.checkAlgorithmParams({ saltLength: 8 } as any); + }); + + }); + + }); + +}); diff --git a/packages/core/test/schema/asn.spec.ts b/packages/core/test/schema/asn.spec.ts new file mode 100644 index 0000000..9e7c6c7 --- /dev/null +++ b/packages/core/test/schema/asn.spec.ts @@ -0,0 +1,114 @@ +import * as assert from "assert"; +import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; +import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; + +context("ASN1", () => { + + context("RSA", () => { + + context("PrivateKey", () => { + + const bytes = Buffer.from("308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100faa3f76e5daf5dc288a54b7a99d7c7a9437581a184d80bb1aaf54cdfe245b28f52edb4db4888199e78ce993407bfd93c8102231b173eca09d44bb127c152b2e7f3a806852ed1dc323a1a33a5fecc0217ea98ddeb7068c14ffbbbd14a7904b3657a663ab76d2d88b10db77bc1b22e8881e58665508af0c31da225d08f3b07ad05bd8cf4d25943bffd3bb57d4266582276089e126db030d8ef04e0c30eeb65c325558d98bfc43b2b0c52212f3294d3ad7a91fa2ec2e838b2e73a4db616ec6aad5592dfc046f7e3589741fa0f4662fcf4ffca767611475f05272b3ddbd09b757b56f0293089d39e2cdd35722cd69ea00b3181e6e7c5e531f6608db3da31ce82afad02030100010282010025698d3901adf8125e204244822b45e7dba4721da07d393da375ab2c6e139644338e3ce5508dd43925f23cc719f306a3b3e414466a715a6a1e30d0384d70a138e3536ce9bb63e2f8f2584fe652c2b3fb4aeed78d59c1a13d65a792e5896becb5549066ea53572d24b495f358a5d6b154a664a9c1dc8374b47b2c26d6026b3265b1d6e4448bd2253ce467ae99017c53af1fb085cdd5c8dc3cc66941beaa480295e907a936776f49e5e619d5e2e89e5a1bf220121c965b08b658d669464a4d0eb414efe11c8fa20987fae0758542ec69a9d335b01a78b8770b499272105629b4e81f04065644928f0b01bfb0294fbeb0e0e4e3ad6129d356fce820d35171126b1702818100fe042d914643ad84d8e5a0d0c3c7dc9b35ac60d96ef9305e74ead8419a1937c3a4d5b6b2d589f818ab0cfa4f6ee12fbeb85f7c117ba4eb489b31f0eecac4f8368b52b3339043a3160fa3535e1e45634947b582438149b062b73029bd2279793154153da0e120c48fe71c466783e6537ea9157d776bedd272e08fe4e961fe14ff02818100fc990a2846cf6c0f38ad798855a81f2386795425523f99a8660968be450564d97d62b58533bb9e65c36d56d28480b39bbbfaf7ddfdb8b08aa080740038b1786e659dfb342cdf197bcb8c40af1719814c734cec50b3e915cf927b6eb8e880d4073ab2d6c1e106c78e5add9042476f78edfb76d2d7ef5e1ae4c33f51c558691f5302818100b4a329f86e5c40700182427b534eb4add75c6f3f10b0ba59e191041a9ac82624c5fa88c2e2220c41169ad3025bda5d86a63c98d121f964ac2c593679c9ce8aa8d7290770babdaea348999ff6855658c5caede3e5b7723cb1e68da490f08c2bc80d8051642fd48a93bf09177413935e7aeb28f22153aa3b0720749397f7eca4e702818067661215589f11c1cd569d98245014a70b25e13f01c30d1834e4871ed3cc18733af34c10c1937c8c7589ed6f7153e9b1c72a3d8a7e90ba9b9485e07632bedae87dea44692031171268c8f9b572843b3c5b3a52c5da4f80611eba2e21bcf2f7581a3c18d2f6553b1cd7af389d18f6d58ebd4fef90fae80fa433145959aa0e260702818045ef370e79be4352cae716a92244f37f0b4a5133442b49de4a8bc5342d40a00eed284dcb5061d6dcde01baa12fde1ee965f66acabf58bd08d2f78c8f5f00a9156242ea971940611c8f9892335e48e211d2667aa0c5186af712cbab48802f2fc37488316e72d8dfd28a9e311e962fba79324e14d61a61d4afc4646da76dc650ae", "hex"); + const json = { + d: "JWmNOQGt-BJeIEJEgitF59ukch2gfTk9o3WrLG4TlkQzjjzlUI3UOSXyPMcZ8wajs-QURmpxWmoeMNA4TXChOONTbOm7Y-L48lhP5lLCs_tK7teNWcGhPWWnkuWJa-y1VJBm6lNXLSS0lfNYpdaxVKZkqcHcg3S0eywm1gJrMmWx1uREi9IlPORnrpkBfFOvH7CFzdXI3DzGaUG-qkgClekHqTZ3b0nl5hnV4uieWhvyIBIcllsItljWaUZKTQ60FO_hHI-iCYf64HWFQuxpqdM1sBp4uHcLSZJyEFYptOgfBAZWRJKPCwG_sClPvrDg5OOtYSnTVvzoINNRcRJrFw", + dp: "tKMp-G5cQHABgkJ7U060rddcbz8QsLpZ4ZEEGprIJiTF-ojC4iIMQRaa0wJb2l2GpjyY0SH5ZKwsWTZ5yc6KqNcpB3C6va6jSJmf9oVWWMXK7ePlt3I8seaNpJDwjCvIDYBRZC_UipO_CRd0E5Neeuso8iFTqjsHIHSTl_fspOc", + dq: "Z2YSFVifEcHNVp2YJFAUpwsl4T8Bww0YNOSHHtPMGHM680wQwZN8jHWJ7W9xU-mxxyo9in6QupuUheB2Mr7a6H3qRGkgMRcSaMj5tXKEOzxbOlLF2k-AYR66LiG88vdYGjwY0vZVOxzXrzidGPbVjr1P75D66A-kMxRZWaoOJgc", + e: "AQAB", + n: "-qP3bl2vXcKIpUt6mdfHqUN1gaGE2AuxqvVM3-JFso9S7bTbSIgZnnjOmTQHv9k8gQIjGxc-ygnUS7EnwVKy5_OoBoUu0dwyOhozpf7MAhfqmN3rcGjBT_u70Up5BLNlemY6t20tiLENt3vBsi6IgeWGZVCK8MMdoiXQjzsHrQW9jPTSWUO__Tu1fUJmWCJ2CJ4SbbAw2O8E4MMO62XDJVWNmL_EOysMUiEvMpTTrXqR-i7C6Diy5zpNthbsaq1Vkt_ARvfjWJdB-g9GYvz0_8p2dhFHXwUnKz3b0Jt1e1bwKTCJ054s3TVyLNaeoAsxgebnxeUx9mCNs9oxzoKvrQ", + p: "_gQtkUZDrYTY5aDQw8fcmzWsYNlu-TBedOrYQZoZN8Ok1bay1Yn4GKsM-k9u4S--uF98EXuk60ibMfDuysT4NotSszOQQ6MWD6NTXh5FY0lHtYJDgUmwYrcwKb0ieXkxVBU9oOEgxI_nHEZng-ZTfqkVfXdr7dJy4I_k6WH-FP8", + q: "_JkKKEbPbA84rXmIVagfI4Z5VCVSP5moZglovkUFZNl9YrWFM7ueZcNtVtKEgLObu_r33f24sIqggHQAOLF4bmWd-zQs3xl7y4xArxcZgUxzTOxQs-kVz5J7brjogNQHOrLWweEGx45a3ZBCR2947ft20tfvXhrkwz9RxVhpH1M", + qi: "Re83Dnm-Q1LK5xapIkTzfwtKUTNEK0neSovFNC1AoA7tKE3LUGHW3N4BuqEv3h7pZfZqyr9YvQjS94yPXwCpFWJC6pcZQGEcj5iSM15I4hHSZnqgxRhq9xLLq0iALy_DdIgxbnLY39KKnjEeli-6eTJOFNYaYdSvxGRtp23GUK4", + }; + + it("parse", () => { + const keyInfo = AsnParser.parse(bytes, core.PrivateKeyInfo); + const key = AsnParser.parse(keyInfo.privateKey, core.RsaPrivateKey); + + const jsonKey = JsonSerializer.toJSON(key); + assert.deepEqual(jsonKey, json); + }); + + it("serialize", () => { + const key = JsonParser.fromJSON(json, { targetSchema: core.RsaPrivateKey }); + + const keyInfo = new core.PrivateKeyInfo(); + keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; + keyInfo.privateKeyAlgorithm.parameters = null; + keyInfo.privateKey = AsnSerializer.serialize(key); + + const asnKeyInfo = Buffer.from(AsnSerializer.serialize(keyInfo)); + assert.equal(asnKeyInfo.equals(bytes), true); + }); + + }); + + context("PublicKey", () => { + + const bytes = Buffer.from("30820122300d06092a864886f70d01010105000382010f003082010a0282010100faa3f76e5daf5dc288a54b7a99d7c7a9437581a184d80bb1aaf54cdfe245b28f52edb4db4888199e78ce993407bfd93c8102231b173eca09d44bb127c152b2e7f3a806852ed1dc323a1a33a5fecc0217ea98ddeb7068c14ffbbbd14a7904b3657a663ab76d2d88b10db77bc1b22e8881e58665508af0c31da225d08f3b07ad05bd8cf4d25943bffd3bb57d4266582276089e126db030d8ef04e0c30eeb65c325558d98bfc43b2b0c52212f3294d3ad7a91fa2ec2e838b2e73a4db616ec6aad5592dfc046f7e3589741fa0f4662fcf4ffca767611475f05272b3ddbd09b757b56f0293089d39e2cdd35722cd69ea00b3181e6e7c5e531f6608db3da31ce82afad0203010001", "hex"); + const json = { + n: "-qP3bl2vXcKIpUt6mdfHqUN1gaGE2AuxqvVM3-JFso9S7bTbSIgZnnjOmTQHv9k8gQIjGxc-ygnUS7EnwVKy5_OoBoUu0dwyOhozpf7MAhfqmN3rcGjBT_u70Up5BLNlemY6t20tiLENt3vBsi6IgeWGZVCK8MMdoiXQjzsHrQW9jPTSWUO__Tu1fUJmWCJ2CJ4SbbAw2O8E4MMO62XDJVWNmL_EOysMUiEvMpTTrXqR-i7C6Diy5zpNthbsaq1Vkt_ARvfjWJdB-g9GYvz0_8p2dhFHXwUnKz3b0Jt1e1bwKTCJ054s3TVyLNaeoAsxgebnxeUx9mCNs9oxzoKvrQ", + e: "AQAB", + }; + + it("parse", () => { + const keyInfo = AsnParser.parse(bytes, core.PublicKeyInfo); + const key = AsnParser.parse(keyInfo.publicKey, core.RsaPublicKey); + + const jsonKey = JsonSerializer.toJSON(key); + assert.deepEqual(jsonKey, json); + }); + + it("serialize", () => { + const key = JsonParser.fromJSON(json, { targetSchema: core.RsaPublicKey }); + + const keyInfo = new core.PublicKeyInfo(); + keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; + keyInfo.publicKeyAlgorithm.parameters = null; + keyInfo.publicKey = AsnSerializer.serialize(key); + + const asnKeyInfo = Buffer.from(AsnSerializer.serialize(keyInfo)); + assert.equal(asnKeyInfo.equals(bytes), true); + }); + + }); + + }); + + context("EC", () => { + + context("PrivateKey", () => { + + const bytes = Buffer.from("308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b0201010420db0964fc2a963e9a2aef561f57db3556fa87e83ceb2e5f6dc84b00c18aa873e3a144034200043266c1386af7a0993b169393df1f7c4016e27fd48642e8d512c775b31c8f06722baef1310974a6c63aff2ef8832fba27f021f5ae2f2c6c2d56fde5be5ade78f5", "hex"); + const json = { + d: "2wlk_CqWPpoq71YfV9s1VvqH6DzrLl9tyEsAwYqoc-M", + x: "MmbBOGr3oJk7FpOT3x98QBbif9SGQujVEsd1sxyPBnI", + y: "K67xMQl0psY6_y74gy-6J_Ah9a4vLGwtVv3lvlreePU", + }; + + it("parse", () => { + const keyInfo = AsnParser.parse(bytes, core.PrivateKeyInfo); + const key = AsnParser.parse(keyInfo.privateKey, core.EcPrivateKey); + + const jsonKey = JsonSerializer.toJSON(key); + assert.deepEqual(jsonKey, json); + }); + + it("serialize", () => { + const keyInfo = new core.PrivateKeyInfo(); + keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; + keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize( + new core.ObjectIdentifier("1.2.840.10045.3.1.7"), + ); + const key = JsonParser.fromJSON(json, { targetSchema: core.EcPrivateKey }); + keyInfo.privateKey = AsnSerializer.serialize(key); + + const asnKeyInfo = Buffer.from(AsnSerializer.serialize(keyInfo)); + assert.equal(asnKeyInfo.equals(bytes), true); + }); + + }); + + }); + +}); diff --git a/packages/core/test/schema/ec_signature.spec.ts b/packages/core/test/schema/ec_signature.spec.ts new file mode 100644 index 0000000..73752d9 --- /dev/null +++ b/packages/core/test/schema/ec_signature.spec.ts @@ -0,0 +1,71 @@ +import * as assert from "assert"; +import { Convert } from "pvtsutils"; +import { AsnSerializer, AsnParser } from "@peculiar/asn1-schema"; +import { EcDsaSignature } from "@peculiar/webcrypto-core"; + +interface IEcSignatureTestVector { + name: string; + asn1: string; + webCrypto: string; +} + +context("ASN1", () => { + + context("ECDSA Signature Value", () => { + + const vectors: IEcSignatureTestVector[] = [ + { + name: "P-256 #1", + asn1: "3045022100d50b6b8b2f84ec9e8704fd7651eed26d1c9e60a773666ec122e135669eb435fe02206e08432c943aec0b3f223014731475277ff7a3840ac9dbd065aab04a540c9a28", + webCrypto: "d50b6b8b2f84ec9e8704fd7651eed26d1c9e60a773666ec122e135669eb435fe6e08432c943aec0b3f223014731475277ff7a3840ac9dbd065aab04a540c9a28", + }, + { + name: "P-256 #2", + asn1: "304402205cce26e35066669ee84acad747d39abe8b882a569004a6d4c1992d66b3b26caf0220791e998153331d52a3b972b77fb1b6e2caf3cb7b8cdc60fd486443819ff08208", + webCrypto: "5cce26e35066669ee84acad747d39abe8b882a569004a6d4c1992d66b3b26caf791e998153331d52a3b972b77fb1b6e2caf3cb7b8cdc60fd486443819ff08208", + }, + { + name: "P-384 #1", + asn1: "3066023100f56792d36a7bd7836e94947343c308f528b5eb9327c468d6cab1b40498824f6f165d5335eabfcc553403b00579a5b68c023100a9daad0d1fbf5903eb1b42cca280f1a39baa33a2b32c19523c3967f7c9a3d23a9fdaab39b6bfedd82ba12abbedda24b1", + webCrypto: "f56792d36a7bd7836e94947343c308f528b5eb9327c468d6cab1b40498824f6f165d5335eabfcc553403b00579a5b68ca9daad0d1fbf5903eb1b42cca280f1a39baa33a2b32c19523c3967f7c9a3d23a9fdaab39b6bfedd82ba12abbedda24b1", + }, + { + name: "P-384 #2", + asn1: "3064023020f5cacedfe6d32ef782027f3cd58dddc6d27ab92cef562eca2d9e7089b450673246141a41c3d0d14f61ffa012a2a100023034cdcb83981758c58bcd92666393a85799b4f5a073347833f22d301aae0bb415cfaf2c6eade9fde00d79365ab6ca93da", + webCrypto: "20f5cacedfe6d32ef782027f3cd58dddc6d27ab92cef562eca2d9e7089b450673246141a41c3d0d14f61ffa012a2a10034cdcb83981758c58bcd92666393a85799b4f5a073347833f22d301aae0bb415cfaf2c6eade9fde00d79365ab6ca93da", + }, + { + name: "P-521 #1", + asn1: "30818702417767d9adbc3994e25c9c0328ab591f0ca6d9b24152c5f692ae4c62efa0b9317a0a26fcaf83ce87d337e8c3945fe8281e738f25ead6999c9521a2c2724f06bdc0e8024201a0aa892238ee98902b4a25c5efb940677cfd11a43df382f633f32d1c6b751ccd00fedfa106c298f652292b16dc1964521a04e42e0c8eaeb368222c6e94b42f325d", + webCrypto: "007767d9adbc3994e25c9c0328ab591f0ca6d9b24152c5f692ae4c62efa0b9317a0a26fcaf83ce87d337e8c3945fe8281e738f25ead6999c9521a2c2724f06bdc0e801a0aa892238ee98902b4a25c5efb940677cfd11a43df382f633f32d1c6b751ccd00fedfa106c298f652292b16dc1964521a04e42e0c8eaeb368222c6e94b42f325d", + }, + { + name: "P-521 #2", + asn1: "3081880242011e0ff3c825b1133ef2779bbffd05374b17eeeff37444108a4c480b881ba3f3f426c3344fb1173dcec305f3e49408965092f946e609dfb845efaaaa25a43c679b0c024201a1366cd7b11efe7a41418cf83156bfdac56bb6253fd018a23974fc182948f3a84d5241922f09b8a60c4366f58b2b86461886515bd79872bb55e9840c412db766da", + webCrypto: "011e0ff3c825b1133ef2779bbffd05374b17eeeff37444108a4c480b881ba3f3f426c3344fb1173dcec305f3e49408965092f946e609dfb845efaaaa25a43c679b0c01a1366cd7b11efe7a41418cf83156bfdac56bb6253fd018a23974fc182948f3a84d5241922f09b8a60c4366f58b2b86461886515bd79872bb55e9840c412db766da", + }, + ]; + + context("From WebCrypto to DER", () => { + vectors.forEach((vector) => { + it(vector.name, () => { + const value = EcDsaSignature.fromWebCryptoSignature(Convert.FromHex(vector.webCrypto)); + const der = AsnSerializer.serialize(value); + assert.strictEqual(Convert.ToHex(der), vector.asn1); + }); + }); + }); + + context("From DER to WebCrypto", () => { + vectors.forEach((vector) => { + it(vector.name, () => { + const value = AsnParser.parse(Convert.FromHex(vector.asn1), EcDsaSignature); + const signature = value.toWebCryptoSignature(); + assert.strictEqual(Convert.ToHex(signature), vector.webCrypto); + }); + }); + }); + + }); + +}); diff --git a/packages/core/test/schema/ed_keys.spec.ts b/packages/core/test/schema/ed_keys.spec.ts new file mode 100644 index 0000000..600660a --- /dev/null +++ b/packages/core/test/schema/ed_keys.spec.ts @@ -0,0 +1,30 @@ +import * as assert from "assert"; +import { AsnConvert } from "@peculiar/asn1-schema"; +import { JsonSerializer } from "@peculiar/json-schema"; +import { CurvePrivateKey, idX25519, idX448, PrivateKeyInfo, PublicKeyInfo } from "@peculiar/webcrypto-core"; +import { Convert } from "pvtsutils"; + +context("EdDSA and ECDH-ES keys", () => { + + it("Private key", () => { + const b64 = "MEYCAQAwBQYDK2VvBDoEOPhm20uZC//c0wk1EEapNDcIIlgSGVxnWhwRJvT5K3+iwjtcyV2inuEihA5Soa5BO2OHh5leznW+"; + const raw = Buffer.from(b64, "base64"); + + const pki = AsnConvert.parse(raw, PrivateKeyInfo); + assert.strictEqual(pki.privateKeyAlgorithm.algorithm, idX448); + const privateKey = AsnConvert.parse(pki.privateKey, CurvePrivateKey); + + assert.deepStrictEqual(JsonSerializer.toJSON(privateKey), { d: "-GbbS5kL_9zTCTUQRqk0NwgiWBIZXGdaHBEm9Pkrf6LCO1zJXaKe4SKEDlKhrkE7Y4eHmV7Odb4" }); + }); + + it("Public key", () => { + const b64 = "MCowBQYDK2VuAyEAR-a_Z6rz2HuBXn7m7v_pjef6nHfCWSIObVWCTr5nxjg"; + const raw = Convert.FromBase64Url(b64); + + const spki = AsnConvert.parse(raw, PublicKeyInfo); + assert.strictEqual(spki.publicKeyAlgorithm.algorithm, idX25519); + + assert.strictEqual(Convert.ToBase64Url(spki.publicKey), "R-a_Z6rz2HuBXn7m7v_pjef6nHfCWSIObVWCTr5nxjg"); + }); + +}); \ No newline at end of file diff --git a/packages/core/test/shake.spec.ts b/packages/core/test/shake.spec.ts new file mode 100644 index 0000000..35314c8 --- /dev/null +++ b/packages/core/test/shake.spec.ts @@ -0,0 +1,56 @@ +import * as assert from "assert"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; + +class TestShake128Provider extends core.Shake128Provider { + public async onDigest(algorithm: Required, data: ArrayBuffer): Promise { + return new ArrayBuffer(algorithm.length); + } +} + +// tslint:disable-next-line: max-classes-per-file +class TestShake256Provider extends core.Shake256Provider { + public async onDigest(algorithm: Required, data: ArrayBuffer): Promise { + return new ArrayBuffer(algorithm.length); + } +} + +context("SHAKE", () => { + + const data = new Uint8Array(); + const shake128 = new TestShake128Provider(); + const shake256 = new TestShake256Provider(); + + context("check parameters", () => { + + context("algorithm.length", () => { + it("negative value", async () => { + assert.rejects(shake128.digest({ name: "Shake128", length: -1 } as types.Algorithm, data), TypeError); + }); + + it("wrong type", async () => { + assert.rejects(shake128.digest({ name: "Shake128", length: "wrong" } as types.Algorithm, data), TypeError); + }); + }); + + }); + + context("shake128", () => { + + it("default length", async () => { + const digest = await shake128.digest({ name: "shake128" }, data); + assert.strictEqual(digest.byteLength, 16); + }); + + }); + + context("shake256", () => { + + it("default length", async () => { + const digest = await shake256.digest({ name: "Shake256" }, data); + assert.strictEqual(digest.byteLength, 32); + }); + + }); + +}); diff --git a/packages/core/test/storage.spec.ts b/packages/core/test/storage.spec.ts new file mode 100644 index 0000000..a1f9868 --- /dev/null +++ b/packages/core/test/storage.spec.ts @@ -0,0 +1,100 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; + +// tslint:disable:max-classes-per-file + +class RsaSsaProvider extends core.RsaSsaProvider { + public onSign(algorithm: core.RsaSsaParams, key: core.BaseCryptoKey, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } + public onVerify(algorithm: core.RsaSsaParams, key: core.BaseCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } + public onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + public onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey): Promise { + throw new Error("Method not implemented."); + } + public onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } +} + +class RsaOaepProvider extends core.RsaOaepProvider { + public onEncrypt(algorithm: types.RsaOaepParams, key: core.BaseCryptoKey, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } + public onDecrypt(algorithm: types.RsaOaepParams, key: core.BaseCryptoKey, data: ArrayBuffer): Promise { + throw new Error("Method not implemented."); + } + public onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } + public onExportKey(format: types.KeyFormat, key: core.BaseCryptoKey): Promise { + throw new Error("Method not implemented."); + } + public onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + throw new Error("Method not implemented."); + } +} + +context("ProviderStorage", () => { + + it("set", () => { + const storage = new core.ProviderStorage(); + + assert.equal(storage.length, 0); + + storage.set(new RsaSsaProvider()); + storage.set(new RsaOaepProvider()); + storage.set(new RsaOaepProvider()); + + assert.equal(storage.length, 2); + }); + + it("get", () => { + const storage = new core.ProviderStorage(); + + storage.set(new RsaSsaProvider()); + storage.set(new RsaOaepProvider()); + + const provider = storage.get("rsa-oaep"); + assert.equal(provider!.name, "RSA-OAEP"); + }); + + it("has", () => { + const storage = new core.ProviderStorage(); + + storage.set(new RsaSsaProvider()); + storage.set(new RsaOaepProvider()); + + const ok = storage.has("rsa-oaep"); + assert.equal(ok, true); + }); + + it("algorithms", () => { + const storage = new core.ProviderStorage(); + + storage.set(new RsaSsaProvider()); + storage.set(new RsaOaepProvider()); + + assert.deepEqual(storage.algorithms, ["RSA-OAEP", "RSASSA-PKCS1-v1_5"]); + }); + + it("removeAt", () => { + const storage = new core.ProviderStorage(); + + storage.set(new RsaSsaProvider()); + storage.set(new RsaOaepProvider()); + + storage.removeAt("rsa-wrong"); + assert.deepEqual(storage.length, 2); + + const removedProvider = storage.removeAt("rsa-oaep"); + assert.deepEqual(removedProvider!.name, "RSA-OAEP"); + assert.deepEqual(storage.length, 1); + }); + +}); diff --git a/packages/core/test/subtle.spec.ts b/packages/core/test/subtle.spec.ts new file mode 100644 index 0000000..381cb2a --- /dev/null +++ b/packages/core/test/subtle.spec.ts @@ -0,0 +1,220 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; + +context("SubtleCrypto", () => { + + class TestProvider extends core.ProviderCrypto { + public name = "TEST"; + public usages: types.KeyUsage[] = ["sign", "verify", "deriveKey", "deriveBits", "encrypt", "decrypt", "wrapKey", "unwrapKey"]; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return new ArrayBuffer(0); + } + + public override async onGenerateKey(algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + return key; + } + + public override async onSign(algorithm: types.Algorithm, sKey: core.BaseCryptoKey, data: ArrayBuffer): Promise { + return new ArrayBuffer(0); + } + + public override async onVerify(algorithm: types.Algorithm, sKey: core.BaseCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + return true; + } + + public override async onEncrypt(algorithm: types.Algorithm, sKey: core.BaseCryptoKey, data: ArrayBuffer): Promise { + return new ArrayBuffer(0); + } + + public override async onDecrypt(algorithm: types.Algorithm, sKey: core.BaseCryptoKey, data: ArrayBuffer): Promise { + return new ArrayBuffer(0); + } + + public override async onDeriveBits(algorithm: types.Algorithm, sKey: core.BaseCryptoKey, length: number): Promise { + return new ArrayBuffer(0); + } + + public override async onExportKey(format: types.KeyFormat, sKey: core.BaseCryptoKey): Promise { + return new ArrayBuffer(0); + } + + public override async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + return key; + } + + } + + // tslint:disable-next-line:max-classes-per-file + class TestSubtleCrypto extends core.SubtleCrypto { + constructor() { + super(); + + this.providers.set(new TestProvider()); + } + } + + const subtle = new TestSubtleCrypto(); + const key = new core.BaseCryptoKey(); + key.algorithm = { name: "TEST" }; + key.type = "secret", + key.usages = ["sign", "verify", "deriveKey", "deriveBits", "encrypt", "decrypt", "wrapKey", "unwrapKey"]; + key.extractable = true; + + context("generateKey", () => { + + it("correct values", async () => { + const res = await subtle.generateKey("test", false, ["sign"]); + assert.equal(!!res, true); + }); + + }); + + context("digest", () => { + + it("correct values", async () => { + const res = await subtle.digest("test", new Uint8Array(0)); + assert.equal(!!res, true); + }); + + }); + + context("sign", () => { + + it("correct values", async () => { + const res = await subtle.sign({ name: "test", hash: "SHA-1" } as any, key, new Uint8Array(0)); + assert.equal(!!res, true); + }); + + }); + + context("verify", () => { + + it("correct values", async () => { + const res = await subtle.verify({ name: "test", hash: { name: "SHA-1" } } as any, key, new ArrayBuffer(0), new Uint8Array(0)); + assert.equal(!!res, true); + }); + + }); + + context("encrypt", () => { + + it("correct values", async () => { + const res = await subtle.encrypt("test", key, new Uint8Array(0)); + assert.equal(!!res, true); + }); + + }); + + context("decrypt", () => { + + it("correct values", async () => { + const res = await subtle.decrypt("test", key, new Uint8Array(0)); + assert.equal(!!res, true); + }); + + }); + + context("deriveBits", () => { + + it("correct values", async () => { + const res = await subtle.deriveBits("test", key, 128); + assert.equal(!!res, true); + }); + + }); + + context("deriveKey", () => { + + it("correct values", async () => { + const res = await subtle.deriveKey("test", key, { name: "test", length: 128 } as any, false, ["verify"]); + assert.equal(!!res, true); + }); + + }); + + context("exportKey", () => { + + it("correct values", async () => { + const res = await subtle.exportKey("raw", key); + assert.equal(!!res, true); + }); + + }); + + context("importKey", () => { + + it("correct values", async () => { + const res = await subtle.importKey("raw", new ArrayBuffer(0), "test", false, ["sign"]); + assert.equal(!!res, true); + }); + + it("json", async () => { + const res = await subtle.importKey("jwk", { kty: "RSA" }, "test", false, ["sign"]); + assert.equal(!!res, true); + }); + + it("Uint8Array", async () => { + const res = await subtle.importKey("raw", new Uint8Array(10), "test", false, ["sign"]); + assert.equal(!!res, true); + }); + + it("Buffer", async () => { + const res = await subtle.importKey("raw", Buffer.alloc(10), "test", false, ["sign"]); + assert.equal(!!res, true); + }); + + it("ArrayBuffer", async () => { + const res = await subtle.importKey("raw", new ArrayBuffer(10), "test", false, ["sign"]); + assert.equal(!!res, true); + }); + + }); + + context("wrapKey", () => { + + it("correct values", async () => { + const res = await subtle.wrapKey("raw", key, key, "test"); + assert.equal(!!res, true); + }); + + }); + + context("unwrapKey", () => { + + it("correct values", async () => { + const res = await subtle.unwrapKey("raw", new ArrayBuffer(0), key, "test", "test", false, ["deriveKey"]); + assert.equal(!!res, true); + }); + + }); + + context("checkRequiredArguments", () => { + + it("error if less than required", async () => { + await assert.rejects(subtle.digest.apply(subtle, ["test"] as unknown as any)); + }); + + it("no error if greater than required", async () => { + await assert.doesNotReject(subtle.digest.apply(subtle, ["test", new Uint8Array(0), 1, 2, 3])); + }); + + }); + + context("getProvider", () => { + it("error if there is not provider with given name", async () => { + await assert.rejects(subtle.digest("wrong", new Uint8Array(0))); + }); + }); + + context("prepareData", () => { + it("error if wrong data", async () => { + await assert.rejects(subtle.digest("test", [1, 2, 3, 4] as any)); + }); + it("from Buffer", async () => { + await subtle.digest("test", Buffer.from([1, 2, 3, 4])); + }); + }); + +}); diff --git a/packages/node/package.json b/packages/node/package.json new file mode 100644 index 0000000..6e9fb68 --- /dev/null +++ b/packages/node/package.json @@ -0,0 +1,60 @@ +{ + "name": "@peculiar/webcrypto", + "version": "3.0.0", + "description": "A WebCrypto Polyfill for NodeJS", + "author": "PeculiarVentures", + "contributors": [ + "Miroshin Stepan" + ], + "homepage": "https://github.com/PeculiarVentures/webcrypto/tree/master/packages/node#readme", + "license": "MIT", + "main": "build/index.js", + "module": "build/index.es.js", + "types": "build/index.d.ts", + "files": [ + "build", + "README.md", + "LICENSE.md" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "https://github.com/PeculiarVentures/webcrypto.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/PeculiarVentures/webcrypto/issues" + }, + "keywords": [ + "webcrypto", + "crypto", + "sha", + "rsa", + "ec", + "aes", + "des", + "hmac", + "pbkdf2", + "eddsa", + "x25519", + "ed25519", + "x448", + "ed448", + "shake128", + "shake256" + ], + "dependencies": { + "@peculiar/asn1-schema": "^2.1.7", + "@peculiar/json-schema": "^1.1.12", + "@peculiar/webcrypto-core": "^3.0.0", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=10.12.0" + } +} \ No newline at end of file diff --git a/src/converters/base64_url.ts b/packages/node/src/converters/base64_url.ts similarity index 100% rename from src/converters/base64_url.ts rename to packages/node/src/converters/base64_url.ts diff --git a/src/converters/index.ts b/packages/node/src/converters/index.ts similarity index 100% rename from src/converters/index.ts rename to packages/node/src/converters/index.ts diff --git a/src/crypto.ts b/packages/node/src/crypto.ts similarity index 85% rename from src/crypto.ts rename to packages/node/src/crypto.ts index 513d9a3..a9c984a 100644 --- a/src/crypto.ts +++ b/packages/node/src/crypto.ts @@ -1,5 +1,5 @@ -import crypto from "crypto"; -import * as core from "webcrypto-core"; +import * as crypto from "crypto"; +import * as core from "@peculiar/webcrypto-core"; import { SubtleCrypto } from "./subtle"; export class Crypto extends core.Crypto { diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts new file mode 100644 index 0000000..753d930 --- /dev/null +++ b/packages/node/src/index.ts @@ -0,0 +1,2 @@ +export { BaseCryptoKey as CryptoKey } from "@peculiar/webcrypto-core"; +export { Crypto } from "./crypto"; diff --git a/src/keys/asymmetric.ts b/packages/node/src/keys/asymmetric.ts similarity index 100% rename from src/keys/asymmetric.ts rename to packages/node/src/keys/asymmetric.ts diff --git a/src/keys/index.ts b/packages/node/src/keys/index.ts similarity index 100% rename from src/keys/index.ts rename to packages/node/src/keys/index.ts diff --git a/src/keys/key.ts b/packages/node/src/keys/key.ts similarity index 59% rename from src/keys/key.ts rename to packages/node/src/keys/key.ts index a00c344..318e4d0 100644 --- a/src/keys/key.ts +++ b/packages/node/src/keys/key.ts @@ -1,18 +1,19 @@ import { JsonProp, JsonPropTypes } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; -export class CryptoKey extends core.CryptoKey { +export class CryptoKey extends core.BaseCryptoKey { public data: Buffer = Buffer.alloc(0); - public override algorithm: KeyAlgorithm = { name: "" }; + public override algorithm: types.KeyAlgorithm = { name: "" }; @JsonProp({ name: "ext", type: JsonPropTypes.Boolean, optional: true }) public override extractable = false; - public override type: KeyType = "secret"; + public override type: types.KeyType = "secret"; @JsonProp({ name: "key_ops", type: JsonPropTypes.String, repeated: true, optional: true }) - public override usages: KeyUsage[] = []; + public override usages: types.KeyUsage[] = []; @JsonProp({ type: JsonPropTypes.String }) protected kty = "oct"; diff --git a/src/keys/symmetric.ts b/packages/node/src/keys/symmetric.ts similarity index 100% rename from src/keys/symmetric.ts rename to packages/node/src/keys/symmetric.ts diff --git a/src/mechs/aes/aes_cbc.ts b/packages/node/src/mechs/aes/aes_cbc.ts similarity index 52% rename from src/mechs/aes/aes_cbc.ts rename to packages/node/src/mechs/aes/aes_cbc.ts index 527a4a5..47c94c8 100644 --- a/src/mechs/aes/aes_cbc.ts +++ b/packages/node/src/mechs/aes/aes_cbc.ts @@ -1,11 +1,12 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { getCryptoKey, setCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; export class AesCbcProvider extends core.AesCbcProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.generateKey( { name: this.name, @@ -17,24 +18,24 @@ export class AesCbcProvider extends core.AesCbcProvider { return setCryptoKey(key); } - public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onEncrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onDecrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/aes_cmac.ts b/packages/node/src/mechs/aes/aes_cmac.ts similarity index 80% rename from src/mechs/aes/aes_cmac.ts rename to packages/node/src/mechs/aes/aes_cmac.ts index 78d6448..48beb3d 100644 --- a/src/mechs/aes/aes_cmac.ts +++ b/packages/node/src/mechs/aes/aes_cmac.ts @@ -1,5 +1,6 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import * as crypto from "crypto"; -import * as core from "webcrypto-core"; import { setCryptoKey, getCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; @@ -113,7 +114,7 @@ function aesCmac(key: Buffer, message: Buffer) { export class AesCmacProvider extends core.AesCmacProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.generateKey( { name: this.name, @@ -125,26 +126,27 @@ export class AesCmacProvider extends core.AesCmacProvider { return setCryptoKey(key); } - public async onSign(algorithm: core.AesCmacParams, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onSign(algorithm: types.AesCmacParams, key: AesCryptoKey, data: ArrayBuffer): Promise { const result = aesCmac(getCryptoKey(key).data, Buffer.from(data)); return new Uint8Array(result).buffer; } - public async onVerify(algorithm: core.AesCmacParams, key: AesCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + public async onVerify(algorithm: types.AesCmacParams, key: AesCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { const signature2 = await this.sign(algorithm, key, data); return Buffer.from(signature).compare(Buffer.from(signature2)) === 0; } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); + } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/aes_ctr.ts b/packages/node/src/mechs/aes/aes_ctr.ts similarity index 52% rename from src/mechs/aes/aes_ctr.ts rename to packages/node/src/mechs/aes/aes_ctr.ts index 95bae84..5acf9b3 100644 --- a/src/mechs/aes/aes_ctr.ts +++ b/packages/node/src/mechs/aes/aes_ctr.ts @@ -1,11 +1,12 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { setCryptoKey, getCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; export class AesCtrProvider extends core.AesCtrProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.generateKey( { name: this.name, @@ -17,24 +18,24 @@ export class AesCtrProvider extends core.AesCtrProvider { return setCryptoKey(key); } - public async onEncrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onEncrypt(algorithm: types.AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onDecrypt(algorithm: AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onDecrypt(algorithm: types.AesCtrParams, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[], ...args: any[]): Promise { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/aes_ecb.ts b/packages/node/src/mechs/aes/aes_ecb.ts similarity index 52% rename from src/mechs/aes/aes_ecb.ts rename to packages/node/src/mechs/aes/aes_ecb.ts index 05f5ffe..0f3c01d 100644 --- a/src/mechs/aes/aes_ecb.ts +++ b/packages/node/src/mechs/aes/aes_ecb.ts @@ -1,11 +1,12 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { setCryptoKey, getCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; export class AesEcbProvider extends core.AesEcbProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.generateKey( { name: this.name, @@ -17,24 +18,24 @@ export class AesEcbProvider extends core.AesEcbProvider { return setCryptoKey(key); } - public async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onEncrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onDecrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/aes_gcm.ts b/packages/node/src/mechs/aes/aes_gcm.ts similarity index 52% rename from src/mechs/aes/aes_gcm.ts rename to packages/node/src/mechs/aes/aes_gcm.ts index 0d4e197..ca61d69 100644 --- a/src/mechs/aes/aes_gcm.ts +++ b/packages/node/src/mechs/aes/aes_gcm.ts @@ -1,11 +1,12 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { setCryptoKey, getCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; export class AesGcmProvider extends core.AesGcmProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await AesCrypto.generateKey( { name: this.name, @@ -17,24 +18,24 @@ export class AesGcmProvider extends core.AesGcmProvider { return setCryptoKey(key); } - public async onEncrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onEncrypt(algorithm: types.AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onDecrypt(algorithm: AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise { + public async onDecrypt(algorithm: types.AesGcmParams, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/aes_kw.ts b/packages/node/src/mechs/aes/aes_kw.ts similarity index 52% rename from src/mechs/aes/aes_kw.ts rename to packages/node/src/mechs/aes/aes_kw.ts index 2e3e1b3..9bd1c21 100644 --- a/src/mechs/aes/aes_kw.ts +++ b/packages/node/src/mechs/aes/aes_kw.ts @@ -1,11 +1,12 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { setCryptoKey, getCryptoKey } from "../storage"; import { AesCrypto } from "./crypto"; import { AesCryptoKey } from "./key"; export class AesKwProvider extends core.AesKwProvider { - public async onGenerateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const res = await AesCrypto.generateKey( { name: this.name, @@ -17,24 +18,24 @@ export class AesKwProvider extends core.AesKwProvider { return setCryptoKey(res); } - public async onExportKey(format: KeyFormat, key: AesCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: AesCryptoKey): Promise { return AesCrypto.exportKey(format, getCryptoKey(key) as AesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } - public override async onEncrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public override async onEncrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.encrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public override async onDecrypt(algorithm: Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { + public override async onDecrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: ArrayBuffer): Promise { return AesCrypto.decrypt(algorithm, getCryptoKey(key) as AesCryptoKey, new Uint8Array(data)); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); diff --git a/src/mechs/aes/crypto.ts b/packages/node/src/mechs/aes/crypto.ts similarity index 65% rename from src/mechs/aes/crypto.ts rename to packages/node/src/mechs/aes/crypto.ts index 090ef37..918e8e7 100644 --- a/src/mechs/aes/crypto.ts +++ b/packages/node/src/mechs/aes/crypto.ts @@ -1,6 +1,7 @@ -import crypto, { CipherGCM, DecipherGCM } from "crypto"; import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; import { CryptoKey } from "../../keys"; import { AesCryptoKey } from "./key"; @@ -8,7 +9,7 @@ export class AesCrypto { public static AES_KW_IV = Buffer.from("A6A6A6A6A6A6A6A6", "hex"); - public static async generateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async generateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = new AesCryptoKey(); key.algorithm = algorithm; key.extractable = extractable; @@ -18,7 +19,7 @@ export class AesCrypto { return key; } - public static async exportKey(format: string, key: AesCryptoKey): Promise { + public static async exportKey(format: string, key: AesCryptoKey): Promise { if (!(key instanceof AesCryptoKey)) { throw new Error("key: Is not AesCryptoKey"); } @@ -33,7 +34,7 @@ export class AesCrypto { } } - public static async importKey(format: string, keyData: JsonWebKey | ArrayBuffer, algorithm: any, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async importKey(format: string, keyData: types.JsonWebKey | ArrayBuffer, algorithm: any, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { let key: AesCryptoKey; switch (format.toLowerCase()) { @@ -66,45 +67,45 @@ export class AesCrypto { return key; } - public static async encrypt(algorithm: Algorithm, key: AesCryptoKey, data: Uint8Array): Promise { + public static async encrypt(algorithm: types.Algorithm, key: AesCryptoKey, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "AES-CBC": - return this.encryptAesCBC(algorithm as AesCbcParams, key, Buffer.from(data)); + return this.encryptAesCBC(algorithm as types.AesCbcParams, key, Buffer.from(data)); case "AES-CTR": - return this.encryptAesCTR(algorithm as AesCtrParams, key, Buffer.from(data)); + return this.encryptAesCTR(algorithm as types.AesCtrParams, key, Buffer.from(data)); case "AES-GCM": - return this.encryptAesGCM(algorithm as AesGcmParams, key, Buffer.from(data)); + return this.encryptAesGCM(algorithm as types.AesGcmParams, key, Buffer.from(data)); case "AES-KW": - return this.encryptAesKW(algorithm as AesKeyAlgorithm, key, Buffer.from(data)); + return this.encryptAesKW(algorithm as types.AesKeyAlgorithm, key, Buffer.from(data)); case "AES-ECB": - return this.encryptAesECB(algorithm as AesKeyAlgorithm, key, Buffer.from(data)); + return this.encryptAesECB(algorithm as types.AesKeyAlgorithm, key, Buffer.from(data)); default: throw new core.OperationError("algorithm: Is not recognized"); } } - public static async decrypt(algorithm: Algorithm, key: CryptoKey, data: Uint8Array): Promise { + public static async decrypt(algorithm: types.Algorithm, key: CryptoKey, data: Uint8Array): Promise { if (!(key instanceof AesCryptoKey)) { throw new Error("key: Is not AesCryptoKey"); } switch (algorithm.name.toUpperCase()) { case "AES-CBC": - return this.decryptAesCBC(algorithm as AesCbcParams, key, Buffer.from(data)); + return this.decryptAesCBC(algorithm as types.AesCbcParams, key, Buffer.from(data)); case "AES-CTR": - return this.decryptAesCTR(algorithm as AesCtrParams, key, Buffer.from(data)); + return this.decryptAesCTR(algorithm as types.AesCtrParams, key, Buffer.from(data)); case "AES-GCM": - return this.decryptAesGCM(algorithm as AesGcmParams, key, Buffer.from(data)); + return this.decryptAesGCM(algorithm as types.AesGcmParams, key, Buffer.from(data)); case "AES-KW": - return this.decryptAesKW(algorithm as AesKeyAlgorithm, key, Buffer.from(data)); + return this.decryptAesKW(algorithm as types.AesKeyAlgorithm, key, Buffer.from(data)); case "AES-ECB": - return this.decryptAesECB(algorithm as AesKeyAlgorithm, key, Buffer.from(data)); + return this.decryptAesECB(algorithm as types.AesKeyAlgorithm, key, Buffer.from(data)); default: throw new core.OperationError("algorithm: Is not recognized"); } } - public static async encryptAesCBC(algorithm: AesCbcParams, key: AesCryptoKey, data: Buffer) { + public static async encryptAesCBC(algorithm: types.AesCbcParams, key: AesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); @@ -112,14 +113,14 @@ export class AesCrypto { return res; } - public static async decryptAesCBC(algorithm: AesCbcParams, key: AesCryptoKey, data: Buffer) { + public static async decryptAesCBC(algorithm: types.AesCbcParams, key: AesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } - public static async encryptAesCTR(algorithm: AesCtrParams, key: AesCryptoKey, data: Buffer) { + public static async encryptAesCTR(algorithm: types.AesCtrParams, key: AesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-ctr`, key.data, Buffer.from(algorithm.counter as ArrayBuffer)); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); @@ -127,17 +128,17 @@ export class AesCrypto { return res; } - public static async decryptAesCTR(algorithm: AesCtrParams, key: AesCryptoKey, data: Buffer) { + public static async decryptAesCTR(algorithm: types.AesCtrParams, key: AesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-ctr`, key.data, new Uint8Array(algorithm.counter as ArrayBuffer)); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } - public static async encryptAesGCM(algorithm: AesGcmParams, key: AesCryptoKey, data: Buffer) { + public static async encryptAesGCM(algorithm: types.AesGcmParams, key: AesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-gcm`, key.data, Buffer.from(algorithm.iv as ArrayBuffer), { authTagLength: (algorithm.tagLength || 128) >> 3, - } as any) as CipherGCM; // NodeJs d.ts doesn't support CipherGCMOptions for createCipheriv + } as any) as crypto.CipherGCM; // NodeJs d.ts doesn't support CipherGCMOptions for createCipheriv if (algorithm.additionalData) { cipher.setAAD(Buffer.from(algorithm.additionalData as ArrayBuffer)); } @@ -147,8 +148,8 @@ export class AesCrypto { return res; } - public static async decryptAesGCM(algorithm: AesGcmParams, key: AesCryptoKey, data: Buffer) { - const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-gcm`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)) as DecipherGCM; + public static async decryptAesGCM(algorithm: types.AesGcmParams, key: AesCryptoKey, data: Buffer) { + const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-gcm`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)) as crypto.DecipherGCM; const tagLength = (algorithm.tagLength || 128) >> 3; const enc = data.slice(0, data.length - tagLength); const tag = data.slice(data.length - tagLength); @@ -161,21 +162,21 @@ export class AesCrypto { return new Uint8Array(dec).buffer; } - public static async encryptAesKW(algorithm: Algorithm, key: AesCryptoKey, data: Buffer) { + public static async encryptAesKW(algorithm: types.Algorithm, key: AesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); return new Uint8Array(enc).buffer; } - public static async decryptAesKW(algorithm: Algorithm, key: AesCryptoKey, data: Buffer) { + public static async decryptAesKW(algorithm: types.Algorithm, key: AesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } - public static async encryptAesECB(algorithm: Algorithm, key: AesCryptoKey, data: Buffer) { + public static async encryptAesECB(algorithm: types.Algorithm, key: AesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0)); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); @@ -183,7 +184,7 @@ export class AesCrypto { return res; } - public static async decryptAesECB(algorithm: Algorithm, key: AesCryptoKey, data: Buffer) { + public static async decryptAesECB(algorithm: types.Algorithm, key: AesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0)); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); diff --git a/src/mechs/aes/index.ts b/packages/node/src/mechs/aes/index.ts similarity index 100% rename from src/mechs/aes/index.ts rename to packages/node/src/mechs/aes/index.ts diff --git a/src/mechs/aes/key.ts b/packages/node/src/mechs/aes/key.ts similarity index 80% rename from src/mechs/aes/key.ts rename to packages/node/src/mechs/aes/key.ts index d652a29..85c503d 100644 --- a/src/mechs/aes/key.ts +++ b/packages/node/src/mechs/aes/key.ts @@ -1,18 +1,19 @@ import { JsonProp } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { JsonBase64UrlConverter } from "../../converters"; import { SymmetricKey } from "../../keys"; export class AesCryptoKey extends SymmetricKey { - public override algorithm!: AesKeyAlgorithm; + public override algorithm!: types.AesKeyAlgorithm; - @JsonProp({name: "k", converter: JsonBase64UrlConverter}) + @JsonProp({ name: "k", converter: JsonBase64UrlConverter }) public override data!: Buffer; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore - public get alg() { + public override get alg() { switch (this.algorithm.name.toUpperCase()) { case "AES-CBC": return `A${this.algorithm.length}CBC`; diff --git a/src/mechs/des/crypto.ts b/packages/node/src/mechs/des/crypto.ts similarity index 67% rename from src/mechs/des/crypto.ts rename to packages/node/src/mechs/des/crypto.ts index 5b0fc90..22a71b9 100644 --- a/src/mechs/des/crypto.ts +++ b/packages/node/src/mechs/des/crypto.ts @@ -1,13 +1,13 @@ -import crypto from "crypto"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { DesParams } from "webcrypto-core"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; import { CryptoKey } from "../../keys"; import { DesCryptoKey } from "./key"; export class DesCrypto { - public static async generateKey(algorithm: AesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async generateKey(algorithm: types.AesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = new DesCryptoKey(); key.algorithm = algorithm; key.extractable = extractable; @@ -17,10 +17,10 @@ export class DesCrypto { return key; } - public static async exportKey(format: string, key: CryptoKey): Promise { + public static async exportKey(format: string, key: CryptoKey): Promise { switch (format.toLowerCase()) { case "jwk": - return JsonSerializer.toJSON(key); + return jsonSchema.JsonSerializer.toJSON(key); case "raw": return new Uint8Array(key.data).buffer; default: @@ -28,12 +28,12 @@ export class DesCrypto { } } - public static async importKey(format: string, keyData: JsonWebKey | ArrayBuffer, algorithm: any, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async importKey(format: string, keyData: types.JsonWebKey | ArrayBuffer, algorithm: any, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { let key: DesCryptoKey; switch (format.toLowerCase()) { case "jwk": - key = JsonParser.fromJSON(keyData, { targetSchema: DesCryptoKey }); + key = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: DesCryptoKey }); break; case "raw": key = new DesCryptoKey(); @@ -50,7 +50,7 @@ export class DesCrypto { return key; } - public static async encrypt(algorithm: DesParams, key: DesCryptoKey, data: Uint8Array): Promise { + public static async encrypt(algorithm: core.DesParams, key: DesCryptoKey, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "DES-CBC": return this.encryptDesCBC(algorithm, key, Buffer.from(data)); @@ -61,7 +61,7 @@ export class DesCrypto { } } - public static async decrypt(algorithm: DesParams, key: CryptoKey, data: Uint8Array): Promise { + public static async decrypt(algorithm: core.DesParams, key: CryptoKey, data: Uint8Array): Promise { if (!(key instanceof DesCryptoKey)) { throw new Error("key: Is not DesCryptoKey"); } @@ -76,7 +76,7 @@ export class DesCrypto { } } - public static async encryptDesCBC(algorithm: DesParams, key: DesCryptoKey, data: Buffer) { + public static async encryptDesCBC(algorithm: core.DesParams, key: DesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); @@ -84,14 +84,14 @@ export class DesCrypto { return res; } - public static async decryptDesCBC(algorithm: DesParams, key: DesCryptoKey, data: Buffer) { + public static async decryptDesCBC(algorithm: core.DesParams, key: DesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } - public static async encryptDesEDE3CBC(algorithm: DesParams, key: DesCryptoKey, data: Buffer) { + public static async encryptDesEDE3CBC(algorithm: core.DesParams, key: DesCryptoKey, data: Buffer) { const cipher = crypto.createCipheriv(`des-ede3-cbc`, key.data, Buffer.from(algorithm.iv as ArrayBuffer)); let enc = cipher.update(data); enc = Buffer.concat([enc, cipher.final()]); @@ -99,7 +99,7 @@ export class DesCrypto { return res; } - public static async decryptDesEDE3CBC(algorithm: DesParams, key: DesCryptoKey, data: Buffer) { + public static async decryptDesEDE3CBC(algorithm: core.DesParams, key: DesCryptoKey, data: Buffer) { const decipher = crypto.createDecipheriv(`des-ede3-cbc`, key.data, new Uint8Array(algorithm.iv as ArrayBuffer)); let dec = decipher.update(data); dec = Buffer.concat([dec, decipher.final()]); diff --git a/src/mechs/des/des_cbc.ts b/packages/node/src/mechs/des/des_cbc.ts similarity index 73% rename from src/mechs/des/des_cbc.ts rename to packages/node/src/mechs/des/des_cbc.ts index f180c69..02097bf 100644 --- a/src/mechs/des/des_cbc.ts +++ b/packages/node/src/mechs/des/des_cbc.ts @@ -1,4 +1,5 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage"; import { DesCrypto } from "./crypto"; @@ -12,7 +13,7 @@ export class DesCbcProvider extends core.DesProvider { public ivSize = 8; public name = "DES-CBC"; - public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await DesCrypto.generateKey( { name: this.name, @@ -32,11 +33,11 @@ export class DesCbcProvider extends core.DesProvider { return DesCrypto.decrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: CryptoKey): Promise { return DesCrypto.exportKey(format, getCryptoKey(key) as DesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages); if (key.data.length !== (this.keySizeBits >> 3)) { throw new core.OperationError("keyData: Wrong key size"); @@ -44,7 +45,7 @@ export class DesCbcProvider extends core.DesProvider { return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof DesCryptoKey)) { throw new TypeError("key: Is not a DesCryptoKey"); diff --git a/src/mechs/des/des_ede3_cbc.ts b/packages/node/src/mechs/des/des_ede3_cbc.ts similarity index 73% rename from src/mechs/des/des_ede3_cbc.ts rename to packages/node/src/mechs/des/des_ede3_cbc.ts index 9c65efd..c4869f7 100644 --- a/src/mechs/des/des_ede3_cbc.ts +++ b/packages/node/src/mechs/des/des_ede3_cbc.ts @@ -1,4 +1,5 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { CryptoKey } from "../../keys"; import { setCryptoKey, getCryptoKey } from "../storage"; import { DesCrypto } from "./crypto"; @@ -12,7 +13,7 @@ export class DesEde3CbcProvider extends core.DesProvider { public ivSize = 8; public name = "DES-EDE3-CBC"; - public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: core.DesKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await DesCrypto.generateKey( { name: this.name, @@ -32,11 +33,11 @@ export class DesEde3CbcProvider extends core.DesProvider { return DesCrypto.decrypt(algorithm, getCryptoKey(key) as DesCryptoKey, new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: CryptoKey): Promise { return DesCrypto.exportKey(format, getCryptoKey(key) as DesCryptoKey); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await DesCrypto.importKey(format, keyData, { name: this.name, length: this.keySizeBits }, extractable, keyUsages); if (key.data.length !== (this.keySizeBits >> 3)) { throw new core.OperationError("keyData: Wrong key size"); @@ -44,7 +45,7 @@ export class DesEde3CbcProvider extends core.DesProvider { return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof DesCryptoKey)) { throw new TypeError("key: Is not a DesCryptoKey"); diff --git a/src/mechs/des/index.ts b/packages/node/src/mechs/des/index.ts similarity index 100% rename from src/mechs/des/index.ts rename to packages/node/src/mechs/des/index.ts diff --git a/src/mechs/des/key.ts b/packages/node/src/mechs/des/key.ts similarity index 87% rename from src/mechs/des/key.ts rename to packages/node/src/mechs/des/key.ts index 65910da..e68b3d9 100644 --- a/src/mechs/des/key.ts +++ b/packages/node/src/mechs/des/key.ts @@ -1,5 +1,5 @@ import { JsonProp } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; import { JsonBase64UrlConverter } from "../../converters"; import { SymmetricKey } from "../../keys"; @@ -7,7 +7,7 @@ export class DesCryptoKey extends SymmetricKey { public override algorithm!: core.DesKeyAlgorithm; - @JsonProp({name: "k", converter: JsonBase64UrlConverter}) + @JsonProp({ name: "k", converter: JsonBase64UrlConverter }) public override data!: Buffer; // eslint-disable-next-line @typescript-eslint/ban-ts-comment diff --git a/src/mechs/ec/crypto.ts b/packages/node/src/mechs/ec/crypto.ts similarity index 70% rename from src/mechs/ec/crypto.ts rename to packages/node/src/mechs/ec/crypto.ts index 3dc157d..4f71555 100644 --- a/src/mechs/ec/crypto.ts +++ b/packages/node/src/mechs/ec/crypto.ts @@ -1,8 +1,10 @@ -import crypto from "crypto"; import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; import { BufferSourceConverter } from "pvtsutils"; -import * as core from "webcrypto-core"; import { CryptoKey } from "../../keys"; import { ShaCrypto } from "../sha"; import { getOidByNamedCurve } from "./helper"; @@ -14,7 +16,7 @@ export class EcCrypto { public static publicKeyUsages = ["verify"]; public static privateKeyUsages = ["sign", "deriveKey", "deriveBits"]; - public static async generateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async generateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const privateKey = new EcPrivateKey(); privateKey.algorithm = algorithm; privateKey.extractable = extractable; @@ -48,8 +50,8 @@ export class EcCrypto { return res; } - public static async sign(algorithm: EcdsaParams, key: EcPrivateKey, data: Uint8Array): Promise { - const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash as Algorithm); + public static async sign(algorithm: types.EcdsaParams, key: EcPrivateKey, data: Uint8Array): Promise { + const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash as types.Algorithm); const signer = crypto.createSign(cryptoAlg); signer.update(Buffer.from(data)); @@ -61,15 +63,15 @@ export class EcCrypto { }; const signature = signer.sign(options); - const ecSignature = AsnParser.parse(signature, core.asn1.EcDsaSignature); + const ecSignature = AsnParser.parse(signature, schema.EcDsaSignature); const signatureRaw = core.EcUtils.encodeSignature(ecSignature, core.EcCurves.get(key.algorithm.namedCurve).size); return signatureRaw.buffer; } - public static async verify(algorithm: EcdsaParams, key: EcPublicKey, signature: Uint8Array, data: Uint8Array): Promise { - const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash as Algorithm); + public static async verify(algorithm: types.EcdsaParams, key: EcPublicKey, signature: Uint8Array, data: Uint8Array): Promise { + const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash as types.Algorithm); const signer = crypto.createVerify(cryptoAlg); signer.update(Buffer.from(data)); @@ -80,7 +82,7 @@ export class EcCrypto { key: key.pem, }; - const ecSignature = new core.asn1.EcDsaSignature(); + const ecSignature = new schema.EcDsaSignature(); const namedCurve = core.EcCurves.get(key.algorithm.namedCurve); const signaturePoint = core.EcUtils.decodeSignature(signature, namedCurve.size); ecSignature.r = BufferSourceConverter.toArrayBuffer(signaturePoint.r); @@ -91,21 +93,21 @@ export class EcCrypto { return ok; } - public static async deriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { - const cryptoAlg = this.getOpenSSLNamedCurve((baseKey.algorithm as EcKeyAlgorithm).namedCurve); + public static async deriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { + const cryptoAlg = this.getOpenSSLNamedCurve((baseKey.algorithm as types.EcKeyAlgorithm).namedCurve); const ecdh = crypto.createECDH(cryptoAlg); - const asnPrivateKey = AsnParser.parse(baseKey.data, core.asn1.PrivateKeyInfo); - const asnEcPrivateKey = AsnParser.parse(asnPrivateKey.privateKey, core.asn1.EcPrivateKey); + const asnPrivateKey = AsnParser.parse(baseKey.data, schema.PrivateKeyInfo); + const asnEcPrivateKey = AsnParser.parse(asnPrivateKey.privateKey, schema.EcPrivateKey); ecdh.setPrivateKey(Buffer.from(asnEcPrivateKey.privateKey)); - const asnPublicKey = AsnParser.parse((algorithm.public as CryptoKey).data, core.asn1.PublicKeyInfo); + const asnPublicKey = AsnParser.parse((algorithm.public as CryptoKey).data, schema.PublicKeyInfo); const bits = ecdh.computeSecret(Buffer.from(asnPublicKey.publicKey)); return new Uint8Array(bits).buffer.slice(0, length >> 3); } - public static async exportKey(format: KeyFormat, key: CryptoKey): Promise { + public static async exportKey(format: types.KeyFormat, key: CryptoKey): Promise { switch (format.toLowerCase()) { case "jwk": return JsonSerializer.toJSON(key); @@ -113,7 +115,7 @@ export class EcCrypto { case "spki": return new Uint8Array(key.data).buffer; case "raw": { - const publicKeyInfo = AsnParser.parse(key.data, core.asn1.PublicKeyInfo); + const publicKeyInfo = AsnParser.parse(key.data, schema.PublicKeyInfo); return publicKeyInfo.publicKey; } default: @@ -121,31 +123,31 @@ export class EcCrypto { } } - public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async importKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { switch (format.toLowerCase()) { case "jwk": { - const jwk = keyData as JsonWebKey; + const jwk = keyData as types.JsonWebKey; if (jwk.d) { - const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.EcPrivateKey }); + const asnKey = JsonParser.fromJSON(keyData, { targetSchema: schema.EcPrivateKey }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { - const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.EcPublicKey }); + const asnKey = JsonParser.fromJSON(keyData, { targetSchema: schema.EcPublicKey }); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } } case "raw": { - const asnKey = new core.asn1.EcPublicKey(keyData as ArrayBuffer); + const asnKey = new schema.EcPublicKey(keyData as ArrayBuffer); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "spki": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PublicKeyInfo); - const asnKey = new core.asn1.EcPublicKey(keyInfo.publicKey); + const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), schema.PublicKeyInfo); + const asnKey = new schema.EcPublicKey(keyInfo.publicKey); this.assertKeyParameters(keyInfo.publicKeyAlgorithm.parameters, algorithm.namedCurve); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "pkcs8": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PrivateKeyInfo); - const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.EcPrivateKey); + const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), schema.PrivateKeyInfo); + const asnKey = AsnParser.parse(keyInfo.privateKey, schema.EcPrivateKey); this.assertKeyParameters(keyInfo.privateKeyAlgorithm.parameters, algorithm.namedCurve); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } @@ -161,7 +163,7 @@ export class EcCrypto { let namedCurveIdentifier = ""; try { - namedCurveIdentifier = AsnParser.parse(parameters, core.asn1.ObjectIdentifier).value; + namedCurveIdentifier = AsnParser.parse(parameters, schema.ObjectIdentifier).value; } catch (e) { throw new core.CryptoError("Cannot read key info parameters"); } @@ -171,33 +173,33 @@ export class EcCrypto { } } - protected static async importPrivateKey(asnKey: core.asn1.EcPrivateKey, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]) { - const keyInfo = new core.asn1.PrivateKeyInfo(); + protected static async importPrivateKey(asnKey: schema.EcPrivateKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { + const keyInfo = new schema.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; - keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(getOidByNamedCurve(algorithm.namedCurve))); + keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize(new schema.ObjectIdentifier(getOidByNamedCurve(algorithm.namedCurve))); keyInfo.privateKey = AsnSerializer.serialize(asnKey); const key = new EcPrivateKey(); key.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - key.algorithm = Object.assign({}, algorithm) as EcKeyAlgorithm; + key.algorithm = Object.assign({}, algorithm) as types.EcKeyAlgorithm; key.extractable = extractable; key.usages = keyUsages; return key; } - protected static async importPublicKey(asnKey: core.asn1.EcPublicKey, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]) { - const keyInfo = new core.asn1.PublicKeyInfo(); + protected static async importPublicKey(asnKey: schema.EcPublicKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { + const keyInfo = new schema.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; const namedCurve = getOidByNamedCurve(algorithm.namedCurve); - keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize(new core.asn1.ObjectIdentifier(namedCurve)); + keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize(new schema.ObjectIdentifier(namedCurve)); keyInfo.publicKey = asnKey.value; const key = new EcPublicKey(); key.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - key.algorithm = Object.assign({}, algorithm) as EcKeyAlgorithm; + key.algorithm = Object.assign({}, algorithm) as types.EcKeyAlgorithm; key.extractable = extractable; key.usages = keyUsages; diff --git a/packages/node/src/mechs/ec/ec_dh.ts b/packages/node/src/mechs/ec/ec_dh.ts new file mode 100644 index 0000000..3d89253 --- /dev/null +++ b/packages/node/src/mechs/ec/ec_dh.ts @@ -0,0 +1,50 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { CryptoKey } from "../../keys"; +import { setCryptoKey, getCryptoKey } from "../storage"; +import { EcCrypto } from "./crypto"; +import { EcPrivateKey } from "./private_key"; +import { EcPublicKey } from "./public_key"; + +export class EcdhProvider extends core.EcdhProvider { + + public override namedCurves = core.EcCurves.names; + + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const keys = await EcCrypto.generateKey( + { + ...algorithm, + name: this.name, + }, + extractable, + keyUsages); + + return { + privateKey: setCryptoKey(keys.privateKey as CryptoKey), + publicKey: setCryptoKey(keys.publicKey as CryptoKey), + }; + } + + public async onExportKey(format: types.KeyFormat, key: CryptoKey): Promise { + return EcCrypto.exportKey(format, getCryptoKey(key)); + } + + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); + return setCryptoKey(key); + } + + public override checkCryptoKey(key: CryptoKey, keyUsage?: types.KeyUsage) { + super.checkCryptoKey(key, keyUsage); + const internalKey = getCryptoKey(key); + if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) { + throw new TypeError("key: Is not EC CryptoKey"); + } + } + + public async onDeriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { + const bits = await EcCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length); + return bits; + } + +} diff --git a/src/mechs/ec/ec_dsa.ts b/packages/node/src/mechs/ec/ec_dsa.ts similarity index 57% rename from src/mechs/ec/ec_dsa.ts rename to packages/node/src/mechs/ec/ec_dsa.ts index fc88ab9..14a926d 100644 --- a/src/mechs/ec/ec_dsa.ts +++ b/packages/node/src/mechs/ec/ec_dsa.ts @@ -1,4 +1,5 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { setCryptoKey, getCryptoKey } from "../storage"; import { EcCrypto } from "./crypto"; import { EcPrivateKey } from "./private_key"; @@ -9,11 +10,11 @@ export class EcdsaProvider extends core.EcdsaProvider { public override namedCurves = core.EcCurves.names; public override hashAlgorithms = [ - "SHA-1", "SHA-256", "SHA-384", "SHA-512", - "shake128", "shake256", + "SHA-1", "SHA-256", "SHA-384", "SHA-512", + "shake128", "shake256", "SHA3-256", "SHA3-384", "SHA3-512"]; - public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const keys = await EcCrypto.generateKey( { ...algorithm, @@ -28,24 +29,24 @@ export class EcdsaProvider extends core.EcdsaProvider { }; } - public async onSign(algorithm: EcdsaParams, key: EcPrivateKey, data: ArrayBuffer): Promise { + public async onSign(algorithm: types.EcdsaParams, key: EcPrivateKey, data: ArrayBuffer): Promise { return EcCrypto.sign(algorithm, getCryptoKey(key) as EcPrivateKey, new Uint8Array(data)); } - public async onVerify(algorithm: EcdsaParams, key: EcPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + public async onVerify(algorithm: types.EcdsaParams, key: EcPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { return EcCrypto.verify(algorithm, getCryptoKey(key) as EcPublicKey, new Uint8Array(signature), new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: types.CryptoKey): Promise { return EcCrypto.exportKey(format, getCryptoKey(key)); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) { diff --git a/src/mechs/ec/helper.ts b/packages/node/src/mechs/ec/helper.ts similarity index 93% rename from src/mechs/ec/helper.ts rename to packages/node/src/mechs/ec/helper.ts index 88f68b1..1b4f68b 100644 --- a/src/mechs/ec/helper.ts +++ b/packages/node/src/mechs/ec/helper.ts @@ -1,6 +1,7 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; -const namedOIDs: { [key: string]: string } = { +// TODO use predefined OIDs from core +const namedOIDs: { [key: string]: string; } = { // P-256 "1.2.840.10045.3.1.7": "P-256", "P-256": "1.2.840.10045.3.1.7", diff --git a/src/mechs/ec/index.ts b/packages/node/src/mechs/ec/index.ts similarity index 100% rename from src/mechs/ec/index.ts rename to packages/node/src/mechs/ec/index.ts diff --git a/packages/node/src/mechs/ec/private_key.ts b/packages/node/src/mechs/ec/private_key.ts new file mode 100644 index 0000000..727de6f --- /dev/null +++ b/packages/node/src/mechs/ec/private_key.ts @@ -0,0 +1,49 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import { AsymmetricKey } from "../../keys"; +import { getOidByNamedCurve } from "./helper"; + +export class EcPrivateKey extends AsymmetricKey implements jsonSchema.IJsonConvertible { + public readonly type: "private" = "private"; + public override algorithm!: types.EcKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, schema.PrivateKeyInfo); + return asn1Schema.AsnParser.parse(keyInfo.privateKey, schema.EcPrivateKey); + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "EC", + crv: this.algorithm.namedCurve, + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); + } + + public fromJSON(json: types.JsonWebKey) { + if (!json.crv) { + throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); + } + + const keyInfo = new schema.PrivateKeyInfo(); + keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; + keyInfo.privateKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize( + new schema.ObjectIdentifier(getOidByNamedCurve(json.crv)), + ); + const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: schema.EcPrivateKey }); + keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + + return this; + } + +} diff --git a/packages/node/src/mechs/ec/public_key.ts b/packages/node/src/mechs/ec/public_key.ts new file mode 100644 index 0000000..b8825f1 --- /dev/null +++ b/packages/node/src/mechs/ec/public_key.ts @@ -0,0 +1,50 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import { AsymmetricKey } from "../../keys/asymmetric"; +import { getOidByNamedCurve } from "./helper"; + +export class EcPublicKey extends AsymmetricKey implements jsonSchema.IJsonConvertible { + + public readonly type: "public" = "public"; + public override algorithm!: types.EcKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, schema.PublicKeyInfo); + return new schema.EcPublicKey(keyInfo.publicKey); + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "EC", + crv: this.algorithm.namedCurve, + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); + } + + public fromJSON(json: types.JsonWebKey) { + if (!json.crv) { + throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); + } + + const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: schema.EcPublicKey }); + + const keyInfo = new schema.PublicKeyInfo(); + keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; + keyInfo.publicKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize( + new schema.ObjectIdentifier(getOidByNamedCurve(json.crv)), + ); + keyInfo.publicKey = asn1Schema.AsnSerializer.toASN(key).valueHex; + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + + return this; + } +} diff --git a/src/mechs/ed/crypto.ts b/packages/node/src/mechs/ed/crypto.ts similarity index 60% rename from src/mechs/ed/crypto.ts rename to packages/node/src/mechs/ed/crypto.ts index a1b9e4e..275db29 100644 --- a/src/mechs/ed/crypto.ts +++ b/packages/node/src/mechs/ed/crypto.ts @@ -1,8 +1,9 @@ -import crypto from "crypto"; -import { AsnParser } from "@peculiar/asn1-schema"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import { Convert } from "pvtsutils"; -import * as core from "webcrypto-core"; +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; +import * as pvtsutils from "pvtsutils"; import { CryptoKey } from "../../keys"; import { EdPrivateKey } from "./private_key"; import { EdPublicKey } from "./public_key"; @@ -12,7 +13,7 @@ export class EdCrypto { public static publicKeyUsages = ["verify"]; public static privateKeyUsages = ["sign", "deriveKey", "deriveBits"]; - public static async generateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async generateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const privateKey = new EdPrivateKey(); privateKey.algorithm = algorithm; privateKey.extractable = extractable; @@ -46,7 +47,7 @@ export class EdCrypto { return res; } - public static async sign(algorithm: Algorithm, key: EdPrivateKey, data: Uint8Array): Promise { + public static async sign(algorithm: types.Algorithm, key: EdPrivateKey, data: Uint8Array): Promise { if (!key.pem) { key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`; } @@ -55,10 +56,10 @@ export class EdCrypto { }; const signature = crypto.sign(null, Buffer.from(data), options); - return core.BufferSourceConverter.toArrayBuffer(signature); + return pvtsutils.BufferSourceConverter.toArrayBuffer(signature); } - public static async verify(algorithm: EcdsaParams, key: EdPublicKey, signature: Uint8Array, data: Uint8Array): Promise { + public static async verify(algorithm: types.EcdsaParams, key: EdPublicKey, signature: Uint8Array, data: Uint8Array): Promise { if (!key.pem) { key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`; } @@ -69,7 +70,7 @@ export class EdCrypto { return ok; } - public static async deriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { + public static async deriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { const publicKey = crypto.createPublicKey({ key: (algorithm.public as CryptoKey).data, format: "der", @@ -88,15 +89,15 @@ export class EdCrypto { return new Uint8Array(bits).buffer.slice(0, length >> 3); } - public static async exportKey(format: KeyFormat, key: CryptoKey): Promise { + public static async exportKey(format: types.KeyFormat, key: CryptoKey): Promise { switch (format.toLowerCase()) { case "jwk": - return JsonSerializer.toJSON(key); + return jsonSchema.JsonSerializer.toJSON(key); case "pkcs8": case "spki": return new Uint8Array(key.data).buffer; case "raw": { - const publicKeyInfo = AsnParser.parse(key.data, core.asn1.PublicKeyInfo); + const publicKeyInfo = asn1Schema.AsnParser.parse(key.data, core.PublicKeyInfo); return publicKeyInfo.publicKey; } default: @@ -104,30 +105,30 @@ export class EdCrypto { } } - public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async importKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { switch (format.toLowerCase()) { case "jwk": { - const jwk = keyData as JsonWebKey; + const jwk = keyData as types.JsonWebKey; if (jwk.d) { - const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.CurvePrivateKey }); + const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core.CurvePrivateKey }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { if (!jwk.x) { throw new TypeError("keyData: Cannot get required 'x' filed"); } - return this.importPublicKey(Convert.FromBase64Url(jwk.x), algorithm, extractable, keyUsages); + return this.importPublicKey(pvtsutils.Convert.FromBase64Url(jwk.x), algorithm, extractable, keyUsages); } } case "raw": { return this.importPublicKey(keyData as ArrayBuffer, algorithm, extractable, keyUsages); } case "spki": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PublicKeyInfo); + const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.PublicKeyInfo); return this.importPublicKey(keyInfo.publicKey, algorithm, extractable, keyUsages); } case "pkcs8": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PrivateKeyInfo); - const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.CurvePrivateKey); + const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.PrivateKeyInfo); + const asnKey = asn1Schema.AsnParser.parse(keyInfo.privateKey, core.CurvePrivateKey); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } default: @@ -135,28 +136,28 @@ export class EdCrypto { } } - protected static importPrivateKey(asnKey: core.asn1.CurvePrivateKey, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]) { + protected static importPrivateKey(asnKey: core.CurvePrivateKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { const key = new EdPrivateKey(); key.fromJSON({ crv: algorithm.namedCurve, - d: Convert.ToBase64Url(asnKey.d), + d: pvtsutils.Convert.ToBase64Url(asnKey.d), }); - - key.algorithm = Object.assign({}, algorithm) as EcKeyAlgorithm; + + key.algorithm = Object.assign({}, algorithm) as types.EcKeyAlgorithm; key.extractable = extractable; key.usages = keyUsages; - + return key; } - - protected static async importPublicKey(asnKey: ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]) { + + protected static async importPublicKey(asnKey: ArrayBuffer, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { const key = new EdPublicKey(); key.fromJSON({ crv: algorithm.namedCurve, - x: Convert.ToBase64Url(asnKey), + x: pvtsutils.Convert.ToBase64Url(asnKey), }); - key.algorithm = Object.assign({}, algorithm) as EcKeyAlgorithm; + key.algorithm = Object.assign({}, algorithm) as types.EcKeyAlgorithm; key.extractable = extractable; key.usages = keyUsages; diff --git a/packages/node/src/mechs/ed/ecdh_es.ts b/packages/node/src/mechs/ed/ecdh_es.ts new file mode 100644 index 0000000..39f0ef9 --- /dev/null +++ b/packages/node/src/mechs/ed/ecdh_es.ts @@ -0,0 +1,38 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { CryptoKey } from "../../keys"; +import { getCryptoKey, setCryptoKey } from "../storage"; +import { EdCrypto } from "./crypto"; + +export class EcdhEsProvider extends core.EcdhEsProvider { + + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const keys = await EdCrypto.generateKey( + { + name: this.name, + namedCurve: algorithm.namedCurve.toUpperCase(), + }, + extractable, + keyUsages); + + return { + privateKey: setCryptoKey(keys.privateKey as CryptoKey), + publicKey: setCryptoKey(keys.publicKey as CryptoKey), + }; + } + + public async onDeriveBits(algorithm: types.EcdhKeyDeriveParams, baseKey: core.BaseCryptoKey, length: number): Promise { + const bits = await EdCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length); + return bits; + } + + public async onExportKey(format: types.KeyFormat, key: CryptoKey): Promise { + return EdCrypto.exportKey(format, getCryptoKey(key)); + } + + public async onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); + return setCryptoKey(key); + } + +} \ No newline at end of file diff --git a/src/mechs/ed/eddsa.ts b/packages/node/src/mechs/ed/eddsa.ts similarity index 56% rename from src/mechs/ed/eddsa.ts rename to packages/node/src/mechs/ed/eddsa.ts index 807371d..7edae72 100644 --- a/src/mechs/ed/eddsa.ts +++ b/packages/node/src/mechs/ed/eddsa.ts @@ -1,4 +1,5 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { CryptoKey } from "../../keys"; import { getCryptoKey, setCryptoKey } from "../storage"; import { EdCrypto } from "./crypto"; @@ -7,7 +8,7 @@ import { EdPublicKey } from "./public_key"; export class EdDsaProvider extends core.EdDsaProvider { - public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.EcKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const keys = await EdCrypto.generateKey( { name: this.name, @@ -22,19 +23,19 @@ export class EdDsaProvider extends core.EdDsaProvider { }; } - public async onSign(algorithm: EcdsaParams, key: CryptoKey, data: ArrayBuffer): Promise { + public async onSign(algorithm: types.EcdsaParams, key: CryptoKey, data: ArrayBuffer): Promise { return EdCrypto.sign(algorithm, getCryptoKey(key) as EdPrivateKey, new Uint8Array(data)); } - public async onVerify(algorithm: EcdsaParams, key: CryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + public async onVerify(algorithm: types.EcdsaParams, key: CryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { return EdCrypto.verify(algorithm, getCryptoKey(key) as EdPublicKey, new Uint8Array(signature), new Uint8Array(data)); } - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: CryptoKey): Promise { return EdCrypto.exportKey(format, getCryptoKey(key)); } - public async onImportKey(format: KeyFormat, keyData: ArrayBuffer | JsonWebKey, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: ArrayBuffer | types.JsonWebKey, algorithm: types.EcKeyImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } diff --git a/src/mechs/ed/helper.ts b/packages/node/src/mechs/ed/helper.ts similarity index 57% rename from src/mechs/ed/helper.ts rename to packages/node/src/mechs/ed/helper.ts index e9482ab..a14c662 100644 --- a/src/mechs/ed/helper.ts +++ b/packages/node/src/mechs/ed/helper.ts @@ -1,18 +1,19 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; -const edOIDs: { [key: string]: string } = { +const edOIDs: { [key: string]: string; } = { // Ed448 - [core.asn1.idEd448]: "Ed448", - "ed448": core.asn1.idEd448, + [schema.idEd448]: "Ed448", + "ed448": schema.idEd448, // X448 - [core.asn1.idX448]: "X448", - "x448": core.asn1.idX448, + [schema.idX448]: "X448", + "x448": schema.idX448, // Ed25519 - [core.asn1.idEd25519]: "Ed25519", - "ed25519": core.asn1.idEd25519, + [schema.idEd25519]: "Ed25519", + "ed25519": schema.idEd25519, // X25519 - [core.asn1.idX25519]: "X25519", - "x25519": core.asn1.idX25519, + [schema.idX25519]: "X25519", + "x25519": schema.idX25519, }; export function getNamedCurveByOid(oid: string) { diff --git a/src/mechs/ed/index.ts b/packages/node/src/mechs/ed/index.ts similarity index 100% rename from src/mechs/ed/index.ts rename to packages/node/src/mechs/ed/index.ts diff --git a/packages/node/src/mechs/ed/private_key.ts b/packages/node/src/mechs/ed/private_key.ts new file mode 100644 index 0000000..49ee44b --- /dev/null +++ b/packages/node/src/mechs/ed/private_key.ts @@ -0,0 +1,46 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import { AsymmetricKey } from "../../keys"; +import { getOidByNamedCurve } from "./helper"; + +export class EdPrivateKey extends AsymmetricKey implements jsonSchema.IJsonConvertible { + public readonly type: "private" = "private"; + public override algorithm!: types.EcKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, schema.PrivateKeyInfo); + return asn1Schema.AsnParser.parse(keyInfo.privateKey, schema.CurvePrivateKey); + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "OKP", + crv: this.algorithm.namedCurve, + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); + } + + public fromJSON(json: types.JsonWebKey) { + if (!json.crv) { + throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); + } + + const keyInfo = new schema.PrivateKeyInfo(); + keyInfo.privateKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); + const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: schema.CurvePrivateKey }); + keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + + return this; + } + +} diff --git a/packages/node/src/mechs/ed/public_key.ts b/packages/node/src/mechs/ed/public_key.ts new file mode 100644 index 0000000..e4429db --- /dev/null +++ b/packages/node/src/mechs/ed/public_key.ts @@ -0,0 +1,51 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import * as pvtsutils from "pvtsutils"; +import { AsymmetricKey } from "../../keys/asymmetric"; +import { getOidByNamedCurve } from "./helper"; + +export class EdPublicKey extends AsymmetricKey implements jsonSchema.IJsonConvertible { + + public readonly type: "public" = "public"; + public override algorithm!: types.EcKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, schema.PublicKeyInfo); + return keyInfo.publicKey; + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "OKP", + crv: this.algorithm.namedCurve, + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, { + x: pvtsutils.Convert.ToBase64Url(key) + }); + } + + public fromJSON(json: types.JsonWebKey) { + if (!json.crv) { + throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); + } + if (!json.x) { + throw new core.OperationError(`Cannot get property from JWK. Property 'x' is required`); + } + + const keyInfo = new schema.PublicKeyInfo(); + keyInfo.publicKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); + keyInfo.publicKey = pvtsutils.Convert.FromBase64Url(json.x); + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + + return this; + } +} diff --git a/packages/node/src/mechs/hkdf/hkdf.ts b/packages/node/src/mechs/hkdf/hkdf.ts new file mode 100644 index 0000000..e7c9d52 --- /dev/null +++ b/packages/node/src/mechs/hkdf/hkdf.ts @@ -0,0 +1,54 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; +import * as pvtsutils from "pvtsutils"; +import { setCryptoKey, getCryptoKey } from "../storage"; +import { HkdfCryptoKey } from "./key"; + +export class HkdfProvider extends core.HkdfProvider { + + public async onImportKey(format: types.KeyFormat, keyData: ArrayBuffer, algorithm: types.HmacImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + if (format.toLowerCase() !== "raw") { + throw new core.OperationError("Operation not supported"); + } + + const key: HkdfCryptoKey = new HkdfCryptoKey(); + key.data = Buffer.from(keyData); + key.algorithm = { name: this.name }; + key.extractable = extractable; + key.usages = keyUsages; + return setCryptoKey(key); + } + + public async onDeriveBits(params: types.HkdfParams, baseKey: HkdfCryptoKey, length: number): Promise { + const hash = (params.hash as types.Algorithm).name.replace("-", ""); + const hashLength = crypto.createHash(hash).digest().length; + + const byteLength = length / 8; + const info = pvtsutils.BufferSourceConverter.toUint8Array(params.info); + + const PRK = crypto.createHmac(hash, pvtsutils.BufferSourceConverter.toUint8Array(params.salt)) + .update(pvtsutils.BufferSourceConverter.toUint8Array(getCryptoKey(baseKey).data)) + .digest(); + + const blocks = [Buffer.alloc(0)]; + const blockCount = Math.ceil(byteLength / hashLength) + 1; // Includes empty buffer + for (let i = 1; i < blockCount; ++i) { + blocks.push( + crypto.createHmac(hash, PRK) + .update(Buffer.concat([blocks[i - 1], info, Buffer.from([i])])) + .digest(), + ); + } + + return Buffer.concat(blocks).slice(0, byteLength); + } + + public override checkCryptoKey(key: core.BaseCryptoKey, keyUsage?: types.KeyUsage) { + super.checkCryptoKey(key, keyUsage); + if (!(getCryptoKey(key) instanceof HkdfCryptoKey)) { + throw new TypeError("key: Is not HKDF CryptoKey"); + } + } + +} diff --git a/packages/node/src/mechs/hkdf/index.ts b/packages/node/src/mechs/hkdf/index.ts new file mode 100644 index 0000000..9fbb9da --- /dev/null +++ b/packages/node/src/mechs/hkdf/index.ts @@ -0,0 +1 @@ +export * from "./hkdf"; diff --git a/src/mechs/hkdf/key.ts b/packages/node/src/mechs/hkdf/key.ts similarity index 55% rename from src/mechs/hkdf/key.ts rename to packages/node/src/mechs/hkdf/key.ts index 222b4e3..2a1a510 100644 --- a/src/mechs/hkdf/key.ts +++ b/packages/node/src/mechs/hkdf/key.ts @@ -1,8 +1,9 @@ +import * as types from "@peculiar/webcrypto-types"; import { CryptoKey } from "../../keys"; export class HkdfCryptoKey extends CryptoKey { public override data!: Buffer; - public override algorithm!: KeyAlgorithm; + public override algorithm!: types.KeyAlgorithm; } diff --git a/src/mechs/hmac/hmac.ts b/packages/node/src/mechs/hmac/hmac.ts similarity index 57% rename from src/mechs/hmac/hmac.ts rename to packages/node/src/mechs/hmac/hmac.ts index 1421af4..5efd039 100644 --- a/src/mechs/hmac/hmac.ts +++ b/packages/node/src/mechs/hmac/hmac.ts @@ -1,14 +1,15 @@ -import crypto from "crypto"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; import { ShaCrypto } from "../sha"; import { setCryptoKey, getCryptoKey } from "../storage"; import { HmacCryptoKey } from "./key"; export class HmacProvider extends core.HmacProvider { - public async onGenerateKey(algorithm: HmacKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const length = (algorithm.length || this.getDefaultLength((algorithm.hash as Algorithm).name)) >> 3 << 3; + public async onGenerateKey(algorithm: types.PreparedHashedAlgorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const length = (algorithm.length || this.getDefaultLength(algorithm.hash.name)) >> 3 << 3; const key = new HmacCryptoKey(); key.algorithm = { ...algorithm as any, @@ -22,7 +23,7 @@ export class HmacProvider extends core.HmacProvider { return setCryptoKey(key); } - public override async onSign(algorithm: Algorithm, key: HmacCryptoKey, data: ArrayBuffer): Promise { + public override async onSign(algorithm: types.Algorithm, key: HmacCryptoKey, data: ArrayBuffer): Promise { const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash); const hmac = crypto.createHmac(cryptoAlg, getCryptoKey(key).data) .update(Buffer.from(data)).digest(); @@ -30,7 +31,7 @@ export class HmacProvider extends core.HmacProvider { return new Uint8Array(hmac).buffer; } - public override async onVerify(algorithm: Algorithm, key: HmacCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + public override async onVerify(algorithm: types.Algorithm, key: HmacCryptoKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash); const hmac = crypto.createHmac(cryptoAlg, getCryptoKey(key).data) .update(Buffer.from(data)).digest(); @@ -38,12 +39,12 @@ export class HmacProvider extends core.HmacProvider { return hmac.compare(Buffer.from(signature)) === 0; } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: HmacImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.HmacImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { let key: HmacCryptoKey; switch (format.toLowerCase()) { case "jwk": - key = JsonParser.fromJSON(keyData, { targetSchema: HmacCryptoKey }); + key = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: HmacCryptoKey }); break; case "raw": key = new HmacCryptoKey(); @@ -54,7 +55,7 @@ export class HmacProvider extends core.HmacProvider { } key.algorithm = { - hash: { name: (algorithm.hash as Algorithm).name }, + hash: { name: (algorithm.hash as types.Algorithm).name }, name: this.name, length: key.data.length << 3, }; @@ -64,10 +65,10 @@ export class HmacProvider extends core.HmacProvider { return setCryptoKey(key); } - public async onExportKey(format: KeyFormat, key: HmacCryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: HmacCryptoKey): Promise { switch (format.toLowerCase()) { case "jwk": - return JsonSerializer.toJSON(getCryptoKey(key)); + return jsonSchema.JsonSerializer.toJSON(getCryptoKey(key)); case "raw": return new Uint8Array(getCryptoKey(key).data).buffer; default: @@ -75,7 +76,7 @@ export class HmacProvider extends core.HmacProvider { } } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof HmacCryptoKey)) { throw new TypeError("key: Is not HMAC CryptoKey"); diff --git a/src/mechs/hmac/index.ts b/packages/node/src/mechs/hmac/index.ts similarity index 100% rename from src/mechs/hmac/index.ts rename to packages/node/src/mechs/hmac/index.ts diff --git a/src/mechs/hmac/key.ts b/packages/node/src/mechs/hmac/key.ts similarity index 69% rename from src/mechs/hmac/key.ts rename to packages/node/src/mechs/hmac/key.ts index 15aa9f3..fcaf2a1 100644 --- a/src/mechs/hmac/key.ts +++ b/packages/node/src/mechs/hmac/key.ts @@ -1,13 +1,14 @@ -import { JsonProp } from "@peculiar/json-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as types from "@peculiar/webcrypto-types"; import { JsonBase64UrlConverter } from "../../converters"; import { CryptoKey } from "../../keys"; export class HmacCryptoKey extends CryptoKey { - @JsonProp({ name: "k", converter: JsonBase64UrlConverter }) + @jsonSchema.JsonProp({ name: "k", converter: JsonBase64UrlConverter }) public override data!: Buffer; - public override algorithm!: HmacKeyAlgorithm; + public override algorithm!: types.HmacKeyAlgorithm; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore diff --git a/src/mechs/index.ts b/packages/node/src/mechs/index.ts similarity index 100% rename from src/mechs/index.ts rename to packages/node/src/mechs/index.ts diff --git a/packages/node/src/mechs/pbkdf/index.ts b/packages/node/src/mechs/pbkdf/index.ts new file mode 100644 index 0000000..b038b9d --- /dev/null +++ b/packages/node/src/mechs/pbkdf/index.ts @@ -0,0 +1 @@ +export * from "./pbkdf2"; diff --git a/src/mechs/pbkdf/key.ts b/packages/node/src/mechs/pbkdf/key.ts similarity index 100% rename from src/mechs/pbkdf/key.ts rename to packages/node/src/mechs/pbkdf/key.ts diff --git a/src/mechs/pbkdf/pbkdf2.ts b/packages/node/src/mechs/pbkdf/pbkdf2.ts similarity index 57% rename from src/mechs/pbkdf/pbkdf2.ts rename to packages/node/src/mechs/pbkdf/pbkdf2.ts index 961c514..c18addb 100644 --- a/src/mechs/pbkdf/pbkdf2.ts +++ b/packages/node/src/mechs/pbkdf/pbkdf2.ts @@ -1,14 +1,16 @@ -import crypto from "crypto"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; +import * as pvtsutils from "pvtsutils"; import { setCryptoKey, getCryptoKey } from "../storage"; import { PbkdfCryptoKey } from "./key"; export class Pbkdf2Provider extends core.Pbkdf2Provider { - public async onDeriveBits(algorithm: Pbkdf2Params, baseKey: PbkdfCryptoKey, length: number): Promise { + public async onDeriveBits(algorithm: types.Pbkdf2Params, baseKey: PbkdfCryptoKey, length: number): Promise { return new Promise((resolve, reject) => { - const salt = core.BufferSourceConverter.toArrayBuffer(algorithm.salt); - const hash = (algorithm.hash as Algorithm).name.replace("-", ""); + const salt = pvtsutils.BufferSourceConverter.toArrayBuffer(algorithm.salt); + const hash = (algorithm.hash as types.Algorithm).name.replace("-", ""); crypto.pbkdf2(getCryptoKey(baseKey).data, Buffer.from(salt), algorithm.iterations, length >> 3, hash, (err, derivedBits) => { if (err) { reject(err); @@ -19,7 +21,7 @@ export class Pbkdf2Provider extends core.Pbkdf2Provider { }); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: Algorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.Algorithm, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { if (format === "raw") { const key = new PbkdfCryptoKey(); key.data = Buffer.from(keyData as ArrayBuffer); @@ -31,7 +33,7 @@ export class Pbkdf2Provider extends core.Pbkdf2Provider { throw new core.OperationError("format: Must be 'raw'"); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof PbkdfCryptoKey)) { throw new TypeError("key: Is not PBKDF CryptoKey"); diff --git a/src/mechs/rsa/crypto.ts b/packages/node/src/mechs/rsa/crypto.ts similarity index 62% rename from src/mechs/rsa/crypto.ts rename to packages/node/src/mechs/rsa/crypto.ts index a2fa260..8ea7a56 100644 --- a/src/mechs/rsa/crypto.ts +++ b/packages/node/src/mechs/rsa/crypto.ts @@ -1,7 +1,9 @@ -import crypto from "crypto"; -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as schema from "packages/core/src/schema"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; import { CryptoKey } from "../../keys"; import { RsaPrivateKey } from "./private_key"; import { RsaPublicKey } from "./public_key"; @@ -18,16 +20,16 @@ export class RsaCrypto { public static publicKeyUsages = ["verify", "encrypt", "wrapKey"]; public static privateKeyUsages = ["sign", "decrypt", "unwrapKey"]; - public static async generateKey(algorithm: RsaHashedKeyGenParams | RsaKeyGenParams, extractable: boolean, keyUsages: string[]): Promise { + public static async generateKey(algorithm: types.RsaHashedKeyGenParams | types.RsaKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const privateKey = new RsaPrivateKey(); - privateKey.algorithm = algorithm as RsaHashedKeyAlgorithm; + privateKey.algorithm = algorithm as types.RsaHashedKeyAlgorithm; privateKey.extractable = extractable; - privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1) as KeyUsage[]; + privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1); const publicKey = new RsaPublicKey(); - publicKey.algorithm = algorithm as RsaHashedKeyAlgorithm; + publicKey.algorithm = algorithm as types.RsaHashedKeyAlgorithm; publicKey.extractable = true; - publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1) as KeyUsage[]; + publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1); const publicExponent = Buffer.concat([ Buffer.alloc(4 - algorithm.publicExponent.byteLength, 0), @@ -58,10 +60,10 @@ export class RsaCrypto { return res; } - public static async exportKey(format: KeyFormat, key: CryptoKey): Promise { + public static async exportKey(format: types.KeyFormat, key: CryptoKey): Promise { switch (format.toLowerCase()) { case "jwk": - return JsonSerializer.toJSON(key); + return jsonSchema.JsonSerializer.toJSON(key); case "pkcs8": case "spki": return new Uint8Array(key.data).buffer; @@ -70,26 +72,26 @@ export class RsaCrypto { } } - public static async importKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public static async importKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { switch (format.toLowerCase()) { case "jwk": { - const jwk = keyData as JsonWebKey; + const jwk = keyData as types.JsonWebKey; if (jwk.d) { - const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.RsaPrivateKey }); + const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: schema.RsaPrivateKey }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { - const asnKey = JsonParser.fromJSON(keyData, { targetSchema: core.asn1.RsaPublicKey }); + const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: schema.RsaPublicKey }); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } } case "spki": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PublicKeyInfo); - const asnKey = AsnParser.parse(keyInfo.publicKey, core.asn1.RsaPublicKey); + const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), schema.PublicKeyInfo); + const asnKey = asn1Schema.AsnParser.parse(keyInfo.publicKey, schema.RsaPublicKey); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "pkcs8": { - const keyInfo = AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), core.asn1.PrivateKeyInfo); - const asnKey = AsnParser.parse(keyInfo.privateKey, core.asn1.RsaPrivateKey); + const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData as ArrayBuffer), schema.PrivateKeyInfo); + const asnKey = asn1Schema.AsnParser.parse(keyInfo.privateKey, schema.RsaPrivateKey); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } default: @@ -97,7 +99,7 @@ export class RsaCrypto { } } - public static async sign(algorithm: Algorithm, key: RsaPrivateKey, data: Uint8Array): Promise { + public static async sign(algorithm: types.Algorithm, key: RsaPrivateKey, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "RSA-PSS": case "RSASSA-PKCS1-V1_5": @@ -107,7 +109,7 @@ export class RsaCrypto { } } - public static async verify(algorithm: Algorithm, key: RsaPublicKey, signature: Uint8Array, data: Uint8Array): Promise { + public static async verify(algorithm: types.Algorithm, key: RsaPublicKey, signature: Uint8Array, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "RSA-PSS": case "RSASSA-PKCS1-V1_5": @@ -117,7 +119,7 @@ export class RsaCrypto { } } - public static async encrypt(algorithm: RsaOaepParams, key: RsaPublicKey, data: Uint8Array): Promise { + public static async encrypt(algorithm: types.RsaOaepParams, key: RsaPublicKey, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": return this.encryptOAEP(algorithm, key, data); @@ -126,7 +128,7 @@ export class RsaCrypto { } } - public static async decrypt(algorithm: RsaOaepParams, key: RsaPrivateKey, data: Uint8Array): Promise { + public static async decrypt(algorithm: types.RsaOaepParams, key: RsaPrivateKey, data: Uint8Array): Promise { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": return this.decryptOAEP(algorithm, key, data); @@ -135,16 +137,16 @@ export class RsaCrypto { } } - protected static importPrivateKey(asnKey: core.asn1.RsaPrivateKey, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]) { - const keyInfo = new core.asn1.PrivateKeyInfo(); + protected static importPrivateKey(asnKey: schema.RsaPrivateKey, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { + const keyInfo = new schema.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.privateKeyAlgorithm.parameters = null; - keyInfo.privateKey = AsnSerializer.serialize(asnKey); + keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(asnKey); const key = new RsaPrivateKey(); - key.data = Buffer.from(AsnSerializer.serialize(keyInfo)); + key.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); - key.algorithm = Object.assign({}, algorithm) as RsaHashedKeyAlgorithm; + key.algorithm = Object.assign({}, algorithm) as types.RsaHashedKeyAlgorithm; key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent); key.algorithm.modulusLength = asnKey.modulus.byteLength << 3; key.extractable = extractable; @@ -153,16 +155,16 @@ export class RsaCrypto { return key; } - protected static importPublicKey(asnKey: core.asn1.RsaPublicKey, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]) { - const keyInfo = new core.asn1.PublicKeyInfo(); + protected static importPublicKey(asnKey: schema.RsaPublicKey, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]) { + const keyInfo = new schema.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.publicKeyAlgorithm.parameters = null; - keyInfo.publicKey = AsnSerializer.serialize(asnKey); + keyInfo.publicKey = asn1Schema.AsnSerializer.serialize(asnKey); const key = new RsaPublicKey(); - key.data = Buffer.from(AsnSerializer.serialize(keyInfo)); + key.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); - key.algorithm = Object.assign({}, algorithm) as RsaHashedKeyAlgorithm; + key.algorithm = Object.assign({}, algorithm) as types.RsaHashedKeyAlgorithm; key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent); key.algorithm.modulusLength = asnKey.modulus.byteLength << 3; key.extractable = extractable; @@ -171,7 +173,7 @@ export class RsaCrypto { return key; } - protected static getCryptoAlgorithm(alg: RsaHashedKeyAlgorithm) { + protected static getCryptoAlgorithm(alg: types.RsaHashedKeyAlgorithm) { switch (alg.hash.name.toUpperCase()) { case "SHA-1": return "RSA-SHA1"; @@ -192,7 +194,7 @@ export class RsaCrypto { } } - protected static signRsa(algorithm: Algorithm, key: RsaPrivateKey, data: Uint8Array) { + protected static signRsa(algorithm: types.Algorithm, key: RsaPrivateKey, data: Uint8Array) { const cryptoAlg = this.getCryptoAlgorithm(key.algorithm); const signer = crypto.createSign(cryptoAlg); signer.update(Buffer.from(data)); @@ -205,14 +207,14 @@ export class RsaCrypto { }; if (algorithm.name.toUpperCase() === "RSA-PSS") { options.padding = crypto.constants.RSA_PKCS1_PSS_PADDING; - options.saltLength = (algorithm as RsaPssParams).saltLength; + options.saltLength = (algorithm as types.RsaPssParams).saltLength; } const signature = signer.sign(options); return new Uint8Array(signature).buffer; } - protected static verifySSA(algorithm: Algorithm, key: RsaPublicKey, data: Uint8Array, signature: Uint8Array) { + protected static verifySSA(algorithm: types.Algorithm, key: RsaPublicKey, data: Uint8Array, signature: Uint8Array) { const cryptoAlg = this.getCryptoAlgorithm(key.algorithm); const signer = crypto.createVerify(cryptoAlg); signer.update(Buffer.from(data)); @@ -225,14 +227,14 @@ export class RsaCrypto { }; if (algorithm.name.toUpperCase() === "RSA-PSS") { options.padding = crypto.constants.RSA_PKCS1_PSS_PADDING; - options.saltLength = (algorithm as RsaPssParams).saltLength; + options.saltLength = (algorithm as types.RsaPssParams).saltLength; } const ok = signer.verify(options, signature); return ok; } - protected static encryptOAEP(algorithm: RsaOaepParams, key: RsaPublicKey, data: Uint8Array) { + protected static encryptOAEP(algorithm: types.RsaOaepParams, key: RsaPublicKey, data: Uint8Array) { const options: crypto.RsaPublicKey = { key: `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, @@ -244,7 +246,7 @@ export class RsaCrypto { return new Uint8Array(crypto.publicEncrypt(options, data)).buffer; } - protected static decryptOAEP(algorithm: RsaOaepParams, key: RsaPrivateKey, data: Uint8Array) { + protected static decryptOAEP(algorithm: types.RsaOaepParams, key: RsaPrivateKey, data: Uint8Array) { const options: crypto.RsaPrivateKey = { key: `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, diff --git a/src/mechs/rsa/helper.ts b/packages/node/src/mechs/rsa/helper.ts similarity index 72% rename from src/mechs/rsa/helper.ts rename to packages/node/src/mechs/rsa/helper.ts index 6691b4c..7570291 100644 --- a/src/mechs/rsa/helper.ts +++ b/packages/node/src/mechs/rsa/helper.ts @@ -1,7 +1,7 @@ -/* eslint-disable @typescript-eslint/no-non-null-assertion */ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; -export function getJwkAlgorithm(algorithm: RsaHashedKeyAlgorithm) { +export function getJwkAlgorithm(algorithm: types.RsaHashedKeyAlgorithm): string { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": { const mdSize = /(\d+)$/.exec(algorithm.hash.name)![1]; diff --git a/src/mechs/rsa/index.ts b/packages/node/src/mechs/rsa/index.ts similarity index 100% rename from src/mechs/rsa/index.ts rename to packages/node/src/mechs/rsa/index.ts diff --git a/packages/node/src/mechs/rsa/private_key.ts b/packages/node/src/mechs/rsa/private_key.ts new file mode 100644 index 0000000..cb693a7 --- /dev/null +++ b/packages/node/src/mechs/rsa/private_key.ts @@ -0,0 +1,41 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { AsymmetricKey } from "../../keys"; +import { getJwkAlgorithm } from "./helper"; + +export class RsaPrivateKey extends AsymmetricKey { + public readonly type: "private" = "private"; + public override algorithm!: types.RsaHashedKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, core.PrivateKeyInfo); + return asn1Schema.AsnParser.parse(keyInfo.privateKey, core.RsaPrivateKey); + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "RSA", + alg: getJwkAlgorithm(this.algorithm), + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); + } + + public fromJSON(json: types.JsonWebKey) { + const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core.RsaPrivateKey }); + + const keyInfo = new core.PrivateKeyInfo(); + keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; + keyInfo.privateKeyAlgorithm.parameters = null; + keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + } + +} diff --git a/packages/node/src/mechs/rsa/public_key.ts b/packages/node/src/mechs/rsa/public_key.ts new file mode 100644 index 0000000..d7d8a1b --- /dev/null +++ b/packages/node/src/mechs/rsa/public_key.ts @@ -0,0 +1,40 @@ +import * as asn1Schema from "@peculiar/asn1-schema"; +import * as jsonSchema from "@peculiar/json-schema"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { AsymmetricKey } from "../../keys/asymmetric"; +import { getJwkAlgorithm } from "./helper"; + +export class RsaPublicKey extends AsymmetricKey { + public readonly type: "public" = "public"; + public override algorithm!: types.RsaHashedKeyAlgorithm; + + public getKey() { + const keyInfo = asn1Schema.AsnParser.parse(this.data, core.PublicKeyInfo); + return asn1Schema.AsnParser.parse(keyInfo.publicKey, core.RsaPublicKey); + } + + public toJSON() { + const key = this.getKey(); + + const json: types.JsonWebKey = { + kty: "RSA", + alg: getJwkAlgorithm(this.algorithm), + key_ops: this.usages, + ext: this.extractable, + }; + + return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); + } + + public fromJSON(json: types.JsonWebKey) { + const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core.RsaPublicKey }); + + const keyInfo = new core.PublicKeyInfo(); + keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; + keyInfo.publicKeyAlgorithm.parameters = null; + keyInfo.publicKey = asn1Schema.AsnSerializer.serialize(key); + + this.data = Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); + } +} diff --git a/src/mechs/rsa/rsa_es.ts b/packages/node/src/mechs/rsa/rsa_es.ts similarity index 66% rename from src/mechs/rsa/rsa_es.ts rename to packages/node/src/mechs/rsa/rsa_es.ts index fb24844..819ddf9 100644 --- a/src/mechs/rsa/rsa_es.ts +++ b/packages/node/src/mechs/rsa/rsa_es.ts @@ -1,6 +1,7 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import * as crypto from "crypto"; -import { Convert } from "pvtsutils"; -import * as core from "webcrypto-core"; +import * as pvtsutils from "pvtsutils"; import { setCryptoKey, getCryptoKey } from "../storage"; import { RsaCrypto } from "./crypto"; import { RsaPrivateKey } from "./private_key"; @@ -10,11 +11,11 @@ export class RsaEsProvider extends core.ProviderCrypto { public name = "RSAES-PKCS1-v1_5"; public usages = { - publicKey: ["encrypt", "wrapKey"] as core.KeyUsages, - privateKey: ["decrypt", "unwrapKey"] as core.KeyUsages, + publicKey: ["encrypt", "wrapKey"] as types.KeyUsages, + privateKey: ["decrypt", "unwrapKey"] as types.KeyUsages, }; - public override async onGenerateKey(algorithm: RsaKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public override async onGenerateKey(algorithm: types.RsaKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const keys = await RsaCrypto.generateKey( { ...algorithm, @@ -29,13 +30,13 @@ export class RsaEsProvider extends core.ProviderCrypto { }; } - public override checkGenerateKeyParams(algorithm: RsaKeyGenParams) { + public override checkGenerateKeyParams(algorithm: types.RsaKeyGenParams) { // public exponent this.checkRequiredProperty(algorithm, "publicExponent"); if (!(algorithm.publicExponent && algorithm.publicExponent instanceof Uint8Array)) { throw new TypeError("publicExponent: Missing or not a Uint8Array"); } - const publicExponent = Convert.ToBase64(algorithm.publicExponent); + const publicExponent = pvtsutils.Convert.ToBase64(algorithm.publicExponent); if (!(publicExponent === "Aw==" || publicExponent === "AQAB")) { throw new TypeError("publicExponent: Must be [3] or [1,0,1]"); } @@ -52,28 +53,28 @@ export class RsaEsProvider extends core.ProviderCrypto { } } - public override async onEncrypt(algorithm: Algorithm, key: RsaPublicKey, data: ArrayBuffer): Promise { + public override async onEncrypt(algorithm: types.Algorithm, key: RsaPublicKey, data: ArrayBuffer): Promise { const options = this.toCryptoOptions(key); const enc = crypto.publicEncrypt(options, new Uint8Array(data)); return new Uint8Array(enc).buffer; } - public override async onDecrypt(algorithm: Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise { + public override async onDecrypt(algorithm: types.Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise { const options = this.toCryptoOptions(key); const dec = crypto.privateDecrypt(options, new Uint8Array(data)); return new Uint8Array(dec).buffer; } - public override async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public override async onExportKey(format: types.KeyFormat, key: types.CryptoKey): Promise { return RsaCrypto.exportKey(format, getCryptoKey(key)); } - public override async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public override async onImportKey(format: types.KeyFormat, keyData: crypto.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { diff --git a/src/mechs/rsa/rsa_oaep.ts b/packages/node/src/mechs/rsa/rsa_oaep.ts similarity index 79% rename from src/mechs/rsa/rsa_oaep.ts rename to packages/node/src/mechs/rsa/rsa_oaep.ts index 03941a3..a1747c1 100644 --- a/src/mechs/rsa/rsa_oaep.ts +++ b/packages/node/src/mechs/rsa/rsa_oaep.ts @@ -1,5 +1,7 @@ -import crypto from "crypto"; -import * as core from "webcrypto-core"; +import * as crypto from "crypto"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import * as pvtsutils from "pvtsutils"; import { ShaCrypto } from "../sha/crypto"; import { setCryptoKey, getCryptoKey } from "../storage"; import { RsaCrypto } from "./crypto"; @@ -15,7 +17,7 @@ import { RsaPublicKey } from "./public_key"; export class RsaOaepProvider extends core.RsaOaepProvider { - public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const keys = await RsaCrypto.generateKey( { ...algorithm, @@ -24,13 +26,13 @@ export class RsaOaepProvider extends core.RsaOaepProvider { extractable, keyUsages); - return { - privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), - publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), - }; + return { + privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), + publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), + }; } - public async onEncrypt(algorithm: RsaOaepParams, key: RsaPublicKey, data: ArrayBuffer): Promise { + public async onEncrypt(algorithm: types.RsaOaepParams, key: RsaPublicKey, data: ArrayBuffer): Promise { const internalKey = getCryptoKey(key) as RsaPublicKey; const dataView = new Uint8Array(data); const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3); @@ -49,7 +51,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider { dataBlock.set(dataView, hashSize + psLength + 1); const labelHash = crypto.createHash(internalKey.algorithm.hash.name.replace("-", "")) - .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) + .update(pvtsutils.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .digest(); dataBlock.set(labelHash, 0); dataBlock[hashSize + psLength] = 1; @@ -78,7 +80,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider { return new Uint8Array(pkcs0).buffer; } - public async onDecrypt(algorithm: RsaOaepParams, key: RsaPrivateKey, data: ArrayBuffer): Promise { + public async onDecrypt(algorithm: types.RsaOaepParams, key: RsaPrivateKey, data: ArrayBuffer): Promise { const internalKey = getCryptoKey(key) as RsaPrivateKey; const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3); const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3; @@ -115,7 +117,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider { } const labelHash = crypto.createHash(internalKey.algorithm.hash.name.replace("-", "")) - .update(core.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) + .update(pvtsutils.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .digest(); for (let i = 0; i < hashSize; i++) { if (labelHash[i] !== dataBlock[i]) { @@ -142,16 +144,16 @@ export class RsaOaepProvider extends core.RsaOaepProvider { return new Uint8Array(pkcs0).buffer; } - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { + public async onExportKey(format: types.KeyFormat, key: types.CryptoKey): Promise { return RsaCrypto.exportKey(format, getCryptoKey(key)); } - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { @@ -165,7 +167,7 @@ export class RsaOaepProvider extends core.RsaOaepProvider { * @param seed * @param length */ - protected mgf1(algorithm: Algorithm, seed: Uint8Array, length = 0) { + protected mgf1(algorithm: types.Algorithm, seed: Uint8Array, length = 0) { const hashSize = ShaCrypto.size(algorithm) >> 3; const mask = new Uint8Array(length); const counter = new Uint8Array(4); diff --git a/packages/node/src/mechs/rsa/rsa_pss.ts b/packages/node/src/mechs/rsa/rsa_pss.ts new file mode 100644 index 0000000..fa4a3d6 --- /dev/null +++ b/packages/node/src/mechs/rsa/rsa_pss.ts @@ -0,0 +1,55 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { setCryptoKey, getCryptoKey } from "../storage"; +import { RsaCrypto } from "./crypto"; +import { RsaPrivateKey } from "./private_key"; +import { RsaPublicKey } from "./public_key"; + +export class RsaPssProvider extends core.RsaPssProvider { + + public override hashAlgorithms = [ + "SHA-1", "SHA-256", "SHA-384", "SHA-512", + "shake128", "shake256", + "SHA3-256", "SHA3-384", "SHA3-512"]; + + public async onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const keys = await RsaCrypto.generateKey( + { + ...algorithm, + name: this.name, + }, + extractable, + keyUsages); + + return { + privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), + publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), + }; + } + + public async onSign(algorithm: types.RsaPssParams, key: RsaPrivateKey, data: ArrayBuffer): Promise { + return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data)); + } + + public async onVerify(algorithm: types.RsaPssParams, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data)); + } + + public async onExportKey(format: types.KeyFormat, key: types.CryptoKey): Promise { + return RsaCrypto.exportKey(format, getCryptoKey(key)); + } + + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); + return setCryptoKey(key); + } + + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { + super.checkCryptoKey(key, keyUsage); + const internalKey = getCryptoKey(key); + if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { + throw new TypeError("key: Is not RSA CryptoKey"); + } + } + +} diff --git a/packages/node/src/mechs/rsa/rsa_ssa.ts b/packages/node/src/mechs/rsa/rsa_ssa.ts new file mode 100644 index 0000000..5d4f3eb --- /dev/null +++ b/packages/node/src/mechs/rsa/rsa_ssa.ts @@ -0,0 +1,55 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { setCryptoKey, getCryptoKey } from "../storage"; +import { RsaCrypto } from "./crypto"; +import { RsaPrivateKey } from "./private_key"; +import { RsaPublicKey } from "./public_key"; + +export class RsaSsaProvider extends core.RsaSsaProvider { + + public override hashAlgorithms = [ + "SHA-1", "SHA-256", "SHA-384", "SHA-512", + "shake128", "shake256", + "SHA3-256", "SHA3-384", "SHA3-512"]; + + public async onGenerateKey(algorithm: types.RsaHashedKeyGenParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const keys = await RsaCrypto.generateKey( + { + ...algorithm, + name: this.name, + }, + extractable, + keyUsages); + + return { + privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), + publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), + }; + } + + public async onSign(algorithm: types.Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise { + return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data)); + } + + public async onVerify(algorithm: types.Algorithm, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { + return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data)); + } + + public async onExportKey(format: types.KeyFormat, key: types.CryptoKey): Promise { + return RsaCrypto.exportKey(format, getCryptoKey(key)); + } + + public async onImportKey(format: types.KeyFormat, keyData: types.JsonWebKey | ArrayBuffer, algorithm: types.RsaHashedImportParams, extractable: boolean, keyUsages: types.KeyUsage[]): Promise { + const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); + return setCryptoKey(key); + } + + public override checkCryptoKey(key: types.CryptoKey, keyUsage?: types.KeyUsage) { + super.checkCryptoKey(key, keyUsage); + const internalKey = getCryptoKey(key); + if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { + throw new TypeError("key: Is not RSA CryptoKey"); + } + } + +} diff --git a/src/mechs/sha/crypto.ts b/packages/node/src/mechs/sha/crypto.ts similarity index 82% rename from src/mechs/sha/crypto.ts rename to packages/node/src/mechs/sha/crypto.ts index 8cc13d8..75816a5 100644 --- a/src/mechs/sha/crypto.ts +++ b/packages/node/src/mechs/sha/crypto.ts @@ -1,4 +1,5 @@ -import crypto from "crypto"; +import * as types from "@peculiar/webcrypto-types"; +import * as crypto from "crypto"; export class ShaCrypto { @@ -7,7 +8,7 @@ export class ShaCrypto { * @param algorithm Hash algorithm * @throws Throws Error if an unrecognized name */ - public static size(algorithm: Algorithm) { + public static size(algorithm: types.Algorithm) { switch (algorithm.name.toUpperCase()) { case "SHA-1": return 160; @@ -30,7 +31,7 @@ export class ShaCrypto { * @param algorithm WebCRypto algorithm * @throws Throws Error if an unrecognized name */ - public static getAlgorithmName(algorithm: Algorithm): string { + public static getAlgorithmName(algorithm: types.Algorithm): string { switch (algorithm.name.toUpperCase()) { case "SHA-1": return "sha1"; @@ -51,7 +52,7 @@ export class ShaCrypto { } } - public static digest(algorithm: Algorithm, data: ArrayBuffer) { + public static digest(algorithm: types.Algorithm, data: ArrayBuffer) { const hashAlg = this.getAlgorithmName(algorithm); const hash = crypto.createHash(hashAlg) .update(Buffer.from(data)).digest(); diff --git a/src/mechs/sha/index.ts b/packages/node/src/mechs/sha/index.ts similarity index 100% rename from src/mechs/sha/index.ts rename to packages/node/src/mechs/sha/index.ts diff --git a/packages/node/src/mechs/sha/sha3_256.ts b/packages/node/src/mechs/sha/sha3_256.ts new file mode 100644 index 0000000..f79aae8 --- /dev/null +++ b/packages/node/src/mechs/sha/sha3_256.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha3256Provider extends core.ProviderCrypto { + public name = "SHA3-256"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha3_384.ts b/packages/node/src/mechs/sha/sha3_384.ts new file mode 100644 index 0000000..9bfbce3 --- /dev/null +++ b/packages/node/src/mechs/sha/sha3_384.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha3384Provider extends core.ProviderCrypto { + public name = "SHA3-384"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha3_512.ts b/packages/node/src/mechs/sha/sha3_512.ts new file mode 100644 index 0000000..cfc69b5 --- /dev/null +++ b/packages/node/src/mechs/sha/sha3_512.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha3512Provider extends core.ProviderCrypto { + public name = "SHA3-512"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha_1.ts b/packages/node/src/mechs/sha/sha_1.ts new file mode 100644 index 0000000..0abcce9 --- /dev/null +++ b/packages/node/src/mechs/sha/sha_1.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha1Provider extends core.ProviderCrypto { + public name = "SHA-1"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha_256.ts b/packages/node/src/mechs/sha/sha_256.ts new file mode 100644 index 0000000..7ac65d9 --- /dev/null +++ b/packages/node/src/mechs/sha/sha_256.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha256Provider extends core.ProviderCrypto { + public name = "SHA-256"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha_384.ts b/packages/node/src/mechs/sha/sha_384.ts new file mode 100644 index 0000000..4db0f11 --- /dev/null +++ b/packages/node/src/mechs/sha/sha_384.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha384Provider extends core.ProviderCrypto { + public name = "SHA-384"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/packages/node/src/mechs/sha/sha_512.ts b/packages/node/src/mechs/sha/sha_512.ts new file mode 100644 index 0000000..b0ed952 --- /dev/null +++ b/packages/node/src/mechs/sha/sha_512.ts @@ -0,0 +1,13 @@ +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { ShaCrypto } from "./crypto"; + +export class Sha512Provider extends core.ProviderCrypto { + public name = "SHA-512"; + public usages = []; + + public override async onDigest(algorithm: types.Algorithm, data: ArrayBuffer): Promise { + return ShaCrypto.digest(algorithm, data); + } + +} diff --git a/src/mechs/shake/crypto.ts b/packages/node/src/mechs/shake/crypto.ts similarity index 68% rename from src/mechs/shake/crypto.ts rename to packages/node/src/mechs/shake/crypto.ts index 11594cd..96ad8fd 100644 --- a/src/mechs/shake/crypto.ts +++ b/packages/node/src/mechs/shake/crypto.ts @@ -1,10 +1,10 @@ -import crypto from "crypto"; -import * as core from "webcrypto-core"; +import * as crypto from "crypto"; +import * as core from "@peculiar/webcrypto-core"; export class ShakeCrypto { public static digest(algorithm: Required, data: ArrayBuffer) { - const hash = crypto.createHash(algorithm.name.toLowerCase(), {outputLength: algorithm.length}) + const hash = crypto.createHash(algorithm.name.toLowerCase(), { outputLength: algorithm.length }) .update(Buffer.from(data)).digest(); return new Uint8Array(hash).buffer; diff --git a/src/mechs/shake/index.ts b/packages/node/src/mechs/shake/index.ts similarity index 100% rename from src/mechs/shake/index.ts rename to packages/node/src/mechs/shake/index.ts diff --git a/src/mechs/shake/shake128.ts b/packages/node/src/mechs/shake/shake128.ts similarity index 84% rename from src/mechs/shake/shake128.ts rename to packages/node/src/mechs/shake/shake128.ts index ac26d38..1972be9 100644 --- a/src/mechs/shake/shake128.ts +++ b/packages/node/src/mechs/shake/shake128.ts @@ -1,4 +1,4 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; import { ShakeCrypto } from "./crypto"; export class Shake128Provider extends core.Shake128Provider { diff --git a/src/mechs/shake/shake256.ts b/packages/node/src/mechs/shake/shake256.ts similarity index 84% rename from src/mechs/shake/shake256.ts rename to packages/node/src/mechs/shake/shake256.ts index 7ab43ce..fa4561d 100644 --- a/src/mechs/shake/shake256.ts +++ b/packages/node/src/mechs/shake/shake256.ts @@ -1,4 +1,4 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; import { ShakeCrypto } from "./crypto"; export class Shake256Provider extends core.Shake256Provider { diff --git a/src/mechs/storage.ts b/packages/node/src/mechs/storage.ts similarity index 50% rename from src/mechs/storage.ts rename to packages/node/src/mechs/storage.ts index 3d3e2e9..ea9ff62 100644 --- a/src/mechs/storage.ts +++ b/packages/node/src/mechs/storage.ts @@ -1,9 +1,11 @@ -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; import { CryptoKey as InternalCryptoKey } from "../keys"; -const keyStorage = new WeakMap(); +const keyStorage = new WeakMap(); + +export function getCryptoKey(key: types.CryptoKey) { -export function getCryptoKey(key: core.CryptoKey) { const res = keyStorage.get(key); if (!res) { throw new core.OperationError("Cannot get CryptoKey from secure storage"); @@ -12,7 +14,7 @@ export function getCryptoKey(key: core.CryptoKey) { } export function setCryptoKey(value: InternalCryptoKey) { - const key = core.CryptoKey.create(value.algorithm, value.type, value.extractable, value.usages); + const key = core.BaseCryptoKey.create(value.algorithm, value.type, value.extractable, value.usages); Object.freeze(key); keyStorage.set(key, value); diff --git a/src/subtle.ts b/packages/node/src/subtle.ts similarity index 98% rename from src/subtle.ts rename to packages/node/src/subtle.ts index 47141c5..88ebce8 100644 --- a/src/subtle.ts +++ b/packages/node/src/subtle.ts @@ -1,6 +1,6 @@ import * as crypto from "crypto"; import * as process from "process"; -import * as core from "webcrypto-core"; +import * as core from "@peculiar/webcrypto-core"; import { AesCbcProvider, AesCmacProvider, AesCtrProvider, AesEcbProvider, AesGcmProvider, AesKwProvider, DesCbcProvider, diff --git a/test/crypto.ts b/packages/node/test/crypto.ts similarity index 82% rename from test/crypto.ts rename to packages/node/test/crypto.ts index 1f2106c..c024708 100644 --- a/test/crypto.ts +++ b/packages/node/test/crypto.ts @@ -1,11 +1,11 @@ -import assert from "assert"; -import process from "process"; import { WebcryptoTest } from "@peculiar/webcrypto-test"; +import * as core from "@peculiar/webcrypto-core"; +import * as types from "@peculiar/webcrypto-types"; +import { Crypto } from "@peculiar/webcrypto"; +import * as assert from "assert"; +import * as process from "process"; import { Convert } from "pvtsutils"; -import * as core from "webcrypto-core"; -import { Crypto } from "../src"; -// eslint-disable-next-line @typescript-eslint/no-non-null-assertion const nodeMajorVersion = parseInt(/^v(\d+)/.exec(process.version)![1], 10); const crypto = new Crypto(); @@ -48,7 +48,7 @@ context("Crypto", () => { await assert.rejects(crypto.subtle.importKey( "spki", spki, - { name: "ECDSA", namedCurve: "K-256" } as Algorithm, + { name: "ECDSA", namedCurve: "K-256" } as types.Algorithm, false, ["verify"]), core.CryptoError); }); @@ -60,15 +60,15 @@ context("Crypto", () => { hash: "SHA-256", info: new Uint8Array([1, 2, 3, 4, 5]), salt: new Uint8Array([1, 2, 3, 4, 5]), - } as HkdfParams, + } as types.HkdfParams, hkdf, { name: "HMAC", hash: "SHA-1", - } as globalThis.HmacImportParams, + } as types.HmacImportParams, false, ["sign"]); - assert.strictEqual((hmac.algorithm as globalThis.HmacKeyAlgorithm).length, 512); + assert.strictEqual((hmac.algorithm as types.HmacKeyAlgorithm).length, 512); }); (nodeMajorVersion < 14 ? context.skip : context)("EdDSA", () => { @@ -76,7 +76,7 @@ context("Crypto", () => { context("generateKey", () => { it("RSA 3072bits", async () => { - const alg: globalThis.RsaHashedKeyGenParams = { + const alg: types.RsaHashedKeyGenParams = { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256", publicExponent: new Uint8Array([1, 0, 1]), @@ -84,26 +84,26 @@ context("Crypto", () => { }; const keys = await crypto.subtle.generateKey(alg, false, ["sign", "verify"]); - assert.strictEqual((keys.privateKey.algorithm as RsaHashedKeyAlgorithm).modulusLength, 3072); + assert.strictEqual((keys.privateKey.algorithm as types.RsaHashedKeyAlgorithm).modulusLength, 3072); }); it("Ed25519", async () => { - const keys = await crypto.subtle.generateKey({ name: "eddsa", namedCurve: "ed25519" } as globalThis.EcKeyGenParams, false, ["sign", "verify"]); + const keys = await crypto.subtle.generateKey({ name: "eddsa", namedCurve: "ed25519" } as types.EcKeyGenParams, false, ["sign", "verify"]); assert.strictEqual(keys.privateKey.algorithm.name, "EdDSA"); - assert.strictEqual((keys.privateKey.algorithm as EcKeyAlgorithm).namedCurve, "Ed25519"); + assert.strictEqual((keys.privateKey.algorithm as types.EcKeyAlgorithm).namedCurve, "Ed25519"); }); it("Ed448", async () => { - const keys = await crypto.subtle.generateKey({ name: "eddsa", namedCurve: "ed448" } as globalThis.EcKeyGenParams, true, ["sign", "verify"]); + const keys = await crypto.subtle.generateKey({ name: "eddsa", namedCurve: "ed448" } as types.EcKeyGenParams, true, ["sign", "verify"]); assert.strictEqual(keys.privateKey.algorithm.name, "EdDSA"); - assert.strictEqual((keys.privateKey.algorithm as EcKeyAlgorithm).namedCurve, "Ed448"); + assert.strictEqual((keys.privateKey.algorithm as types.EcKeyAlgorithm).namedCurve, "Ed448"); const data = await crypto.subtle.exportKey("jwk", keys.privateKey); assert.strictEqual(data.kty, "OKP"); assert.strictEqual(data.crv, "Ed448"); assert.strictEqual(!!data.d, true); - const privateKey = await crypto.subtle.importKey("jwk", data, { name: "eddsa", namedCurve: "ed448" } as EcKeyImportParams, false, ["sign"]); + const privateKey = await crypto.subtle.importKey("jwk", data, { name: "eddsa", namedCurve: "ed448" } as types.EcKeyImportParams, false, ["sign"]); const message = Buffer.from("message"); const signature = await crypto.subtle.sign({ name: "EdDSA" }, privateKey, message); @@ -120,17 +120,17 @@ context("Crypto", () => { context("generateKey", () => { it("X25519", async () => { - const keys = await crypto.subtle.generateKey({ name: "ecdh-es", namedCurve: "x25519" } as globalThis.EcKeyGenParams, false, ["deriveBits", "deriveKey"]); + const keys = await crypto.subtle.generateKey({ name: "ecdh-es", namedCurve: "x25519" } as types.EcKeyGenParams, false, ["deriveBits", "deriveKey"]); assert.strictEqual(keys.privateKey.algorithm.name, "ECDH-ES"); - assert.strictEqual((keys.privateKey.algorithm as EcKeyAlgorithm).namedCurve, "X25519"); + assert.strictEqual((keys.privateKey.algorithm as types.EcKeyAlgorithm).namedCurve, "X25519"); }); it("X448", async () => { - const keys = await crypto.subtle.generateKey({ name: "ecdh-es", namedCurve: "x448" } as globalThis.EcKeyGenParams, true, ["deriveBits", "deriveKey"]); + const keys = await crypto.subtle.generateKey({ name: "ecdh-es", namedCurve: "x448" } as types.EcKeyGenParams, true, ["deriveBits", "deriveKey"]); assert.strictEqual(keys.privateKey.algorithm.name, "ECDH-ES"); - assert.strictEqual((keys.privateKey.algorithm as EcKeyAlgorithm).namedCurve, "X448"); + assert.strictEqual((keys.privateKey.algorithm as types.EcKeyAlgorithm).namedCurve, "X448"); - const bits = await crypto.subtle.deriveBits({ name: "ECDH-ES", public: keys.publicKey } as globalThis.EcdhKeyDeriveParams, keys.privateKey, 256); + const bits = await crypto.subtle.deriveBits({ name: "ECDH-ES", public: keys.publicKey } as types.EcdhKeyDeriveParams, keys.privateKey, 256); assert.strictEqual(bits.byteLength, 32); const data = await crypto.subtle.exportKey("jwk", keys.publicKey); @@ -166,8 +166,8 @@ context("Crypto", () => { namedCurves.forEach((namedCurve) => { it(namedCurve, async () => { - const alg: EcKeyGenParams = { name: "ECDSA", namedCurve }; - const signAlg = { ...alg, hash: "SHA-256" } as EcdsaParams; + const alg: types.EcKeyGenParams = { name: "ECDSA", namedCurve }; + const signAlg = { ...alg, hash: "SHA-256" } as types.EcdsaParams; const keys = await crypto.subtle.generateKey(alg, true, ["sign", "verify"]); @@ -195,11 +195,11 @@ context("Crypto", () => { context("deriveBits + jwk", () => { namedCurves.forEach((namedCurve) => { it(namedCurve, async () => { - const alg: EcKeyGenParams = { name: "ECDH", namedCurve }; + const alg: types.EcKeyGenParams = { name: "ECDH", namedCurve }; const keys = await crypto.subtle.generateKey(alg, true, ["deriveBits", "deriveKey"]); - const deriveAlg: EcdhKeyDeriveParams = { name: "ECDH", public: keys.publicKey }; + const deriveAlg: types.EcdhKeyDeriveParams = { name: "ECDH", public: keys.publicKey }; const derivedBits = await crypto.subtle.deriveBits(deriveAlg, keys.privateKey, 128); const privateJwk = await crypto.subtle.exportKey("jwk", keys.privateKey); @@ -207,8 +207,8 @@ context("Crypto", () => { const privateKey = await crypto.subtle.importKey("jwk", privateJwk, alg, true, ["deriveBits"]); const publicKey = await crypto.subtle.importKey("jwk", publicJwk, alg, true, []); - const derivedBits2 = await crypto.subtle.deriveBits({ name: "ECDH", public: keys.publicKey } as EcdhKeyDeriveParams, privateKey, 128); - const derivedBits3 = await crypto.subtle.deriveBits({ name: "ECDH", public: publicKey } as EcdhKeyDeriveParams, keys.privateKey, 128); + const derivedBits2 = await crypto.subtle.deriveBits({ name: "ECDH", public: keys.publicKey } as types.EcdhKeyDeriveParams, privateKey, 128); + const derivedBits3 = await crypto.subtle.deriveBits({ name: "ECDH", public: publicKey } as types.EcdhKeyDeriveParams, keys.privateKey, 128); assert.strictEqual(Convert.ToHex(derivedBits2), Convert.ToHex(derivedBits)); assert.strictEqual(Convert.ToHex(derivedBits3), Convert.ToHex(derivedBits)); @@ -222,7 +222,7 @@ context("Crypto", () => { const jwk = await crypto.subtle.exportKey("jwk", aesKey); delete jwk.key_ops; delete jwk.alg; - const hmacKey = await crypto.subtle.importKey("jwk", jwk, { name: "HMAC", hash: "SHA-256" } as Algorithm, false, ["sign", "verify"]); + const hmacKey = await crypto.subtle.importKey("jwk", jwk, { name: "HMAC", hash: "SHA-256" } as types.Algorithm, false, ["sign", "verify"]); assert.strictEqual(hmacKey.algorithm.name, "HMAC"); }); diff --git a/packages/test/README.md b/packages/test/README.md new file mode 100644 index 0000000..74eae70 --- /dev/null +++ b/packages/test/README.md @@ -0,0 +1,11 @@ +# `@peculiar/webcrypto-test` + +> TODO: description + +## Usage + +``` +const webcryptoTest = require('@peculiar/webcrypto-test'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/test/package.json b/packages/test/package.json new file mode 100644 index 0000000..ad32949 --- /dev/null +++ b/packages/test/package.json @@ -0,0 +1,29 @@ +{ + "name": "@peculiar/webcrypto-test", + "version": "3.0.0", + "description": "> TODO: description", + "author": "microshine ", + "homepage": "https://github.com/PeculiarVentures/webcrypto/tree/master/packages/webcrypto-test#readme", + "license": "MIT", + "main": "build/index.js", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/PeculiarVentures/webcrypto.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/PeculiarVentures/webcrypto/issues" + } +} diff --git a/packages/test/src/helper.ts b/packages/test/src/helper.ts new file mode 100644 index 0000000..b8aea77 --- /dev/null +++ b/packages/test/src/helper.ts @@ -0,0 +1,263 @@ + +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; +import { Convert } from "pvtsutils"; +import * as testTypes from "./types"; + +/** + * Gets keys + * @param crypto + * @param key + */ +async function getKeys(crypto: types.Crypto, key: testTypes.IImportKeyParams | testTypes.IImportKeyPairParams) { + const keys = {} as types.CryptoKeyPair; + if ("privateKey" in key) { + keys.privateKey = await crypto.subtle.importKey( + key.privateKey.format, + key.privateKey.data, + key.privateKey.algorithm, + key.privateKey.extractable, + key.privateKey.keyUsages); + keys.publicKey = await crypto.subtle.importKey( + key.publicKey.format, + key.publicKey.data, + key.publicKey.algorithm, + key.publicKey.extractable, + key.publicKey.keyUsages); + } else { + keys.privateKey = keys.publicKey = await crypto.subtle.importKey( + key.format, + key.data, + key.algorithm, + key.extractable, + key.keyUsages); + } + return keys; +} + +async function wrapTest(promise: () => Promise, action: testTypes.ITestAction, index: number) { + const test = action.skip + ? it.skip + : action.only + ? it.only + : it; + + test(action.name || `#${index + 1}`, async () => { + if (action.error) { + await assert.rejects(promise(), action.error); + } else { + await promise(); + } + }); +} + +function isKeyPair(obj: any): obj is types.CryptoKeyPair { + return obj.privateKey && obj.publicKey; +} + +function testGenerateKey(generateKey: testTypes.ITestGenerateKeyAction[], crypto: types.Crypto) { + context("Generate Key", () => { + generateKey.forEach((action, index) => { + wrapTest(async () => { + const algorithm = Object.assign({}, action.algorithm); + algorithm.name = algorithm.name.toLowerCase(); + const key = await crypto.subtle.generateKey(algorithm, action.extractable, action.keyUsages); + assert(key); + if (!isKeyPair(key)) { + assert.equal(key.algorithm.name, action.algorithm.name, "Algorithm name MUST be equal to incoming algorithm and in the same case"); + assert.equal(key.extractable, action.extractable); + assert.deepEqual(key.usages, action.keyUsages); + } else { + assert(key.privateKey); + assert.equal(key.privateKey.algorithm.name, action.algorithm.name, "Algorithm name MUST be equal to incoming algorithm and in the same case"); + assert.equal(key.privateKey.extractable, action.extractable); + assert(key.publicKey); + assert.equal(key.publicKey.algorithm.name, action.algorithm.name, "Algorithm name MUST be equal to incoming algorithm and in the same case"); + assert.equal(key.publicKey.extractable, true); + } + action.assert?.(key); + }, action, index); + }); + }); +} + +function testImport(importFn: testTypes.ITestImportAction[], crypto: types.Crypto) { + context("Import/Export", () => { + importFn.forEach((action, index) => { + wrapTest(async () => { + // @ts-ignore + const importedKey = await crypto.subtle.importKey(action.format, action.data, action.algorithm, action.extractable, action.keyUsages); + // Can't continue if key is not extractable. + if (!action.extractable) { + return; + } + const exportedData = await crypto.subtle.exportKey(action.format, importedKey); + if (action.format === "jwk") { + assert.deepEqual(exportedData, action.data); + } else { + assert.equal(Buffer.from(exportedData as ArrayBuffer).toString("hex"), Buffer.from(action.data as ArrayBuffer).toString("hex")); + } + action.assert?.(importedKey); + }, action, index); + }); + }); +} + +function testSign(sign: testTypes.ITestSignAction[], crypto: types.Crypto) { + context("Sign/Verify", () => { + sign.forEach((action, index) => { + wrapTest(async () => { + // import keys + const keys = await getKeys(crypto, action.key); + const verifyKey = keys.publicKey; + const signKey = keys.privateKey; + const algorithm = Object.assign({}, action.algorithm); + algorithm.name = algorithm.name.toLowerCase(); + // sign + // @ts-ignore + const signature = await crypto.subtle.sign(algorithm, signKey, action.data); + // verify + // @ts-ignore + let ok = await crypto.subtle.verify(algorithm, verifyKey, signature, action.data); + assert.equal(true, ok, "Cannot verify signature from Action data"); + // @ts-ignore + ok = await crypto.subtle.verify(algorithm, verifyKey, action.signature, action.data); + if (!ok) { + assert.equal(Convert.ToHex(signature), Convert.ToHex(action.signature)); + } + assert.equal(true, ok); + }, action, index); + }); + }); +} + +function testDeriveBits(deriveBits: testTypes.ITestDeriveBitsAction[], crypto: types.Crypto) { + context("Derive bits", () => { + deriveBits.forEach((action, index) => { + wrapTest(async () => { + // import keys + const keys = await getKeys(crypto, action.key); + const algorithm = Object.assign({}, action.algorithm, { public: keys.publicKey }) as any; + algorithm.name = algorithm.name.toLowerCase(); + // derive bits + const derivedBits = await crypto.subtle.deriveBits(algorithm, keys.privateKey, action.length); + assert.equal(Convert.ToHex(derivedBits), Convert.ToHex(action.data)); + }, action, index); + }); + }); +} + +function testDeriveKey(deriveKey: testTypes.ITestDeriveKeyAction[], crypto: types.Crypto) { + context("Derive key", () => { + deriveKey.forEach((action, index) => { + wrapTest(async () => { + // import keys + const keys = await getKeys(crypto, action.key); + const algorithm = Object.assign({}, action.algorithm, { public: keys.publicKey }) as any; + algorithm.name = algorithm.name.toLowerCase(); + // derive key + // @ts-ignore + const derivedKey = await crypto.subtle.deriveKey(algorithm, keys.privateKey, action.derivedKeyType, true, action.keyUsages); + const keyData = await crypto.subtle.exportKey(action.format, derivedKey); + if (action.format === "jwk") { + assert.deepEqual(keyData, action.keyData); + } else { + assert.equal(Convert.ToHex(keyData as ArrayBuffer), Convert.ToHex(action.keyData as ArrayBuffer)); + } + action.assert?.(derivedKey); + }, action, index); + }); + }); +} + +function testWrap(wrapKey: testTypes.ITestWrapKeyAction[], crypto: types.Crypto) { + context("Wrap/Unwrap key", () => { + wrapKey.forEach((action, index) => { + wrapTest(async () => { + const wKey = (await getKeys(crypto, action.wKey)).privateKey; + const key = await getKeys(crypto, action.key); + const wrappedKey = await crypto.subtle.wrapKey(action.wKey.format, wKey, key.publicKey, action.algorithm); + if (action.wrappedKey) { + assert.equal(Convert.ToHex(wrappedKey), Convert.ToHex(action.wrappedKey)); + } + const unwrappedKey = await crypto.subtle.unwrapKey(action.wKey.format, wrappedKey, key.privateKey, action.algorithm, action.wKey.algorithm, action.wKey.extractable, action.wKey.keyUsages); + assert.deepEqual(unwrappedKey.algorithm, wKey.algorithm); + }, action, index); + }); + }); +} + +function testDigest(digest: testTypes.ITestDigestAction[], crypto: types.Crypto) { + context("Digest", () => { + digest.forEach((action, index) => { + wrapTest(async () => { + // @ts-ignore + const hash = await crypto.subtle.digest(action.algorithm, action.data); + assert.equal(Convert.ToHex(hash), Convert.ToHex(action.hash)); + }, action, index); + }); + }); +} + +function testEncrypt(encrypt: testTypes.ITestEncryptAction[], crypto: types.Crypto) { + context("Encrypt/Decrypt", () => { + encrypt.forEach((action, index) => { + wrapTest(async () => { + // import keys + const keys = await getKeys(crypto, action.key); + const encKey = keys.publicKey; + const decKey = keys.privateKey; + const algorithm = Object.assign({}, action.algorithm); + algorithm.name = algorithm.name.toLowerCase(); + // encrypt + // @ts-ignore + const enc = await crypto.subtle.encrypt(algorithm, encKey, action.data); + // decrypt + let dec = await crypto.subtle.decrypt(algorithm, decKey, enc); + assert.equal(Convert.ToHex(dec), Convert.ToHex(action.data)); + // @ts-ignore + dec = await crypto.subtle.decrypt(algorithm, decKey, action.encData); + assert.equal(Convert.ToHex(dec), Convert.ToHex(action.data)); + }, action, index); + }); + }); +} + +export function testCrypto(crypto: types.Crypto, param: testTypes.ITestParams) { + context(param.name, () => { + + if (param.actions.generateKey) { + testGenerateKey(param.actions.generateKey, crypto); + } + + if (param.actions.encrypt) { + testEncrypt(param.actions.encrypt, crypto); + } + + if (param.actions.import) { + testImport(param.actions.import, crypto); + } + + if (param.actions.sign) { + testSign(param.actions.sign, crypto); + } + + if (param.actions.deriveBits) { + testDeriveBits(param.actions.deriveBits, crypto); + } + + if (param.actions.deriveKey) { + testDeriveKey(param.actions.deriveKey, crypto); + } + + const digest = param.actions.digest; + if (digest) { + testDigest(digest, crypto); + } + + const wrapKey = param.actions.wrapKey; + if (wrapKey) { + testWrap(wrapKey, crypto); + } + }); +} \ No newline at end of file diff --git a/packages/test/src/index.ts b/packages/test/src/index.ts new file mode 100644 index 0000000..2c6b04c --- /dev/null +++ b/packages/test/src/index.ts @@ -0,0 +1,2 @@ +export * from "./webcrypto_test"; +export * as vectors from "./vectors"; diff --git a/packages/test/src/types.ts b/packages/test/src/types.ts new file mode 100644 index 0000000..6f847b4 --- /dev/null +++ b/packages/test/src/types.ts @@ -0,0 +1,130 @@ +import * as types from "@peculiar/webcrypto-types"; + +export interface ITestAction { + name?: string; + only?: boolean; + skip?: boolean; + error?: any; +} + +export interface ITestVectorsExclude { + [name: string]: boolean | undefined; + AES128CBC?: boolean; + AES192CBC?: boolean; + AES256CBC?: boolean; + AES128CMAC?: boolean; + AES192CMAC?: boolean; + AES128CTR?: boolean; + AES192CTR?: boolean; + AES256CTR?: boolean; + AES128ECB?: boolean; + AES192ECB?: boolean; + AES256ECB?: boolean; + AES128GCM?: boolean; + AES192GCM?: boolean; + AES256GCM?: boolean; + AES128KW?: boolean; + AES192KW?: boolean; + AES256KW?: boolean; + + DESCBC?: boolean; + DESEDE3CBC?: boolean; + + RSAESPKCS1?: boolean; + RSASSAPKCS1?: boolean; + RSAOAEP?: boolean; + RSAPSS?: boolean; + + ECDSA?: boolean; + ECDH?: boolean; + + HKDF?: boolean; + HMAC?: boolean; + PBKDF2?: boolean; + SHA?: boolean; +} + +export interface ITestGenerateKeyAction extends ITestAction { + algorithm: types.Algorithm; + extractable: boolean; + keyUsages: types.KeyUsage[]; + assert?: (keys: types.CryptoKey | types.CryptoKeyPair) => void; +} + +export interface IImportKeyParams { + format: types.KeyFormat; + data: types.JsonWebKey | types.BufferSource; + algorithm: types.AlgorithmIdentifier; + extractable: boolean; + keyUsages: types.KeyUsage[]; + assert?: (keys: types.CryptoKey) => void; +} + +export interface IImportKeyPairParams { + privateKey: IImportKeyParams; + publicKey: IImportKeyParams; +} + +export interface ITestEncryptAction extends ITestAction { + algorithm: types.Algorithm; + data: types.BufferSource; + encData: types.BufferSource; + key: IImportKeyParams | IImportKeyPairParams; +} + +export interface ITestSignAction extends ITestAction { + algorithm: types.Algorithm; + data: types.BufferSource; + signature: types.BufferSource; + key: IImportKeyParams | IImportKeyPairParams; +} + +export interface ITestDeriveBitsAction extends ITestAction { + algorithm: types.Algorithm; + key: IImportKeyParams | IImportKeyPairParams; + data: types.BufferSource; + length: number; +} + +export interface ITestDeriveKeyAction extends ITestAction { + algorithm: types.Algorithm; + key: IImportKeyParams | IImportKeyPairParams; + derivedKeyType: types.Algorithm; + keyUsages: types.KeyUsage[]; + format: types.KeyFormat; + keyData: types.BufferSource | types.JsonWebKey; + assert?: (keys: types.CryptoKey) => void; +} + +export interface ITestWrapKeyAction extends ITestAction { + key: IImportKeyParams | IImportKeyPairParams; + algorithm: types.Algorithm; + wKey: IImportKeyParams; + wrappedKey?: types.BufferSource; +} + +export interface ITestImportAction extends IImportKeyParams, ITestAction { +} + +export interface ITestDigestAction extends ITestAction { + algorithm: types.AlgorithmIdentifier; + data: types.BufferSource; + hash: types.BufferSource; +} + +export interface ITestActions { + generateKey?: ITestGenerateKeyAction[]; + encrypt?: ITestEncryptAction[]; + wrapKey?: ITestWrapKeyAction[]; + sign?: ITestSignAction[]; + import?: ITestImportAction[]; + deriveBits?: ITestDeriveBitsAction[]; + deriveKey?: ITestDeriveKeyAction[]; + digest?: ITestDigestAction[]; +} + +export interface ITestParams { + name: string; + only?: boolean; + actions: ITestActions; +} diff --git a/packages/test/src/vectors/aes/aes_cbc.ts b/packages/test/src/vectors/aes/aes_cbc.ts new file mode 100644 index 0000000..fe94821 --- /dev/null +++ b/packages/test/src/vectors/aes/aes_cbc.ts @@ -0,0 +1,197 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams } from "../../types"; + +export const AES128CBC: ITestParams = { + name: "AES-128-CBC", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CBC", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CBC", + iv: Buffer.from("1234567890abcdef"), + } as types.AesCbcParams, + data: Buffer.from("test message"), + encData: Buffer.from("d5df3ea1598defe7446420802baef28e", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: { name: "AES-CBC" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw" as types.KeyFormat, + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "wrong key size", + error: Error, + format: "raw" as types.KeyFormat, + data: Buffer.from("12345678"), + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk" as types.KeyFormat, + data: { + kty: "oct", + alg: "A128CBC", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + wrapKey: [ + { + key: { + format: "raw", + algorithm: "AES-CBC", + data: Convert.FromBase64("AQIDBAUGBwgJAAECAwQFBg=="), + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + wKey: { + format: "raw" as types.KeyFormat, + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + algorithm: { + name: "AES-CBC", + iv: Buffer.from("1234567890abcdef"), + } as types.AesCbcParams, + wrappedKey: Convert.FromHex("c630c4bf95977db13f386cc950b18e98521d54c4fda0ba15b2884d2695638bd9"), + }, + ], + } +}; + +export const AES192CBC: ITestParams = { + name: "AES-192-CBC", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CBC", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CBC", + iv: Buffer.from("1234567890abcdef"), + } as types.AesCbcParams, + data: Buffer.from("test message"), + encData: Buffer.from("67d0b3022149829bf009ad4aff19963a", "hex"), + key: { + format: "raw" as types.KeyFormat, + data: Buffer.from("1234567890abcdef12345678"), + algorithm: { name: "AES-CBC" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw" as types.KeyFormat, + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192CBC", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; + +export const AES256CBC: ITestParams = { + name: "AES-256-CBC", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CBC", length: 256 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CBC", + iv: Buffer.from("1234567890abcdef"), + } as types.AesCbcParams, + data: Buffer.from("test message"), + encData: Buffer.from("d827c1c6aee9f0f552c62f30ddee83af", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef1234567809abcdef"), + algorithm: { name: "AES-CBC" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef1234567890abcdef"), + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A256CBC", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWY", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/aes_cmac.ts b/packages/test/src/vectors/aes/aes_cmac.ts new file mode 100644 index 0000000..f56fb7a --- /dev/null +++ b/packages/test/src/vectors/aes/aes_cmac.ts @@ -0,0 +1,113 @@ + +import * as types from "@peculiar/webcrypto-types"; +import { ITestParams } from "../../types"; + +export const AES128CMAC: ITestParams = { + name: "AES-128-CMAC", + only: true, + actions: { + generateKey: [ + { + algorithm: { name: "AES-CMAC", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + sign: [ + { + algorithm: { + name: "AES-CMAC", + length: 256, + } as types.AesCmacParams, + data: Buffer.from("test message"), + signature: Buffer.from("98038e3ad7500d11005b6789c6cf9672", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: { name: "AES-CMAC" }, + extractable: true, + keyUsages: ["sign", "verify"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A128CMAC", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["sign", "verify"], + }, + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + } +}; + +export const AES192CMAC: ITestParams = { + name: "AES-192-CMAC", + only: true, + actions: { + generateKey: [ + { + algorithm: { name: "AES-CMAC", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + sign: [ + { + algorithm: { + name: "AES-CMAC", + length: 192, + } as types.AesCmacParams, + data: Buffer.from("test message"), + signature: Buffer.from("fe5c107cbcafd8a0a47a83c7bf55f1d0", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: { name: "AES-CMAC" }, + extractable: true, + keyUsages: ["sign", "verify"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192CMAC", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["sign", "verify"], + }, + algorithm: "AES-CMAC", + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + } +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/aes_ctr.ts b/packages/test/src/vectors/aes/aes_ctr.ts new file mode 100644 index 0000000..1bb14de --- /dev/null +++ b/packages/test/src/vectors/aes/aes_ctr.ts @@ -0,0 +1,167 @@ +import * as types from "@peculiar/webcrypto-types"; +import { ITestParams } from "../../types"; + +export const AES128CTR: ITestParams = { + name: "AES-128-CTR", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CTR", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CTR", + counter: Buffer.from("1234567890abcdef"), + length: 128, + } as types.AesCtrParams, + data: Buffer.from("test message"), + encData: Buffer.from("e1d561c49ce4eb2f448f8a00", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: { name: "AES-CTR" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A128CTR", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; + +export const AES192CTR: ITestParams = { + name: "AES-192-CTR", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CTR", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CTR", + counter: Buffer.from("1234567890abcdef"), + length: 128, + } as types.AesCtrParams, + data: Buffer.from("test message"), + encData: Buffer.from("55a00e2851f00aba53bbd02c", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: { name: "AES-CTR" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192CTR", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; + +export const AES256CTR: ITestParams = { + name: "AES-256-CTR", + actions: { + generateKey: [ + { + algorithm: { name: "AES-CTR", length: 256 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-CTR", + counter: Buffer.from("1234567890abcdef"), + length: 128, + } as types.AesCtrParams, + data: Buffer.from("test message"), + encData: Buffer.from("8208d011a20162c8af7a9ce5", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef1234567809abcdef"), + algorithm: { name: "AES-CTR" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef1234567890abcdef"), + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A256CTR", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWY", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-CTR", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/aes_ecb.ts b/packages/test/src/vectors/aes/aes_ecb.ts new file mode 100644 index 0000000..c9ebee9 --- /dev/null +++ b/packages/test/src/vectors/aes/aes_ecb.ts @@ -0,0 +1,182 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams } from "../../types"; + +export const AES128ECB: ITestParams = { + name: "AES-128-ECB", + actions: { + generateKey: [ + { + algorithm: { name: "AES-ECB", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-ECB", + } as types.Algorithm, + data: Convert.FromUtf8String("test message"), + encData: Convert.FromHex("c6ec2f91a9f48e10062ae41e86cb299f"), + key: { + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef"), + algorithm: { name: "AES-ECB" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef"), + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A128ECB", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + wrapKey: [ + { + key: { + format: "raw", + algorithm: "AES-ECB", + data: Convert.FromBase64("AQIDBAUGBwgJAAECAwQFBg=="), + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + wKey: { + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef"), + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + algorithm: { + name: "AES-ECB", + } as types.Algorithm, + wrappedKey: Convert.FromHex("039ec14b350bd92efd02dac2c01cdee6ea9953cfbdc067f20f5f47bb4459da79"), + }, + ], + }, +}; +export const AES192ECB: ITestParams = { + name: "AES-192-ECB", + actions: { + generateKey: [ + { + algorithm: { name: "AES-ECB", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-ECB", + } as types.Algorithm, + data: Convert.FromUtf8String("test message"), + encData: Convert.FromHex("8c9f297827ad6aaa9e7501e79fb45ca5"), + key: { + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef12345678"), + algorithm: { name: "AES-ECB" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef12345678"), + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192ECB", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + }, +}; +export const AES256ECB: ITestParams = { + name: "AES-256-ECB", + actions: { + generateKey: [ + { + algorithm: { name: "AES-ECB", length: 256 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-ECB", + } as types.Algorithm, + data: Convert.FromUtf8String("test message"), + encData: Convert.FromHex("84ccef71a364b112eb2b3b8b99587a95"), + key: { + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef1234567809abcdef"), + algorithm: { name: "AES-ECB" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Convert.FromUtf8String("1234567890abcdef1234567890abcdef"), + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A256ECB", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWY", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-ECB", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/aes_gcm.ts b/packages/test/src/vectors/aes/aes_gcm.ts new file mode 100644 index 0000000..54640cf --- /dev/null +++ b/packages/test/src/vectors/aes/aes_gcm.ts @@ -0,0 +1,162 @@ +import * as types from "@peculiar/webcrypto-types"; +import { ITestParams } from "../../types"; + +export const AES128GCM: ITestParams = { + name: "AES-128-GCM", + actions: { + generateKey: [ + { + algorithm: { name: "AES-GCM", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-GCM", + iv: Buffer.from("1234567890ab"), + } as types.AesGcmParams, + data: Buffer.from("test message"), + encData: Buffer.from("68d645649ddf8152a253304d698185072f28cdcf7644ac6064bcb240", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: { name: "AES-GCM" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef"), + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A128GCM", + k: "MTIzNDU2Nzg5MGFiY2RlZg", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; +export const AES192GCM: ITestParams = { + name: "AES-192-GCM", + actions: { + generateKey: [ + { + algorithm: { name: "AES-GCM", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-GCM", + iv: Buffer.from("1234567890ab"), + } as types.AesGcmParams, + data: Buffer.from("test message"), + encData: Buffer.from("d8eab579ed2418f41ca9c4567226f54cb391d3ca2cb6819dace35691", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: { name: "AES-GCM" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192GCM", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; +export const AES256GCM: ITestParams = { + name: "AES-256-GCM", + actions: { + generateKey: [ + { + algorithm: { name: "AES-GCM", length: 256 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + ], + encrypt: [ + { + algorithm: { + name: "AES-GCM", + iv: Buffer.from("1234567890ab"), + } as types.AesGcmParams, + data: Buffer.from("test message"), + encData: Buffer.from("f961f2aadbe689ffce86fcaf2619ab647950afcf19e55b71b857c79d", "hex"), + key: { + format: "raw", + data: Buffer.from("1234567890abcdef1234567809abcdef"), + algorithm: { name: "AES-GCM" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef1234567890abcdef"), + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A256GCM", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWY", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "AES-GCM", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + } +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/aes_kw.ts b/packages/test/src/vectors/aes/aes_kw.ts new file mode 100644 index 0000000..788c04f --- /dev/null +++ b/packages/test/src/vectors/aes/aes_kw.ts @@ -0,0 +1,177 @@ +import * as types from "@peculiar/webcrypto-types"; +import { ITestParams } from "../../types"; + +export const AES128KW: ITestParams = { + name: "AES-128-KW", + actions: { + generateKey: [ + { + algorithm: { name: "AES-KW", length: 128 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + wrapKey: [ + { + key: { + format: "raw", + algorithm: "AES-KW", + data: Buffer.from("000102030405060708090A0B0C0D0E0F", "hex"), + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + wKey: { + format: "raw", + data: Buffer.from("00112233445566778899AABBCCDDEEFF", "hex"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + algorithm: { + name: "AES-KW", + }, + wrappedKey: Buffer.from("1FA68B0A8112B447AEF34BD8FB5A7B829D3E862371D2CFE5", "hex"), + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192KW", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["wrapKey", "unwrapKey"], + }, + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + }, +}; +export const AES192KW: ITestParams = { + name: "AES-192-KW", + actions: { + generateKey: [ + { + algorithm: { name: "AES-KW", length: 192 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + wrapKey: [ + { + key: { + format: "raw", + algorithm: "AES-KW", + data: Buffer.from("000102030405060708090A0B0C0D0E0F1011121314151617", "hex"), + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + wKey: { + format: "raw", + data: Buffer.from("00112233445566778899AABBCCDDEEFF0001020304050607", "hex"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + algorithm: { + name: "AES-KW", + }, + wrappedKey: Buffer.from("031D33264E15D33268F24EC260743EDCE1C6C7DDEE725A936BA814915C6762D2", "hex"), + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A192KW", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["wrapKey", "unwrapKey"], + }, + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + }, +}; +export const AES256KW: ITestParams = { + name: "AES-256-KW", + actions: { + generateKey: [ + { + algorithm: { name: "AES-KW", length: 256 } as types.AesKeyGenParams, + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + wrapKey: [ + { + key: { + format: "raw", + algorithm: "AES-KW", + data: Buffer.from("000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F", "hex"), + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + wKey: { + format: "raw", + data: Buffer.from("00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F", "hex"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + algorithm: { + name: "AES-KW", + }, + wrappedKey: Buffer.from("28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43BFB988B9B7A02DD21", "hex"), + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef1234567890abcdef"), + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "A256KW", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4OTBhYmNkZWY", + ext: true, + key_ops: ["wrapKey", "unwrapKey"], + }, + algorithm: "AES-KW", + extractable: true, + keyUsages: ["wrapKey", "unwrapKey"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/aes/index.ts b/packages/test/src/vectors/aes/index.ts new file mode 100644 index 0000000..5c17c04 --- /dev/null +++ b/packages/test/src/vectors/aes/index.ts @@ -0,0 +1,6 @@ +export * from "./aes_cbc"; +export * from "./aes_ctr"; +export * from "./aes_cmac"; +export * from "./aes_gcm"; +export * from "./aes_kw"; +export * from "./aes_ecb"; \ No newline at end of file diff --git a/packages/test/src/vectors/des/des_cbc.ts b/packages/test/src/vectors/des/des_cbc.ts new file mode 100644 index 0000000..d2d9298 --- /dev/null +++ b/packages/test/src/vectors/des/des_cbc.ts @@ -0,0 +1,55 @@ +import { ITestParams } from "../../types"; + +export const DESCBC: ITestParams = { + name: "DES-CBC", + actions: { + generateKey: [ + { + algorithm: { name: "DES-CBC", length: 64 } as any, + extractable: false, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + encrypt: [ + { + algorithm: { + name: "DES-CBC", + iv: Buffer.from("12345678"), + } as any, + data: Buffer.from("test message"), + encData: Buffer.from("3af3f901ff01fe0102dfbbf37d9bdb94", "hex"), + key: { + format: "raw", + algorithm: { name: "DES-CBC" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + data: Buffer.from("12345678"), + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("12345678"), + algorithm: "DES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "DES-CBC", + k: "MTIzNDU2Nzg", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "DES-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/des/des_ede3_cbc.ts b/packages/test/src/vectors/des/des_ede3_cbc.ts new file mode 100644 index 0000000..cb78bfc --- /dev/null +++ b/packages/test/src/vectors/des/des_ede3_cbc.ts @@ -0,0 +1,64 @@ +import { ITestParams } from "../../types"; + +export const DESEDE3CBC: ITestParams = { + name: "DES-EDE3-CBC", + actions: { + generateKey: [ + { + algorithm: { name: "DES-EDE3-CBC", length: 192 } as any, + extractable: false, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + encrypt: [ + { + algorithm: { + name: "DES-EDE3-CBC", + iv: Buffer.from("12345678"), + } as any, + data: Buffer.from("test message"), + encData: Buffer.from("b9ef20e7db926490e4ff8680d99d2141", "hex"), + key: { + format: "raw", + algorithm: { name: "DES-EDE3-CBC" }, + extractable: true, + keyUsages: ["encrypt", "decrypt"], + data: Buffer.from("1234567890abcdef12345678"), + }, + }, + ], + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("1234567890abcdef12345678"), + algorithm: "DES-EDE3-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "wrong key size", + error: Error, + format: "raw", + data: Buffer.from("12345678"), + algorithm: "DES-EDE3-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + { + name: "jwk", + format: "jwk", + data: { + kty: "oct", + alg: "3DES-CBC", + k: "MTIzNDU2Nzg5MGFiY2RlZjEyMzQ1Njc4", + ext: true, + key_ops: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + algorithm: "DES-EDE3-CBC", + extractable: true, + keyUsages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/des/index.ts b/packages/test/src/vectors/des/index.ts new file mode 100644 index 0000000..9e229d3 --- /dev/null +++ b/packages/test/src/vectors/des/index.ts @@ -0,0 +1,2 @@ +export * from "./des_cbc"; +export * from "./des_ede3_cbc"; \ No newline at end of file diff --git a/packages/test/src/vectors/ec/ecdh.ts b/packages/test/src/vectors/ec/ecdh.ts new file mode 100644 index 0000000..bdba916 --- /dev/null +++ b/packages/test/src/vectors/ec/ecdh.ts @@ -0,0 +1,469 @@ +import * as webcryptoTypes from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestGenerateKeyAction, ITestParams } from "../../types"; + +export const ECDH: ITestParams = { + name: "ECDH", + actions: { + generateKey: ["P-256", "P-384", "P-521", "K-256"].map((namedCurve) => { + return { + name: namedCurve, + algorithm: { + name: "ECDH", + namedCurve, + } as webcryptoTypes.EcKeyGenParams, + extractable: false, + keyUsages: ["deriveKey", "deriveBits"], + } as ITestGenerateKeyAction; + }), + import: [ + { + name: "JWK public key P-256", + format: "jwk", + data: { + crv: "P-256", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "dJ9C3NyXDa3fMeZ477NWdp9W6faytA7A_U1ub-tyRcs", + y: "aS0_VVe_SeIm8w5TBWjUEco7us6EJUMPKKJaIh36Lho", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "JWK public key P-384", + format: "jwk", + data: { + crv: "P-384", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "eHlLZ4jnt_Drs-qoVxK-SZZvhNhi34jLCgyaEZ9XI6bdlK3y1ettm8K5SnLtDhWO", + y: "qbr3pOOViYDQ2wWG-_9pwQ0S8cHV0LP-x9JO5dl-dsFYtbGix9YH7fRNOl8GkP-6", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "JWK public key P-521", + format: "jwk", + data: { + crv: "P-521", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "Adqn62IVQX8LIauAXrUtxH05DHlRygKcsP9qWAnd9tfJvpaG7bzIs16WMEUe1V-f4AxbQJceU4xCP8dJppK_fzdC", + y: "AEo3s1eExCOvpuBtBWnWlr7TuFhq_fMzqX9eqDHiy8qWl4I_koQtMePodrAc85mVrJAjvsa77Y3Ul3QtIWpXXBqa", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#region SPKI + { + name: "SPKI P-256", + format: "spki", + data: Convert.FromBase64("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoZMMqyfA16N6bvloFHmalk/SGMisr3zSXFZdR8F9UkaY7hF13hHiQtwp2YO+1zd7jwYi1Y7SMA9iUrC+ap2OCw=="), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "SPKI P-384", + format: "spki", + data: Convert.FromBase64("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8Kf5Wv21nksy0LuMlkMZv9sxTVAmzNWt81b6MVlYuzxl9D2/obwoVp86pTe4BM79gWWj8pfLc1XrjaIyMSrV8+05IejRLB3i4c0KTGA6QARGm3/AOm0MbTt6kMQF7drL"), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "SPKI P-521", + format: "spki", + data: Convert.FromBase64("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB+/g37ii0T5iLHCAaXcYRRoNpT0LhfeAr88OwQY4cUpQm1S9lkR0EVUtyuYrYsMB8FarhAZYsLtOiyhjl/Y5f+lQAZ6veWILhbDcbrSNhTPSp3wamAm8QT3EjPUkJlYjHefuAUBIYS9pl5FWjK1pI9fkYe3bdAemkjP1ccHVzqZU9sjg="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#endregion + //#region RAW + { + name: "RAW P-256", + format: "raw", + data: Convert.FromBase64("BEehen4AavxgJkx5EPZpBeopzgZuY+1i3cMR9iYdZj+IY7/h98Q/GboC2BKS6lT0hEyt6y1DFFXj8ytuof4zXR4="), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "RAW P-384", + format: "raw", + data: Convert.FromBase64("BGYoCpP3Qv4o0s2GWg5xFnasdkI8h6K/LeBm4TV+9HCsqnoXFUJDM5SDeZ0rcCAUUuaPJVn5sedPEKEGW80zmLM1rBOG2RzaBq+uhEJkLpibongnzMZNX2LB58wGJ05f2g=="), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "RAW P-521", + format: "raw", + data: Convert.FromBase64("BABIiZ3f90HQsl4CYHt7Q1WnOIOs+dxeecfQrew/z+73yI/bUrMlmR3mOVARtvg7ZPX7h3lSSqzA1Vv6iv7bPYekcwDKQPeLJkem//H7zY8xtKY+YrYnLUVv6vPE9jyk2vYkj8QPxQRdeIT5bzY2BzTiTcLHDwi2+w2Eonkt7M+zb4G6xw=="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#endregion + //#region JWK Private key + { + name: "JWK private key P-256", + format: "jwk", + data: { + crv: "P-256", + d: "RIrfLaesGcEeNy7fOoVIkgMiImJOFw1Y44kdrtK_49I", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "wJls5KwIfRDxJEvyAlo3G84qNY0HjvsujyxDSMYAlm4", + y: "I61bQbFgnzfDom68P86kRo98fTrV_9HLeqa4gYnGOdw", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "JWK private key P-384", + format: "jwk", + data: { + crv: "P-384", + d: "4YQRcOD-4LMLEr-qsRhQ1oq8hfPKa66BfGVUv3LUlsf2OU3aFG5FxabG5xFUoAE2", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "XKewC5QCVW9w-SFyZd3z1vlmCqbYYuJmoGRzKtjwkpYQD_RhNAc3ck29d_t0QmaT", + y: "6oSrri3ry1_8c2NKM8aiaJcjwd146ITViezQ7-BpsE1-wDH18P1QkbmR3-Ho54We", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "JWK private key P-521", + format: "jwk", + data: { + crv: "P-521", + d: "AItxxufCXVzwPVePNe9Acy8HfbmYeUVkiEyFXdsYRnHxqgDpwucVnIJ44-ZWRpuWu5Ep5KVV3vY9Hp8nJfksi7z2", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "AJGuTezC-8F-d_0bBpS502OK0z63vo87Dw99a3NUm6gm5pQC1rwu7LcblGqFWOuFBZhsF8I6OFjYvsR-z3u7hhCA", + y: "AFQT8BB9hBf7UwwBUV4im8bFJ7_MD0qOZMVetmdbooMjfec1q3wU5cSoy4LvCnWAaFqu5havUxwnAUuPUWGG_InR", + }, + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + //#endregion + //#region PKCS8 + { + name: "PKCS8 P-256", + format: "pkcs8", + data: Convert.FromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiVEY5OFo3J7g1BnSw/WEWykY/alrhNmpEBLy/7cNnuGhRANCAAQ4SFnMDGYc5kWv7D0gtgUj/Bzbu0B6Bq6XK1vqOo//2m8FS1D4kYKV4KDfFRWehKEtrMBjjkW6OZcM/n0qZ6Uw"), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "PKCS8 P-384", + format: "pkcs8", + data: Convert.FromBase64("MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCY18ajGPCgLv4aF1UkkohMEaB5MU1MyfkuFQSQVDYHLWFTn8f9czce7aTIDjkCx0OhZANiAAR1fni8TC1N1NdXvx25kJyK3y3rpVVaAmA44Wm9jIFseGmSzm/EgmKOFclSzQdEpSC6jxi3olIJ4iYetjl36Ygfwed/xqrsiV6BUb/ny2mimzk3r0M9H6yvbEVQFd7rEAA="), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "PKCS8 P-521", + format: "pkcs8", + data: Convert.FromBase64("MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAbHGkGfik5q0l+ZMI70dbpTGWeKy1+c3mG98wHmnpU+d2bArcYDOXcoqg5Ic/pnmtHvxmk+El33u3XogGONKPlouhgYkDgYYABAH16CoJzEx+Oncpeam6ysUG17y9ttNm5Eg8WqD+BJkP9ju3R22I5PVyYYYZ3ICc1IyDGxFCS7leO1N7tqQLaLi8NAEFTkwCy1G6AAK7LbSa1hNC2fUAaC9L8QJNUNJpjgYiXPDmEnaRNT1XXL00Bjo5iMpE2Ddc/Kp6ktTAo2jOMnfmow=="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + //#endregion + ], + deriveBits: [ + { + name: "P-256 128", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgQA7bkTNYlIYVb9+DavBlJ3b08f0892or3XwfscA3tLGhRANCAARzsy+ZcbrNchF7SrpL0hYnGp6ICX77jXUrpMYkq0BuzfaPFWcu9YZH5ASUzQJGz9eCK3mDXEbLCuiHRw3dwkFs"), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveBits"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7MvmXG6zXIRe0q6S9IWJxqeiAl++411K6TGJKtAbs32jxVnLvWGR+QElM0CRs/Xgit5g1xGywroh0cN3cJBbA=="), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + data: Convert.FromBase64("Jlc1/Zqi/8mH1oQT8+YfCA=="), + algorithm: { + name: "ECDH", + }, + length: 128, + }, + { + name: "P-384 192", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAFOXcWxQ+YqPdUqc9Iar3ZDf012ZtQAFajBMApKpd2WPQccBmyPzvDZJSWKe3d5jShZANiAAQ4Z43bP7d5fUFIBorLA1pBFTwDLb6XA7J871VUwyu64q8L5qidV7iBZK3P+9m7eMMQWm0drWPvrEszE+4jEsS4HIbBeuduBU+6R46Orv+V6VXU1hAXKSdMFZOCzdbDFlE="), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveBits"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEOGeN2z+3eX1BSAaKywNaQRU8Ay2+lwOyfO9VVMMruuKvC+aonVe4gWStz/vZu3jDEFptHa1j76xLMxPuIxLEuByGwXrnbgVPukeOjq7/lelV1NYQFyknTBWTgs3WwxZR"), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + data: Convert.FromBase64("2EKT/nmV68wIXFMZiCv4CyOEhWzpwdQ5"), + algorithm: { + name: "ECDH", + }, + length: 192, + }, + { + name: "P-521 256", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB6PyCXpJ4TWPpwlGAmayLz5ecYHT+1ilxD64HytpTaViUS72sEzG1JMApD31+STX0zeVcARfG+yh71dXLCTlqqHGhgYkDgYYABADgIblBbth8vnOZt/HLU9VdUJHmenwRRADVZWL+P5IeCDQs6B87API41R3+91xFDHnjst9VKksYl/NJIIfl6b9cmABO6z80mTz3+0klquIpSQLidK2aFaFbqiGnMdCO+AZfwxu2qBx+1f5MwbHXUW5HXsfmEvzBUC9xCQKLpQ8oZYBrSg=="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveBits"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQA4CG5QW7YfL5zmbfxy1PVXVCR5np8EUQA1WVi/j+SHgg0LOgfOwDyONUd/vdcRQx547LfVSpLGJfzSSCH5em/XJgATus/NJk89/tJJariKUkC4nStmhWhW6ohpzHQjvgGX8MbtqgcftX+TMGx11FuR17H5hL8wVAvcQkCi6UPKGWAa0o="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + data: Convert.FromBase64("AS2ene28pmWYdJwW6dyTXUe1eq1p2i8QEIo/rXSiJRo="), + algorithm: { + name: "ECDH", + }, + length: 256, + }, + { + name: "K-256 128", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQghgLhhrz/EYuB0G08/UoM5nV9jS7Pl/rtIcXeJkc2b3uhRANCAARgMfEiAPcF7pmEuLRGRRFXEKSwcJwqURKK/Pqo8MaqU0cl7eNQmLJ7mFpBtTDY8hr9xxJeIP9sI/u83A1F5ag7"), + algorithm: { + name: "ECDH", + namedCurve: "K-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveBits"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEYDHxIgD3Be6ZhLi0RkURVxCksHCcKlESivz6qPDGqlNHJe3jUJiye5haQbUw2PIa/ccSXiD/bCP7vNwNReWoOw=="), + algorithm: { + name: "ECDH", + namedCurve: "K-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + data: Convert.FromBase64("3+2JX3D4/veBGJXnvU+aTg=="), + algorithm: { + name: "ECDH", + }, + length: 128, + }, + ], + deriveKey: [ + { + name: "P-256 128", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgQA7bkTNYlIYVb9+DavBlJ3b08f0892or3XwfscA3tLGhRANCAARzsy+ZcbrNchF7SrpL0hYnGp6ICX77jXUrpMYkq0BuzfaPFWcu9YZH5ASUzQJGz9eCK3mDXEbLCuiHRw3dwkFs"), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveKey"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEc7MvmXG6zXIRe0q6S9IWJxqeiAl++411K6TGJKtAbs32jxVnLvWGR+QElM0CRs/Xgit5g1xGywroh0cN3cJBbA=="), + algorithm: { + name: "ECDH", + namedCurve: "P-256", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + algorithm: { + name: "ECDH", + }, + derivedKeyType: { + name: "AES-CBC", + length: 128, + } as webcryptoTypes.AesKeyAlgorithm, + keyUsages: ["encrypt", "decrypt"], + format: "raw", + keyData: Convert.FromBase64("Jlc1/Zqi/8mH1oQT8+YfCA=="), + }, + { + name: "P-384 192", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDAFOXcWxQ+YqPdUqc9Iar3ZDf012ZtQAFajBMApKpd2WPQccBmyPzvDZJSWKe3d5jShZANiAAQ4Z43bP7d5fUFIBorLA1pBFTwDLb6XA7J871VUwyu64q8L5qidV7iBZK3P+9m7eMMQWm0drWPvrEszE+4jEsS4HIbBeuduBU+6R46Orv+V6VXU1hAXKSdMFZOCzdbDFlE="), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveKey"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEOGeN2z+3eX1BSAaKywNaQRU8Ay2+lwOyfO9VVMMruuKvC+aonVe4gWStz/vZu3jDEFptHa1j76xLMxPuIxLEuByGwXrnbgVPukeOjq7/lelV1NYQFyknTBWTgs3WwxZR"), + algorithm: { + name: "ECDH", + namedCurve: "P-384", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + algorithm: { + name: "ECDH", + }, + derivedKeyType: { + name: "AES-GCM", + length: 192, + } as webcryptoTypes.AesKeyAlgorithm, + keyUsages: ["encrypt", "decrypt"], + format: "raw", + keyData: Convert.FromBase64("2EKT/nmV68wIXFMZiCv4CyOEhWzpwdQ5"), + }, + { + name: "P-521 256", + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIB6PyCXpJ4TWPpwlGAmayLz5ecYHT+1ilxD64HytpTaViUS72sEzG1JMApD31+STX0zeVcARfG+yh71dXLCTlqqHGhgYkDgYYABADgIblBbth8vnOZt/HLU9VdUJHmenwRRADVZWL+P5IeCDQs6B87API41R3+91xFDHnjst9VKksYl/NJIIfl6b9cmABO6z80mTz3+0klquIpSQLidK2aFaFbqiGnMdCO+AZfwxu2qBx+1f5MwbHXUW5HXsfmEvzBUC9xCQKLpQ8oZYBrSg=="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: ["deriveKey"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQA4CG5QW7YfL5zmbfxy1PVXVCR5np8EUQA1WVi/j+SHgg0LOgfOwDyONUd/vdcRQx547LfVSpLGJfzSSCH5em/XJgATus/NJk89/tJJariKUkC4nStmhWhW6ohpzHQjvgGX8MbtqgcftX+TMGx11FuR17H5hL8wVAvcQkCi6UPKGWAa0o="), + algorithm: { + name: "ECDH", + namedCurve: "P-521", + } as webcryptoTypes.EcKeyImportParams, + extractable: true, + keyUsages: [], + }, + }, + algorithm: { + name: "ECDH", + }, + derivedKeyType: { + name: "AES-CTR", + length: 256, + } as webcryptoTypes.AesKeyAlgorithm, + keyUsages: ["encrypt", "decrypt"], + format: "raw", + keyData: Convert.FromBase64("AS2ene28pmWYdJwW6dyTXUe1eq1p2i8QEIo/rXSiJRo="), + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/ec/ecdsa.ts b/packages/test/src/vectors/ec/ecdsa.ts new file mode 100644 index 0000000..a1ef073 --- /dev/null +++ b/packages/test/src/vectors/ec/ecdsa.ts @@ -0,0 +1,302 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestGenerateKeyAction, ITestParams } from "../../types"; + +export const ECDSA: ITestParams = { + name: "ECDSA", + actions: { + generateKey: ["P-256", "P-384", "P-521", "K-256"].map((namedCurve) => { + return { + name: namedCurve, + algorithm: { + name: "ECDSA", + namedCurve, + } as types.EcKeyGenParams, + extractable: false, + keyUsages: ["sign", "verify"], + } as ITestGenerateKeyAction; + }), + import: [ + { + name: "JWK public key P-256", + format: "jwk", + data: { + crv: "P-256", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "dJ9C3NyXDa3fMeZ477NWdp9W6faytA7A_U1ub-tyRcs", + y: "aS0_VVe_SeIm8w5TBWjUEco7us6EJUMPKKJaIh36Lho", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "JWK public key P-384", + format: "jwk", + data: { + crv: "P-384", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "eHlLZ4jnt_Drs-qoVxK-SZZvhNhi34jLCgyaEZ9XI6bdlK3y1ettm8K5SnLtDhWO", + y: "qbr3pOOViYDQ2wWG-_9pwQ0S8cHV0LP-x9JO5dl-dsFYtbGix9YH7fRNOl8GkP-6", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-384", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "JWK public key P-521", + format: "jwk", + data: { + crv: "P-521", + ext: true, + key_ops: ["verify"], + kty: "EC", + x: "Adqn62IVQX8LIauAXrUtxH05DHlRygKcsP9qWAnd9tfJvpaG7bzIs16WMEUe1V-f4AxbQJceU4xCP8dJppK_fzdC", + y: "AEo3s1eExCOvpuBtBWnWlr7TuFhq_fMzqX9eqDHiy8qWl4I_koQtMePodrAc85mVrJAjvsa77Y3Ul3QtIWpXXBqa", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-521", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#region SPKI + { + name: "SPKI P-256", + format: "spki", + data: Convert.FromBase64("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEoZMMqyfA16N6bvloFHmalk/SGMisr3zSXFZdR8F9UkaY7hF13hHiQtwp2YO+1zd7jwYi1Y7SMA9iUrC+ap2OCw=="), + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "SPKI P-384", + format: "spki", + data: Convert.FromBase64("MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE8Kf5Wv21nksy0LuMlkMZv9sxTVAmzNWt81b6MVlYuzxl9D2/obwoVp86pTe4BM79gWWj8pfLc1XrjaIyMSrV8+05IejRLB3i4c0KTGA6QARGm3/AOm0MbTt6kMQF7drL"), + algorithm: { + name: "ECDSA", + namedCurve: "P-384", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "SPKI P-521", + format: "spki", + data: Convert.FromBase64("MIGbMBAGByqGSM49AgEGBSuBBAAjA4GGAAQB+/g37ii0T5iLHCAaXcYRRoNpT0LhfeAr88OwQY4cUpQm1S9lkR0EVUtyuYrYsMB8FarhAZYsLtOiyhjl/Y5f+lQAZ6veWILhbDcbrSNhTPSp3wamAm8QT3EjPUkJlYjHefuAUBIYS9pl5FWjK1pI9fkYe3bdAemkjP1ccHVzqZU9sjg="), + algorithm: { + name: "ECDSA", + namedCurve: "P-521", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#endregion + //#region RAW + { + name: "RAW P-256", + format: "raw", + data: Convert.FromBase64("BEehen4AavxgJkx5EPZpBeopzgZuY+1i3cMR9iYdZj+IY7/h98Q/GboC2BKS6lT0hEyt6y1DFFXj8ytuof4zXR4="), + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "RAW P-384", + format: "raw", + data: Convert.FromBase64("BGYoCpP3Qv4o0s2GWg5xFnasdkI8h6K/LeBm4TV+9HCsqnoXFUJDM5SDeZ0rcCAUUuaPJVn5sedPEKEGW80zmLM1rBOG2RzaBq+uhEJkLpibongnzMZNX2LB58wGJ05f2g=="), + algorithm: { + name: "ECDSA", + namedCurve: "P-384", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "RAW P-521", + format: "raw", + data: Convert.FromBase64("BABIiZ3f90HQsl4CYHt7Q1WnOIOs+dxeecfQrew/z+73yI/bUrMlmR3mOVARtvg7ZPX7h3lSSqzA1Vv6iv7bPYekcwDKQPeLJkem//H7zY8xtKY+YrYnLUVv6vPE9jyk2vYkj8QPxQRdeIT5bzY2BzTiTcLHDwi2+w2Eonkt7M+zb4G6xw=="), + algorithm: { + name: "ECDSA", + namedCurve: "P-521", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + //#endregion + //#region JWK Private key + { + name: "JWK private key P-256", + format: "jwk", + data: { + crv: "P-256", + d: "RIrfLaesGcEeNy7fOoVIkgMiImJOFw1Y44kdrtK_49I", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "wJls5KwIfRDxJEvyAlo3G84qNY0HjvsujyxDSMYAlm4", + y: "I61bQbFgnzfDom68P86kRo98fTrV_9HLeqa4gYnGOdw", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "JWK private key P-384", + format: "jwk", + data: { + crv: "P-384", + d: "4YQRcOD-4LMLEr-qsRhQ1oq8hfPKa66BfGVUv3LUlsf2OU3aFG5FxabG5xFUoAE2", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "XKewC5QCVW9w-SFyZd3z1vlmCqbYYuJmoGRzKtjwkpYQD_RhNAc3ck29d_t0QmaT", + y: "6oSrri3ry1_8c2NKM8aiaJcjwd146ITViezQ7-BpsE1-wDH18P1QkbmR3-Ho54We", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-384", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "JWK private key P-521", + format: "jwk", + data: { + crv: "P-521", + d: "AItxxufCXVzwPVePNe9Acy8HfbmYeUVkiEyFXdsYRnHxqgDpwucVnIJ44-ZWRpuWu5Ep5KVV3vY9Hp8nJfksi7z2", + ext: true, + key_ops: ["sign"], + kty: "EC", + x: "AJGuTezC-8F-d_0bBpS502OK0z63vo87Dw99a3NUm6gm5pQC1rwu7LcblGqFWOuFBZhsF8I6OFjYvsR-z3u7hhCA", + y: "AFQT8BB9hBf7UwwBUV4im8bFJ7_MD0qOZMVetmdbooMjfec1q3wU5cSoy4LvCnWAaFqu5havUxwnAUuPUWGG_InR", + }, + algorithm: { + name: "ECDSA", + namedCurve: "P-521", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + //#endregion + //#region PKCS8 + { + name: "PKCS8 P-256", + format: "pkcs8", + data: Convert.FromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiVEY5OFo3J7g1BnSw/WEWykY/alrhNmpEBLy/7cNnuGhRANCAAQ4SFnMDGYc5kWv7D0gtgUj/Bzbu0B6Bq6XK1vqOo//2m8FS1D4kYKV4KDfFRWehKEtrMBjjkW6OZcM/n0qZ6Uw"), + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "PKCS8 P-384", + format: "pkcs8", + data: Convert.FromBase64("MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCY18ajGPCgLv4aF1UkkohMEaB5MU1MyfkuFQSQVDYHLWFTn8f9czce7aTIDjkCx0OhZANiAAR1fni8TC1N1NdXvx25kJyK3y3rpVVaAmA44Wm9jIFseGmSzm/EgmKOFclSzQdEpSC6jxi3olIJ4iYetjl36Ygfwed/xqrsiV6BUb/ny2mimzk3r0M9H6yvbEVQFd7rEAA="), + algorithm: { + name: "ECDSA", + namedCurve: "P-384", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "PKCS8 P-521", + format: "pkcs8", + data: Convert.FromBase64("MIHuAgEAMBAGByqGSM49AgEGBSuBBAAjBIHWMIHTAgEBBEIAbHGkGfik5q0l+ZMI70dbpTGWeKy1+c3mG98wHmnpU+d2bArcYDOXcoqg5Ic/pnmtHvxmk+El33u3XogGONKPlouhgYkDgYYABAH16CoJzEx+Oncpeam6ysUG17y9ttNm5Eg8WqD+BJkP9ju3R22I5PVyYYYZ3ICc1IyDGxFCS7leO1N7tqQLaLi8NAEFTkwCy1G6AAK7LbSa1hNC2fUAaC9L8QJNUNJpjgYiXPDmEnaRNT1XXL00Bjo5iMpE2Ddc/Kp6ktTAo2jOMnfmow=="), + algorithm: { + name: "ECDSA", + namedCurve: "P-521", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + //#endregion + ], + sign: [ + { + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgsY5TBHM+9mLXGpFaPmrigl6+jl0XWzazxu1lbwb5KRahRANCAATqDP2L/xxSOlckG+j6oPHfzBE4WpmjA/YE9sP2rXpXW1qe9I/GJ7wjlOTXpqHUxQeBbps8jSvV+A7DzQqzjOst"), + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE6gz9i/8cUjpXJBvo+qDx38wROFqZowP2BPbD9q16V1tanvSPxie8I5Tk16ah1MUHgW6bPI0r1fgOw80Ks4zrLQ=="), + algorithm: { + name: "ECDSA", + namedCurve: "P-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + }, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + signature: Convert.FromBase64("gsTh0IcWfzj3hjjourRgzTIsNa+wcDEDlKnkEA4Jv8ygLF2IDIOXpCD7ocCGo7xlSMGTme78CyrPqWGSz95mZg=="), + algorithm: { + name: "ECDSA", + hash: "SHA-256", + } as types.EcdsaParams, + }, + { + key: { + privateKey: { + format: "pkcs8", + data: Convert.FromBase64("MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQg0h6+W+/4eFVP+i79hrzYeiEJ6UrveFYhuhoXRW+g/LGhRANCAASiJU6MaFN5fshUv6X5rCf/RjLQ0nAXj06gBdo3ruYiKZf8daAcYImniAq81PjF0j6eTwCy4bYbkyfBQtrtCTKR"), + algorithm: { + name: "ECDSA", + namedCurve: "K-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["sign"], + }, + publicKey: { + format: "spki", + data: Convert.FromBase64("MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEoiVOjGhTeX7IVL+l+awn/0Yy0NJwF49OoAXaN67mIimX/HWgHGCJp4gKvNT4xdI+nk8AsuG2G5MnwULa7QkykQ=="), + algorithm: { + name: "ECDSA", + namedCurve: "K-256", + } as types.EcKeyImportParams, + extractable: true, + keyUsages: ["verify"], + }, + }, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + signature: Convert.FromBase64("lqUTZHqf9v9KcOCw5r5wR1sCt9RPA0ONVW6vqejpoALehd6vtAb+ybVrDEtyUDpBFw9UIRIW6GnXRrAz4KaO4Q=="), + algorithm: { + name: "ECDSA", + hash: "SHA-256", + } as types.EcdsaParams, + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/ec/index.ts b/packages/test/src/vectors/ec/index.ts new file mode 100644 index 0000000..3911257 --- /dev/null +++ b/packages/test/src/vectors/ec/index.ts @@ -0,0 +1,2 @@ +export * from "./ecdh"; +export * from "./ecdsa"; \ No newline at end of file diff --git a/packages/test/src/vectors/hkdf.ts b/packages/test/src/vectors/hkdf.ts new file mode 100644 index 0000000..4e5793a --- /dev/null +++ b/packages/test/src/vectors/hkdf.ts @@ -0,0 +1,79 @@ +import * as types from "@peculiar/webcrypto-types"; +import { ITestParams } from "../types"; + +export const HKDF: ITestParams = { + name: "HKDF", + actions: { + import: [ + { + name: "raw", + format: "raw", + data: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + algorithm: { + name: "HKDF", + }, + extractable: false, + keyUsages: ["deriveBits", "deriveKey"], + }, + ], + deriveBits: [ + { + key: { + format: "raw", + data: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + algorithm: { + name: "HKDF", + }, + extractable: false, + keyUsages: ["deriveBits"], + }, + algorithm: { + name: "HKDF", + hash: { name: "SHA-256" }, + salt: Buffer.from("000102030405060708090a0b0c", "hex"), + info: Buffer.from("f0f1f2f3f4f5f6f7f8f9", "hex"), + } as types.HkdfParams, + data: Buffer.from("3cb25f25faacd57a90434f64d0362f2a2d2d0a90cf1a5a4c5db02d56ecc4c5bf34007208d5b887185865", "hex"), + length: 42 * 8, + }, + { + key: { + format: "raw", + data: Buffer.from("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f", "hex"), + algorithm: { + name: "HKDF", + }, + extractable: false, + keyUsages: ["deriveBits"], + }, + algorithm: { + name: "HKDF", + hash: "SHA-256", + salt: Buffer.from("606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "hex"), + info: Buffer.from("b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "hex"), + } as types.HkdfParams, + data: Buffer.from("b11e398dc80327a1c8e7f78c596a49344f012eda2d4efad8a050cc4c19afa97c59045a99cac7827271cb41c65e590e09da3275600c2f09b8367793a9aca3db71cc30c58179ec3e87c14c01d5c1f3434f1d87", "hex"), + length: 82 * 8, + }, + { + key: { + format: "raw", + data: Buffer.from("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "hex"), + algorithm: { + name: "HKDF", + }, + extractable: false, + keyUsages: ["deriveBits"], + }, + algorithm: { + name: "HKDF", + hash: "SHA-256", + salt: Buffer.from([]), + info: Buffer.from([]), + } as types.HkdfParams, + data: Buffer.from("8da4e775a563c18f715f802a063c5a31b8a11f5c5ee1879ec3454e5f3c738d2d9d201395faa4b61a96c8", "hex"), + length: 42 * 8, + }, + ], + } +}; \ No newline at end of file diff --git a/packages/test/src/vectors/hmac.ts b/packages/test/src/vectors/hmac.ts new file mode 100644 index 0000000..04f7ef0 --- /dev/null +++ b/packages/test/src/vectors/hmac.ts @@ -0,0 +1,171 @@ +import * as types from "@peculiar/webcrypto-types"; +import * as assert from "assert"; +import { Convert } from "pvtsutils"; +import { ITestParams, ITestGenerateKeyAction } from "../types"; + +export const HMAC: ITestParams = { + name: "HMAC", + actions: { + generateKey: [ + ...["SHA-1", "SHA-256", "SHA-384", "SHA-512"].map((hash) => { + return { + name: `default length for ${hash} algorithm`, + algorithm: { + name: "HMAC", + hash, + } as types.HmacKeyGenParams, + extractable: true, + keyUsages: ["sign", "verify"], + assert: (key: types.CryptoKey) => { + const algorithm = key.algorithm as types.HmacKeyAlgorithm; + // Chrome, Safari and Firefox return key with algorithm length 512 bits + assert.equal(algorithm.length, 512); + }, + } as ITestGenerateKeyAction; + }), + ...["SHA-1", "SHA-256", "SHA-384", "SHA-512"].map((hash) => { + return { + name: `Fixed length:160 for ${hash}`, + algorithm: { + name: "HMAC", + hash, + length: 160, + }, + extractable: true, + keyUsages: ["sign", "verify"], + assert: (key: types.CryptoKey) => { + const algorithm = key.algorithm as types.HmacKeyAlgorithm; + assert.equal(algorithm.length, 160); + } + } as ITestGenerateKeyAction; + }), + ...["SHA-1"].map((hash) => { + return { + name: `Round length 164->160`, + algorithm: { + name: "HMAC", + hash, + length: 164, + }, + extractable: true, + keyUsages: ["sign", "verify"], + assert: (key: types.CryptoKey) => { + const algorithm = key.algorithm as types.HmacKeyAlgorithm; + assert.equal(algorithm.length, 160); + } + } as ITestGenerateKeyAction; + }), + ], + sign: [ + { + name: "HMAC-SHA256 without length param", + key: { + format: "raw", + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6]), + algorithm: { + name: "HMAC", + hash: "SHA-256", + } as types.HmacImportParams, + extractable: false, + keyUsages: ["sign", "verify"], + }, + algorithm: { name: "HMAC" }, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + signature: Convert.FromHex("ad05febab44cd369e27433bbf00e63e6271f6a350614bec453f5d0efd6503a31"), + }, + ], + import: [ + { // JWK SHA-1 + name: "JWK SHA-1", + format: "jwk", + data: { + alg: "HS1", + ext: true, + k: "AQIDBAUGBwgJAAECAwQFBg", + key_ops: ["sign", "verify"], + kty: "oct", + }, + algorithm: { + name: "HMAC", + hash: "SHA-1", + length: 128, + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + { // JWK SHA-256 + name: "JWK SHA-256", + format: "jwk", + data: { + alg: "HS256", + ext: true, + k: "AQIDBAUGBwgJAAECAwQFBg", + key_ops: ["sign", "verify"], + kty: "oct", + }, + algorithm: { + name: "HMAC", + hash: "SHA-256", + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + { // JWK SHA-384 + name: "JWK SHA-384", + format: "jwk", + data: { + alg: "HS384", + ext: true, + k: "AQIDBAUGBwgJAAECAwQFBg", + key_ops: ["sign", "verify"], + kty: "oct", + }, + algorithm: { + name: "HMAC", + hash: "SHA-384", + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + { // JWK SHA-512 + name: "JWK SHA-512", + format: "jwk", + data: { + alg: "HS512", + ext: true, + k: "AQIDBAUGBwgJAAECAwQFBg", + key_ops: ["sign", "verify"], + kty: "oct", + }, + algorithm: { + name: "HMAC", + hash: "SHA-512", + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + { // raw 128 + name: "raw 128", + format: "raw", + data: Convert.FromBase64("AQIDBAUGBwgJAAECAwQFBg=="), + algorithm: { + name: "HMAC", + hash: "SHA-512", + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + { // raw 160 + name: "raw 160", + format: "raw", + data: new Uint8Array(20), + algorithm: { + name: "HMAC", + hash: "SHA-512", + } as types.HmacImportParams, + extractable: true, + keyUsages: ["sign", "verify"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/index.ts b/packages/test/src/vectors/index.ts new file mode 100644 index 0000000..173e7d4 --- /dev/null +++ b/packages/test/src/vectors/index.ts @@ -0,0 +1,9 @@ +export * from "./aes"; +export * from "./rsa"; +export * from "./des"; +export * from "./ec"; + +export * from "./hkdf"; +export * from "./pbkdf2"; +export * from "./hmac"; +export * from "./sha"; \ No newline at end of file diff --git a/packages/test/src/vectors/pbkdf2.ts b/packages/test/src/vectors/pbkdf2.ts new file mode 100644 index 0000000..f0f340d --- /dev/null +++ b/packages/test/src/vectors/pbkdf2.ts @@ -0,0 +1,56 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams } from "../types"; + +export const PBKDF2: ITestParams = { + name: "PBKDF2", + actions: { + deriveBits: [ + { + key: { + format: "raw", + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + algorithm: { + name: "PBKDF2", + }, + extractable: false, + keyUsages: ["deriveBits"], + }, + algorithm: { + name: "PBKDF2", + salt: new Uint8Array([1, 2, 3, 4]), + hash: "SHA-256", + iterations: 1000, + } as types.Pbkdf2Params, + data: Convert.FromBase64("3GK58/4RT+UPLooz5HT1MQ=="), + length: 128, + }, + ], + deriveKey: [ + { + key: { + format: "raw", + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + algorithm: { + name: "PBKDF2", + }, + extractable: false, + keyUsages: ["deriveKey"], + }, + algorithm: { + name: "PBKDF2", + salt: new Uint8Array([1, 2, 3, 4]), + hash: "SHA-256", + iterations: 1000, + } as types.Pbkdf2Params, + derivedKeyType: { + name: "AES-CBC", + length: 128, + } as types.AesDerivedKeyParams, + keyUsages: ["encrypt"], + format: "raw", + keyData: Convert.FromBase64("3GK58/4RT+UPLooz5HT1MQ=="), + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/rsa/index.ts b/packages/test/src/vectors/rsa/index.ts new file mode 100644 index 0000000..faf586d --- /dev/null +++ b/packages/test/src/vectors/rsa/index.ts @@ -0,0 +1,4 @@ +export * from "./rsa_pss"; +export * from "./rsa_oaep"; +export * from "./rsa_es_pkcs1"; +export * from "./rsa_ssa_pkcs1"; \ No newline at end of file diff --git a/packages/test/src/vectors/rsa/rsa_es_pkcs1.ts b/packages/test/src/vectors/rsa/rsa_es_pkcs1.ts new file mode 100644 index 0000000..72f673a --- /dev/null +++ b/packages/test/src/vectors/rsa/rsa_es_pkcs1.ts @@ -0,0 +1,65 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams, ITestGenerateKeyAction } from "../../types"; + +export const RSAESPKCS1: ITestParams = { + name: "RSAES-PKCS1-v1_5", + actions: { + generateKey: [ + { + algorithm: { + name: "RSAES-PKCS1-v1_5", + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 1024, + } as types.RsaKeyGenParams, + extractable: false, + keyUsages: ["encrypt", "decrypt"], + } as ITestGenerateKeyAction, + ], + encrypt: [ + { + algorithm: { + name: "RSAES-PKCS1-v1_5", + } as types.Algorithm, + data: Convert.FromHex("01435e62ad3ec4850720e34f8cab620e203749f2315b203d"), + encData: Convert.FromHex("76e5ea6e1df52471454f790923f60e2baa7adf5017fe0a36c0af3e32f6390d570e1d592375ba6035fdf4ffa70764b797ab54d0ab1efe89cf31d7fc98240a4d08c2476b7eb4c2d92355b8bf60e3897c3fcbfe09f20c7b159d9a9c4a6b2ce5021dd313e492afa762c24930f97f03a429f7b2b1e1d6088651d60e323835807c6fefe7952f74e5da29e8e327ea46e69a0a6684272f022bf18ec602ffcd10a62666b35a51ec7c7d101096f663ddfa0924a86bdbcde0433b4f71dc42bfd9facf329558026f8667f1a71c3365e09843a12339d8aaf31987b0d800e53fd0835e990096cb145e278153faf1188cd5713c6fcd289cb77d80515e1d200139b8ccac4d3bcebc"), + key: { + publicKey: { + format: "jwk", + algorithm: { name: "RSAES-PKCS1-v1_5" } as types.Algorithm, + data: { + alg: "RS1", + e: "AQAB", + ext: true, + key_ops: ["encrypt"], + kty: "RSA", + n: "xr8ELXq5dGFycys8jrc8vVPkWl2GzuRgyOxATtjcNIy5MD7j1XVsUH62VVdIVUUGt0IQ7K288ij3gkIPcIkRO6GmV0vbQAqHrjSHYUAtKQXbIgNRIuJGZvO5AXsxSo1X-tfhOxe140pseOkaehz1bGduhdcYWNR3xLmp7i-GQTRDo-v6CQXtFvSUwG_EIOXnl1trN2Q1Yw4wA1dbtY9FDz69uH-dEWTx7BFCAXVTQMjNe7BTvgGeQcX7XZIw5e2pd0pXjdIgb0xMgziwmc5bbABrGlhK7TmKqA47RlWzY_Lcj7VcTUfMfh7YKKichGTUbqxlgsRTma_e-0-vgDEz6w", + }, + extractable: true, + keyUsages: ["encrypt"], + }, + privateKey: { + format: "jwk", + algorithm: { name: "RSAES-PKCS1-v1_5" } as types.Algorithm, + data: { + kty: "RSA", + alg: "RS1", + key_ops: ["decrypt"], + ext: true, + n: "xr8ELXq5dGFycys8jrc8vVPkWl2GzuRgyOxATtjcNIy5MD7j1XVsUH62VVdIVUUGt0IQ7K288ij3gkIPcIkRO6GmV0vbQAqHrjSHYUAtKQXbIgNRIuJGZvO5AXsxSo1X-tfhOxe140pseOkaehz1bGduhdcYWNR3xLmp7i-GQTRDo-v6CQXtFvSUwG_EIOXnl1trN2Q1Yw4wA1dbtY9FDz69uH-dEWTx7BFCAXVTQMjNe7BTvgGeQcX7XZIw5e2pd0pXjdIgb0xMgziwmc5bbABrGlhK7TmKqA47RlWzY_Lcj7VcTUfMfh7YKKichGTUbqxlgsRTma_e-0-vgDEz6w", + e: "AQAB", + d: "kZ2IoQ3G7UcshMdL8kC85vadW7wktldLtkqqf1qSVIo6cOfTJCWJe5yrWPG_VIJjfkeQgOh2hHKRjcV67HfwwWEZr-IrPMu6R1_DRPSxYdohiNUnUEi7TlkJ1tT882OF74rWQeaIZIS13wzjUk7_XjKWHsfO1d6t9dwWbiYx1nj4syQCcUrvHIgVXCfL85Tyu3NHqpxOdbzRb2OLmkv5ciHFExm4ai98xAgsEXbNvZQeSOOfKNsiCb-NjBXLYrbaDIsakAEV75893JubfeD51UHn7dPT8M8MmKEvrTOKCscShf01scTDHfx_hiOXK3XG4tVx9l2YGEkt3xCedljocQ", + p: "_dWMJ57SECcBbOjPRCvT97ypDyw9ydvnSZXTsn9c7ScxvUxBk6-wuMtgsLI8OWkhZGDBLyVrn-I3RMAN-A5QI_adoGdK7fq5lFWmQYvb1u1xUaGEInVFsM3BW7RBBF8N7OzHwULEQLTXb4jkpgwyCynsX0OEbVVvVerqrcr7osM", + q: "yHEjuQe9TNo-leMrL6cu-yDPfA85M8xQuBM59Cwz06-ggBRi9EOpbV-CrejGUbVlE9QmKGqIBT8C3NVBQwybzlgUihgIpnVgkb01lLEf13ohQ_GWV1mS8ybznjMgaVtVF5Lva4WixIDlXbOu4svVQpkr-KRpKvEMUCTsX-Sxx7k", + dp: "jMP4TaCN7dczuyoAh1Wm3yQIvRlTyrXgtbYZCEwJRJsPwmKfmz87Sb-_hz3QmCXtFrVxbKvb23agH8hB9uY5GziQgXvG2eLJN7Gn2YGuEKrsxNBFbraKR1pTeH-l7r6oAlPtEwfrvdaMApZv9oWc2wQMyWev8NIIRCVar7Z5hfE", + dq: "wi2g3sJZp9cRpGEDWFHM2KnrdxLEZqK7W-f8T8h2mM9eXFXjmyDlRLivP0zuuv9QoUn3gVXa2cI2QrsxUwQm-Fop47Hux1uUpvs2qgqBf1yoV0r2Sz7Sdk442fxLnOVG5OSKno5Cpbz89q54cOvoeHEswN59p4UHWai7eRZzB7k", + qi: "k9hlEyvZCWj8Fvxrknj5WHgaLrSqaVku3PVod2wUJox3aZ8vUsGmmD27lfiWwVKNRmgxLiazY40pLPu07SEmlJgF8QjzDb33k5Pcn9wRuezcCi-53LBRK6-EptZ-UjEINBlM_Cx_WOuxs7P77pwcCo2NV76ilxP5PP_34SUZ0ts", + }, + extractable: true, + keyUsages: ["decrypt"], + }, + }, + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/rsa/rsa_oaep.ts b/packages/test/src/vectors/rsa/rsa_oaep.ts new file mode 100644 index 0000000..d76ff48 --- /dev/null +++ b/packages/test/src/vectors/rsa/rsa_oaep.ts @@ -0,0 +1,113 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams, ITestGenerateKeyAction } from "../../types"; + +export const RSAOAEP: ITestParams = { + name: "RSA-OAEP", + actions: { + generateKey: ["SHA-1", "SHA-256", "SHA-384", "SHA-512"].map((hash) => { + return { + name: hash, + algorithm: { + name: "RSA-OAEP", + hash, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 1024, + } as types.RsaHashedKeyGenParams, + extractable: false, + keyUsages: ["encrypt", "decrypt"], + } as ITestGenerateKeyAction; + }), + encrypt: [ + { + name: "with label", + algorithm: { + name: "RSA-OAEP", + label: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]), + } as types.RsaOaepParams, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]), + encData: Convert.FromBase64("aHu8PBZuctYecfINKgUdB8gBoLyUUFxTZDTzTHUk9KKxtYywYml48HoijBG5DyaIWUUbOIdPgap9C8pFG2iYShQnE9Aj3gzKLHacBbFw1P79+Ei/Tm0j/THiXqCplBZC4dIp4jhTDepmdrlXZcY0slmjG+h8h8TpSmWKP3pEGGk="), + key: { + publicKey: { + format: "jwk", + algorithm: { name: "RSA-OAEP", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RSA-OAEP-256", + e: "AQAB", + ext: true, + key_ops: ["encrypt"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + }, + extractable: true, + keyUsages: ["encrypt"], + }, + privateKey: { + format: "jwk", + algorithm: { name: "RSA-OAEP", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RSA-OAEP-256", + d: "AkeIWJywp9OfYsj0ECsKmhDVBw55ZL_yU-rbIrashQ_31P6gsc_0I-SVN1rd8Hz79OJ_rTY8ZRBZ4PIyFdPoyvuo5apHdAHH6riJKxDHWPxhE-ReNVEPSTiF1ry8DSe5zC7w9BLnH_QM8bkN4cOnvgqrg7EbrGWomAGJVvoRwOM", + dp: "pOolqL7HwnmWLn7GDX8zGkm0Q1IAj-ouBL7ZZbaTm3wETLtwu-dGsQheEdzP_mfL_CTiCAwGuQBcSItimD0DdQ", + dq: "FTSY59AnkgmB7TsErWNBE3xlVB_pMpE2xWyCBCz96gyDOUOFDz8vlSV-clhjawJeRd1n30nZOPSBtOHozhwZmQ", + e: "AQAB", + ext: true, + key_ops: ["decrypt"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + p: "6jFtmBJJQFIlQUXXZYIgvH70Y9a03oWKjNuF2veb5Zf09EtLNE86NpnIm463OnoHJPW0m8wHFXZZfcYVTIPR_w", + q: "0GttDMl1kIzSV2rNzGXpOS8tUqr5Lz0EtVZwIb9GJPMmJ0P3gZ801zEgZZ4-esU7cLUf-BSZEAmfnKA80G2jIw", + qi: "FByTxX4G2eXkk1xe0IuiEv7I5NS-CnFyp8iB4XLG0rabnfcIZFKpf__X0sNyVOAVo5-jJMuUYjCRTdaXNAWhkg", + }, + extractable: true, + keyUsages: ["decrypt"], + }, + }, + }, + { + name: "without label", + algorithm: { + name: "RSA-OAEP", + } as types.RsaOaepParams, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]), + encData: Convert.FromBase64("NcsyyVE/y4Z1K5bWGElWAkvlN+jWpfgPtcytlydWUUz4RqFeW5w6KA1cQMHy3eNh920YXDjsLSYHe6Dz1CEqjIKkHS9HBuOhLA39yUArOu/fmn1lMnwb9N9roTxHDxpgY3y98DXEVkAKU4Py0rlzJLVazDV/+1YcbzFLCSKUNaI="), + key: { + publicKey: { + format: "jwk", + algorithm: { name: "RSA-OAEP", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RSA-OAEP-256", + e: "AQAB", + ext: true, + key_ops: ["encrypt"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + }, + extractable: true, + keyUsages: ["encrypt"], + }, + privateKey: { + format: "jwk", + algorithm: { name: "RSA-OAEP", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RSA-OAEP-256", + d: "AkeIWJywp9OfYsj0ECsKmhDVBw55ZL_yU-rbIrashQ_31P6gsc_0I-SVN1rd8Hz79OJ_rTY8ZRBZ4PIyFdPoyvuo5apHdAHH6riJKxDHWPxhE-ReNVEPSTiF1ry8DSe5zC7w9BLnH_QM8bkN4cOnvgqrg7EbrGWomAGJVvoRwOM", + dp: "pOolqL7HwnmWLn7GDX8zGkm0Q1IAj-ouBL7ZZbaTm3wETLtwu-dGsQheEdzP_mfL_CTiCAwGuQBcSItimD0DdQ", + dq: "FTSY59AnkgmB7TsErWNBE3xlVB_pMpE2xWyCBCz96gyDOUOFDz8vlSV-clhjawJeRd1n30nZOPSBtOHozhwZmQ", + e: "AQAB", + ext: true, + key_ops: ["decrypt"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + p: "6jFtmBJJQFIlQUXXZYIgvH70Y9a03oWKjNuF2veb5Zf09EtLNE86NpnIm463OnoHJPW0m8wHFXZZfcYVTIPR_w", + q: "0GttDMl1kIzSV2rNzGXpOS8tUqr5Lz0EtVZwIb9GJPMmJ0P3gZ801zEgZZ4-esU7cLUf-BSZEAmfnKA80G2jIw", + qi: "FByTxX4G2eXkk1xe0IuiEv7I5NS-CnFyp8iB4XLG0rabnfcIZFKpf__X0sNyVOAVo5-jJMuUYjCRTdaXNAWhkg", + }, + extractable: true, + keyUsages: ["decrypt"], + }, + }, + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/rsa/rsa_pss.ts b/packages/test/src/vectors/rsa/rsa_pss.ts new file mode 100644 index 0000000..72d16ec --- /dev/null +++ b/packages/test/src/vectors/rsa/rsa_pss.ts @@ -0,0 +1,68 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams, ITestGenerateKeyAction } from "../../types"; + +export const RSAPSS: ITestParams = { + name: "RSA-PSS", + actions: { + generateKey: ["SHA-1", "SHA-256", "SHA-384", "SHA-512"].map((hash) => { + return { + name: hash, + algorithm: { + name: "RSA-PSS", + hash, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 1024, + } as types.RsaHashedKeyGenParams, + extractable: false, + keyUsages: ["sign", "verify"], + } as ITestGenerateKeyAction; + }), + sign: [ + { + algorithm: { + name: "RSA-PSS", + saltLength: 64, + } as types.RsaPssParams, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + signature: Convert.FromBase64("OYz/7fv71ELOs5kuz5IiYq1NsXuOazl22xqIFjiY++hYFzJMWaR+ZI0WPoMOifvb1PNKmdQ4dY+QbpYC1vdzlAKfkLe22l5htLyQaXzjD/yeMZYrL0KmrabC9ayL6bxrMW+ccePStkbrF1Jn0LT09l22aX/r1y3SPrl0b+zwo/Q="), + key: { + publicKey: { + format: "jwk", + algorithm: { name: "RSA-PSS", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "PS256", + e: "AQAB", + ext: true, + key_ops: ["verify"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + }, + extractable: true, + keyUsages: ["verify"], + }, + privateKey: { + format: "jwk", + algorithm: { name: "RSA-PSS", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "PS256", + d: "AkeIWJywp9OfYsj0ECsKmhDVBw55ZL_yU-rbIrashQ_31P6gsc_0I-SVN1rd8Hz79OJ_rTY8ZRBZ4PIyFdPoyvuo5apHdAHH6riJKxDHWPxhE-ReNVEPSTiF1ry8DSe5zC7w9BLnH_QM8bkN4cOnvgqrg7EbrGWomAGJVvoRwOM", + dp: "pOolqL7HwnmWLn7GDX8zGkm0Q1IAj-ouBL7ZZbaTm3wETLtwu-dGsQheEdzP_mfL_CTiCAwGuQBcSItimD0DdQ", + dq: "FTSY59AnkgmB7TsErWNBE3xlVB_pMpE2xWyCBCz96gyDOUOFDz8vlSV-clhjawJeRd1n30nZOPSBtOHozhwZmQ", + e: "AQAB", + ext: true, + key_ops: ["sign"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + p: "6jFtmBJJQFIlQUXXZYIgvH70Y9a03oWKjNuF2veb5Zf09EtLNE86NpnIm463OnoHJPW0m8wHFXZZfcYVTIPR_w", + q: "0GttDMl1kIzSV2rNzGXpOS8tUqr5Lz0EtVZwIb9GJPMmJ0P3gZ801zEgZZ4-esU7cLUf-BSZEAmfnKA80G2jIw", + qi: "FByTxX4G2eXkk1xe0IuiEv7I5NS-CnFyp8iB4XLG0rabnfcIZFKpf__X0sNyVOAVo5-jJMuUYjCRTdaXNAWhkg", + }, + extractable: true, + keyUsages: ["sign"], + }, + }, + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/rsa/rsa_ssa_pkcs1.ts b/packages/test/src/vectors/rsa/rsa_ssa_pkcs1.ts new file mode 100644 index 0000000..b4666f7 --- /dev/null +++ b/packages/test/src/vectors/rsa/rsa_ssa_pkcs1.ts @@ -0,0 +1,121 @@ +import * as types from "@peculiar/webcrypto-types"; +import { Convert } from "pvtsutils"; +import { ITestParams, ITestGenerateKeyAction } from "../../types"; + +export const RSASSAPKCS1: ITestParams = { + name: "RSASSA-PKCS1-v1_5", + actions: { + generateKey: ["SHA-1", "SHA-256", "SHA-384", "SHA-512"].map((hash) => { + return { + name: hash, + algorithm: { + name: "RSASSA-PKCS1-v1_5", + hash, + publicExponent: new Uint8Array([1, 0, 1]), + modulusLength: 1024, + } as types.RsaHashedKeyGenParams, + extractable: false, + keyUsages: ["sign", "verify"], + } as ITestGenerateKeyAction; + }), + sign: [ + { + algorithm: { + name: "RSASSA-PKCS1-v1_5", + }, + data: new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]), + signature: Convert.FromBase64("f8OvbYnwX5YPVPjWkOTalYTFJjS1Ks7iNmPdLEby/kK6BEGk5uPvY/ebcok6sTQpQXJXJFJbOcMrZftmJXpm1szcgOdNgVW6FDc3722a9Mzvk/YfvNUCQRNEMON9lYKdpOLSXAFpXR5ovZytbFQ2w2ztpKkJvNY2QZQlizcZKSg="), + key: { + publicKey: { + format: "jwk", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RS256", + e: "AQAB", + ext: true, + key_ops: ["verify"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + }, + extractable: true, + keyUsages: ["verify"], + }, + privateKey: { + format: "jwk", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RS256", + d: "AkeIWJywp9OfYsj0ECsKmhDVBw55ZL_yU-rbIrashQ_31P6gsc_0I-SVN1rd8Hz79OJ_rTY8ZRBZ4PIyFdPoyvuo5apHdAHH6riJKxDHWPxhE-ReNVEPSTiF1ry8DSe5zC7w9BLnH_QM8bkN4cOnvgqrg7EbrGWomAGJVvoRwOM", + dp: "pOolqL7HwnmWLn7GDX8zGkm0Q1IAj-ouBL7ZZbaTm3wETLtwu-dGsQheEdzP_mfL_CTiCAwGuQBcSItimD0DdQ", + dq: "FTSY59AnkgmB7TsErWNBE3xlVB_pMpE2xWyCBCz96gyDOUOFDz8vlSV-clhjawJeRd1n30nZOPSBtOHozhwZmQ", + e: "AQAB", + ext: true, + key_ops: ["sign"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + p: "6jFtmBJJQFIlQUXXZYIgvH70Y9a03oWKjNuF2veb5Zf09EtLNE86NpnIm463OnoHJPW0m8wHFXZZfcYVTIPR_w", + q: "0GttDMl1kIzSV2rNzGXpOS8tUqr5Lz0EtVZwIb9GJPMmJ0P3gZ801zEgZZ4-esU7cLUf-BSZEAmfnKA80G2jIw", + qi: "FByTxX4G2eXkk1xe0IuiEv7I5NS-CnFyp8iB4XLG0rabnfcIZFKpf__X0sNyVOAVo5-jJMuUYjCRTdaXNAWhkg", + }, + extractable: true, + keyUsages: ["sign"], + }, + }, + }, + ], + import: [ + { + name: "public key JWK", + format: "jwk", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RS256", + e: "AQAB", + ext: true, + key_ops: ["verify"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + }, + extractable: true, + keyUsages: ["verify"], + }, + { + name: "public key SPKI", + format: "spki", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: Convert.FromBase64("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+qm93G7JnqspidZOP9nMMEVkAACWl7mGmiJgepraPmQru/xTkRo9jZsuJv2bgHjSP6fcVX3FQIaKmVZ2owkkpP7g+MY7kTdLg32SMWG7nuehhPvPvfTYnSwld6gVtfGWAT7gbnk7GWbnYgPb9El6w/mfNwZOuJDChFusk/k4S3QIDAQAB"), + extractable: true, + keyUsages: ["verify"], + }, + { + name: "private key JWK", + format: "jwk", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: { + alg: "RS256", + d: "AkeIWJywp9OfYsj0ECsKmhDVBw55ZL_yU-rbIrashQ_31P6gsc_0I-SVN1rd8Hz79OJ_rTY8ZRBZ4PIyFdPoyvuo5apHdAHH6riJKxDHWPxhE-ReNVEPSTiF1ry8DSe5zC7w9BLnH_QM8bkN4cOnvgqrg7EbrGWomAGJVvoRwOM", + dp: "pOolqL7HwnmWLn7GDX8zGkm0Q1IAj-ouBL7ZZbaTm3wETLtwu-dGsQheEdzP_mfL_CTiCAwGuQBcSItimD0DdQ", + dq: "FTSY59AnkgmB7TsErWNBE3xlVB_pMpE2xWyCBCz96gyDOUOFDz8vlSV-clhjawJeRd1n30nZOPSBtOHozhwZmQ", + e: "AQAB", + ext: true, + key_ops: ["sign"], + kty: "RSA", + n: "vqpvdxuyZ6rKYnWTj_ZzDBFZAAAlpe5hpoiYHqa2j5kK7v8U5EaPY2bLib9m4B40j-n3FV9xUCGiplWdqMJJKT-4PjGO5E3S4N9kjFhu57noYT7z7302J0sJXeoFbXxlgE-4G55Oxlm52ID2_RJesP5nzcGTriQwoRbrJP5OEt0", + p: "6jFtmBJJQFIlQUXXZYIgvH70Y9a03oWKjNuF2veb5Zf09EtLNE86NpnIm463OnoHJPW0m8wHFXZZfcYVTIPR_w", + q: "0GttDMl1kIzSV2rNzGXpOS8tUqr5Lz0EtVZwIb9GJPMmJ0P3gZ801zEgZZ4-esU7cLUf-BSZEAmfnKA80G2jIw", + qi: "FByTxX4G2eXkk1xe0IuiEv7I5NS-CnFyp8iB4XLG0rabnfcIZFKpf__X0sNyVOAVo5-jJMuUYjCRTdaXNAWhkg", + }, + extractable: true, + keyUsages: ["sign"], + }, + { + name: "private key pkcs8", + format: "pkcs8", + algorithm: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" } as types.RsaHashedImportParams, + data: Convert.FromBase64("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAL6qb3cbsmeqymJ1k4/2cwwRWQAAJaXuYaaImB6mto+ZCu7/FORGj2Nmy4m/ZuAeNI/p9xVfcVAhoqZVnajCSSk/uD4xjuRN0uDfZIxYbue56GE+8+99NidLCV3qBW18ZYBPuBueTsZZudiA9v0SXrD+Z83Bk64kMKEW6yT+ThLdAgMBAAECgYACR4hYnLCn059iyPQQKwqaENUHDnlkv/JT6tsitqyFD/fU/qCxz/Qj5JU3Wt3wfPv04n+tNjxlEFng8jIV0+jK+6jlqkd0AcfquIkrEMdY/GET5F41UQ9JOIXWvLwNJ7nMLvD0Eucf9AzxuQ3hw6e+CquDsRusZaiYAYlW+hHA4wJBAOoxbZgSSUBSJUFF12WCILx+9GPWtN6Fiozbhdr3m+WX9PRLSzRPOjaZyJuOtzp6ByT1tJvMBxV2WX3GFUyD0f8CQQDQa20MyXWQjNJXas3MZek5Ly1SqvkvPQS1VnAhv0Yk8yYnQ/eBnzTXMSBlnj56xTtwtR/4FJkQCZ+coDzQbaMjAkEApOolqL7HwnmWLn7GDX8zGkm0Q1IAj+ouBL7ZZbaTm3wETLtwu+dGsQheEdzP/mfL/CTiCAwGuQBcSItimD0DdQJAFTSY59AnkgmB7TsErWNBE3xlVB/pMpE2xWyCBCz96gyDOUOFDz8vlSV+clhjawJeRd1n30nZOPSBtOHozhwZmQJAFByTxX4G2eXkk1xe0IuiEv7I5NS+CnFyp8iB4XLG0rabnfcIZFKpf//X0sNyVOAVo5+jJMuUYjCRTdaXNAWhkg=="), + extractable: true, + keyUsages: ["sign"], + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/vectors/sha.ts b/packages/test/src/vectors/sha.ts new file mode 100644 index 0000000..f5765f2 --- /dev/null +++ b/packages/test/src/vectors/sha.ts @@ -0,0 +1,36 @@ +import { Convert } from "pvtsutils"; +import { ITestParams } from "../types"; + +const data = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]); + +export const SHA: ITestParams = { + name: "SHA", + actions: { + digest: [ + { + name: "SHA-1", + algorithm: "SHA-1", + data, + hash: Convert.FromBase64("6JrVqWMcPv3e1+Psznm00P7c4b8="), + }, + { + name: "SHA-256", + algorithm: "SHA-256", + data, + hash: Convert.FromBase64("monGjExeKLjEpVZ2c9Ri//UV20YRb5kAYk0JxHT1k/s="), + }, + { + name: "SHA-384", + algorithm: "SHA-384", + data, + hash: Convert.FromBase64("E9WqubQC9JnxffIniWwf0soI91o5z0Kbvk+s/32Fi3z28kAh+Fcne7Hgy1nnW4rR"), + }, + { + name: "SHA-512", + algorithm: "SHA-512", + data, + hash: Convert.FromBase64("OtPzaXlFDU9TNmJE7PEBD0+RIdaIgoX/FBBP1a3thdSKoXG/HjOhEmAvkrenCIsph4kBL7h7kFYyEkGhn7dOCw=="), + }, + ], + }, +}; \ No newline at end of file diff --git a/packages/test/src/webcrypto_test.ts b/packages/test/src/webcrypto_test.ts new file mode 100644 index 0000000..952483a --- /dev/null +++ b/packages/test/src/webcrypto_test.ts @@ -0,0 +1,34 @@ +import * as types from "@peculiar/webcrypto-types"; +import { testCrypto } from "./helper"; +import { ITestParams, ITestVectorsExclude } from "./types"; +import * as Vectors from "./vectors"; + +export class WebcryptoTest { + + /** + * Adds non default check + * @param func + */ + public static add(crypto: types.Crypto, param: ITestParams) { + testCrypto(crypto, param); + } + + /** + * Default check + * @param crypto + * @param vectors + */ + public static check(crypto: types.Crypto, vectors?: ITestParams[] | ITestVectorsExclude) { + if (Array.isArray(vectors)) { + vectors.forEach((element) => { + testCrypto(crypto, element); + }); + } else { + for (const key in Vectors) { + if (!vectors?.[key]) { + testCrypto(crypto, (Vectors as any)[key]); + } + } + } + } +} diff --git a/packages/test/test/test.ts b/packages/test/test/test.ts new file mode 100644 index 0000000..d1431ae --- /dev/null +++ b/packages/test/test/test.ts @@ -0,0 +1,42 @@ +import { Crypto } from "@peculiar/webcrypto"; +// eslint-disable-next-line import/named +import { WebcryptoTest, vectors } from "../src"; + +const crypto = new Crypto(); +WebcryptoTest.check(crypto); +WebcryptoTest.check(crypto, [vectors.SHA]); +WebcryptoTest.check(crypto, { + AES128CBC: true, + AES192CBC: true, + AES256CBC: true, + AES128CMAC: true, + AES192CMAC: true, + AES128CTR: true, + AES192CTR: true, + AES256CTR: true, + AES128ECB: true, + AES192ECB: true, + AES256ECB: true, + AES128GCM: true, + AES192GCM: true, + AES256GCM: true, + AES128KW: true, + AES192KW: true, + AES256KW: true, + + DESCBC: true, + DESEDE3CBC: true, + + RSAESPKCS1: true, + RSASSAPKCS1: true, + RSAOAEP: true, + RSAPSS: true, + + ECDSA: true, + ECDH: true, + + HKDF: true, + HMAC: true, + PBKDF2: true +}); +WebcryptoTest.add(crypto, vectors.SHA); \ No newline at end of file diff --git a/packages/types/README.md b/packages/types/README.md new file mode 100644 index 0000000..99c28ba --- /dev/null +++ b/packages/types/README.md @@ -0,0 +1,11 @@ +# `@peculiar/webcrypto-types` + +> TODO: description + +## Usage + +``` +const webcryptoTypes = require('@peculiar/webcrypto-types'); + +// TODO: DEMONSTRATE API +``` diff --git a/packages/types/package.json b/packages/types/package.json new file mode 100644 index 0000000..b089c17 --- /dev/null +++ b/packages/types/package.json @@ -0,0 +1,29 @@ +{ + "name": "@peculiar/webcrypto-types", + "version": "3.0.0", + "description": "> TODO: description", + "author": "microshine ", + "homepage": "https://github.com/PeculiarVentures/webcrypto/tree/master/packages/webcrypto-types#readme", + "license": "MIT", + "types": "src/index.d.ts", + "directories": { + "lib": "lib", + "test": "__tests__" + }, + "files": [ + "lib" + ], + "publishConfig": { + "access": "public" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/PeculiarVentures/webcrypto.git" + }, + "scripts": { + "test": "echo \"Error: run tests from root\" && exit 1" + }, + "bugs": { + "url": "https://github.com/PeculiarVentures/webcrypto/issues" + } +} \ No newline at end of file diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts new file mode 100644 index 0000000..1bb42ef --- /dev/null +++ b/packages/types/src/index.ts @@ -0,0 +1,382 @@ +//#region WebCrypto API + +export type BufferSource = ArrayBuffer | ArrayBufferView; + +export type KeyFormat = "jwk" | "pkcs8" | "raw" | "spki"; + +export type KeyType = "private" | "public" | "secret"; + +export type KeyUsage = "decrypt" | "deriveBits" | "deriveKey" | "encrypt" | "sign" | "unwrapKey" | "verify" | "wrapKey"; + +export interface Algorithm { + name: string; +} + +export interface JsonWebKey { + alg?: string; + crv?: string; + d?: string; + dp?: string; + dq?: string; + e?: string; + ext?: boolean; + k?: string; + key_ops?: string[]; + kty?: string; + n?: string; + oth?: RsaOtherPrimesInfo[]; + p?: string; + q?: string; + qi?: string; + use?: string; + x?: string; + y?: string; +} + +export interface KeyAlgorithm { + name: string; +} + +export type BigInteger = Uint8Array; + +export type HashAlgorithmIdentifier = AlgorithmIdentifier; + +export type AlgorithmIdentifier = Algorithm | string; + +//#region RSA + +export interface RsaHashedImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; +} + +export interface RsaHashedKeyAlgorithm extends RsaKeyAlgorithm { + hash: KeyAlgorithm; +} + +export interface RsaHashedKeyGenParams extends RsaKeyGenParams { + hash: HashAlgorithmIdentifier; +} + +export interface RsaKeyAlgorithm extends KeyAlgorithm { + modulusLength: number; + publicExponent: BigInteger; +} + +export interface RsaKeyGenParams extends Algorithm { + modulusLength: number; + publicExponent: BigInteger; +} + +export interface RsaOaepParams extends Algorithm { + label?: BufferSource; +} + +export interface RsaOtherPrimesInfo { + d?: string; + r?: string; + t?: string; +} + +export interface RsaPssParams extends Algorithm { + saltLength: number; +} + +//#endregion + +//#region AES + +export interface AesCbcParams extends Algorithm { + iv: BufferSource; +} + +export interface AesCtrParams extends Algorithm { + counter: BufferSource; + length: number; +} + +export interface AesDerivedKeyParams extends Algorithm { + length: number; +} + +export interface AesGcmParams extends Algorithm { + additionalData?: BufferSource; + iv: BufferSource; + tagLength?: number; +} + +export interface AesKeyAlgorithm extends KeyAlgorithm { + length: number; +} + +export interface AesKeyGenParams extends Algorithm { + length: number; +} + +//#endregion + +//#region EC + +export type NamedCurve = string; + +export interface EcKeyAlgorithm extends KeyAlgorithm { + namedCurve: NamedCurve; +} + +export interface EcKeyGenParams extends Algorithm { + namedCurve: NamedCurve; +} + +export interface EcKeyImportParams extends Algorithm { + namedCurve: NamedCurve; +} + +export interface EcdhKeyDeriveParams extends Algorithm { + public: CryptoKey; +} + +export interface EcdsaParams extends Algorithm { + hash: HashAlgorithmIdentifier; +} + +//#endregion + +//#region HKDF + +export interface HkdfParams extends Algorithm { + hash: HashAlgorithmIdentifier; + info: BufferSource; + salt: BufferSource; +} + +//#endregion + +//#region HMAC + +export interface HmacImportParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; +} + +export interface HmacKeyAlgorithm extends KeyAlgorithm { + hash: KeyAlgorithm; + length: number; +} + +export interface HmacKeyGenParams extends Algorithm { + hash: HashAlgorithmIdentifier; + length?: number; +} + +//#endregion + +//#region PKBKDF2 + +export interface Pbkdf2Params extends Algorithm { + hash: HashAlgorithmIdentifier; + iterations: number; + salt: BufferSource; +} + +//#endregion + +export interface CryptoKeyPair { + privateKey: CryptoKey; + publicKey: CryptoKey; +} + +/** + * The CryptoKey dictionary of the Web Crypto API represents a cryptographic key. + * Available only in secure contexts. + */ +export interface CryptoKey { + readonly algorithm: KeyAlgorithm; + readonly extractable: boolean; + readonly type: KeyType; + readonly usages: KeyUsage[]; +} + +/** + * This Web Crypto API export interface provides a number of low-level cryptographic functions. + * It is accessed via the Crypto.subtle properties available in a window context (via Window.crypto). + * + * Available only in secure contexts. + */ +export interface SubtleCrypto { + decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise; + deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise; + deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKey: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise; + digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise; + encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise; + exportKey(format: "jwk", key: CryptoKey): Promise; + exportKey(format: Exclude, key: CryptoKey): Promise; + exportKey(format: KeyFormat, key: CryptoKey): Promise; + generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise; + generateKey(algorithm: AesKeyGenParams | HmacKeyGenParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise; + generateKey(algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise; + importKey(format: "jwk", keyData: JsonWebKey, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise; + importKey(format: Exclude, keyData: BufferSource, algorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise; + importKey(format: KeyFormat, keyData: BufferSource | JsonWebKey, algorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise; + sign(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, data: BufferSource): Promise; + unwrapKey(format: KeyFormat, wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, unwrappedKeyAlgorithm: AlgorithmIdentifier | RsaHashedImportParams | EcKeyImportParams | HmacImportParams | AesKeyAlgorithm, extractable: boolean, keyUsages: KeyUsage[]): Promise; + verify(algorithm: AlgorithmIdentifier | RsaPssParams | EcdsaParams, key: CryptoKey, signature: BufferSource, data: BufferSource): Promise; + wrapKey(format: KeyFormat, key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams): Promise; +} + +/** + * Basic cryptography features available in the current context. It allows access to a cryptographically + * strong random number generator and to cryptographic primitives. + */ +export interface Crypto { + /** + * Returns a SubtleCrypto object providing access to common cryptographic primitives, + * like hashing, signing, encryption or decryption + * + * Available only in secure contexts. + */ + readonly subtle: SubtleCrypto; + + /** + * Generates cryptographically random values + * @param array Is an integer-based BufferSource. + * All elements in the array are going to be overridden with random numbers. + */ + getRandomValues(array: T): T; + + /** + * Generates a v4 UUID using a cryptographically secure random number generator + * + * Available only in secure contexts. + * @returns UUID v4 string + */ + randomUUID(): string; +} + +//#endregion + +export type HexString = string; +export type KeyUsages = KeyUsage[]; + +export type ProviderKeyUsage = KeyUsages; + +export interface ProviderKeyPairUsage { + privateKey: KeyUsages; + publicKey: KeyUsages; +} + +export type ProviderKeyUsages = ProviderKeyUsage | ProviderKeyPairUsage; + +export interface HashedAlgorithm extends Algorithm { + hash: AlgorithmIdentifier; +} + +export type ImportAlgorithms = Algorithm | RsaHashedImportParams | EcKeyImportParams; + +/** + * Base generic class for crypto storages + */ +export interface CryptoStorage { + /** + * Returns list of indexes from storage + */ + keys(): Promise; + + /** + * Returns index of item in storage + * @param item Crypto item + * @returns Index of item in storage otherwise null + */ + indexOf(item: T): Promise; + + /** + * Add crypto item to storage and returns it's index + */ + setItem(item: T): Promise; + + /** + * Returns crypto item from storage by index + * @param index index of crypto item + * @returns Crypto item + * @throws Throws Error when cannot find crypto item in storage + */ + getItem(index: string): Promise; + + /** + * Returns `true` if item is in storage otherwise `false` + * @param item Crypto item + */ + hasItem(item: T): Promise; + + /** + * Removes all items from storage + */ + clear(): Promise; + + /** + * Removes crypto item from storage by index + * @param index Index of crypto storage + */ + removeItem(index: string): Promise; + +} + +//#region CryptoKeyStorage + +export interface CryptoKeyStorage extends CryptoStorage { + + getItem(index: string): Promise; + getItem(index: string, algorithm: ImportAlgorithms, extractable: boolean, keyUsages: KeyUsage[]): Promise; + +} + +//#endregion CryptoKeyStorage + +//#region CryptoCertificateStorage + +export type CryptoCertificateFormat = "raw" | "pem"; +export type CryptoCertificateType = "x509" | "request"; + +export interface CryptoCertificate { + type: CryptoCertificateType; + publicKey: CryptoKey; +} + +export interface CryptoX509Certificate extends CryptoCertificate { + type: "x509"; + notBefore: Date; + notAfter: Date; + serialNumber: HexString; + issuerName: string; + subjectName: string; +} + +export interface CryptoX509CertificateRequest extends CryptoCertificate { + type: "request"; + subjectName: string; +} + +export interface CryptoCertificateStorage extends CryptoStorage { + + getItem(index: string): Promise; + getItem(index: string, algorithm: ImportAlgorithms, keyUsages: KeyUsage[]): Promise; + + exportCert(format: CryptoCertificateFormat, item: CryptoCertificate): Promise; + exportCert(format: "raw", item: CryptoCertificate): Promise; + exportCert(format: "pem", item: CryptoCertificate): Promise; + + importCert(format: CryptoCertificateFormat, data: BufferSource | string, algorithm: ImportAlgorithms, keyUsages: KeyUsage[]): Promise; + importCert(format: "raw", data: BufferSource, algorithm: ImportAlgorithms, keyUsages: KeyUsage[]): Promise; + importCert(format: "pem", data: string, algorithm: ImportAlgorithms, keyUsages: KeyUsage[]): Promise; +} + +//#endregion CryptoCertificateStorage + +export interface CryptoStorages { + keyStorage: CryptoKeyStorage; + certStorage: CryptoCertificateStorage; +} + +export type PreparedHashedAlgorithm = Omit & { hash: Algorithm; }; + +export interface AesCmacParams extends Algorithm { + length: number; +} diff --git a/src/index.ts b/src/index.ts deleted file mode 100644 index 2be3353..0000000 --- a/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { CryptoKey } from "webcrypto-core"; -export { Crypto } from "./crypto"; diff --git a/src/mechs/ec/ec_dh.ts b/src/mechs/ec/ec_dh.ts deleted file mode 100644 index 0cdec6c..0000000 --- a/src/mechs/ec/ec_dh.ts +++ /dev/null @@ -1,49 +0,0 @@ -import * as core from "webcrypto-core"; -import { CryptoKey } from "../../keys"; -import { setCryptoKey, getCryptoKey } from "../storage"; -import { EcCrypto } from "./crypto"; -import { EcPrivateKey } from "./private_key"; -import { EcPublicKey } from "./public_key"; - -export class EcdhProvider extends core.EcdhProvider { - - public override namedCurves = core.EcCurves.names; - - public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const keys = await EcCrypto.generateKey( - { - ...algorithm, - name: this.name, - }, - extractable, - keyUsages); - - return { - privateKey: setCryptoKey(keys.privateKey as CryptoKey), - publicKey: setCryptoKey(keys.publicKey as CryptoKey), - }; - } - - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { - return EcCrypto.exportKey(format, getCryptoKey(key)); - } - - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const key = await EcCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); - return setCryptoKey(key); - } - - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { - super.checkCryptoKey(key, keyUsage); - const internalKey = getCryptoKey(key); - if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) { - throw new TypeError("key: Is not EC CryptoKey"); - } - } - - public async onDeriveBits(algorithm: EcdhKeyDeriveParams, baseKey: CryptoKey, length: number): Promise { - const bits = await EcCrypto.deriveBits({...algorithm, public: getCryptoKey(algorithm.public)}, getCryptoKey(baseKey), length); - return bits; - } - -} diff --git a/src/mechs/ec/private_key.ts b/src/mechs/ec/private_key.ts deleted file mode 100644 index 1855223..0000000 --- a/src/mechs/ec/private_key.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { IJsonConvertible, JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys"; -import { getOidByNamedCurve } from "./helper"; - -export class EcPrivateKey extends AsymmetricKey implements IJsonConvertible { - public readonly type: "private" = "private"; - public override algorithm!: EcKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo); - return AsnParser.parse(keyInfo.privateKey, core.asn1.EcPrivateKey); - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "EC", - crv: this.algorithm.namedCurve, - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, JsonSerializer.toJSON(key)); - } - - public fromJSON(json: JsonWebKey) { - if (!json.crv) { - throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); - } - - const keyInfo = new core.asn1.PrivateKeyInfo(); - keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; - keyInfo.privateKeyAlgorithm.parameters = AsnSerializer.serialize( - new core.asn1.ObjectIdentifier(getOidByNamedCurve(json.crv)), - ); - const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.EcPrivateKey }); - keyInfo.privateKey = AsnSerializer.serialize(key); - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - - return this; - } - -} diff --git a/src/mechs/ec/public_key.ts b/src/mechs/ec/public_key.ts deleted file mode 100644 index 8911228..0000000 --- a/src/mechs/ec/public_key.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { IJsonConvertible, JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys/asymmetric"; -import { getOidByNamedCurve } from "./helper"; - -export class EcPublicKey extends AsymmetricKey implements IJsonConvertible { - - public readonly type: "public" = "public"; - public override algorithm!: EcKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo); - return new core.asn1.EcPublicKey(keyInfo.publicKey); - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "EC", - crv: this.algorithm.namedCurve, - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, JsonSerializer.toJSON(key)); - } - - public fromJSON(json: JsonWebKey) { - if (!json.crv) { - throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); - } - - const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.EcPublicKey }); - - const keyInfo = new core.asn1.PublicKeyInfo(); - keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; - keyInfo.publicKeyAlgorithm.parameters = AsnSerializer.serialize( - new core.asn1.ObjectIdentifier(getOidByNamedCurve(json.crv)), - ); - keyInfo.publicKey = AsnSerializer.toASN(key).valueHex; - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - - return this; - } -} diff --git a/src/mechs/ed/ecdh_es.ts b/src/mechs/ed/ecdh_es.ts deleted file mode 100644 index 7dcc2f0..0000000 --- a/src/mechs/ed/ecdh_es.ts +++ /dev/null @@ -1,37 +0,0 @@ -import * as core from "webcrypto-core"; -import { CryptoKey } from "../../keys"; -import { getCryptoKey, setCryptoKey } from "../storage"; -import { EdCrypto } from "./crypto"; - -export class EcdhEsProvider extends core.EcdhEsProvider { - - public async onGenerateKey(algorithm: EcKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const keys = await EdCrypto.generateKey( - { - name: this.name, - namedCurve: algorithm.namedCurve.toUpperCase(), - }, - extractable, - keyUsages); - - return { - privateKey: setCryptoKey(keys.privateKey as CryptoKey), - publicKey: setCryptoKey(keys.publicKey as CryptoKey), - }; - } - - public async onDeriveBits(algorithm: EcdhKeyDeriveParams, baseKey: core.CryptoKey, length: number): Promise { - const bits = await EdCrypto.deriveBits({...algorithm, public: getCryptoKey(algorithm.public)}, getCryptoKey(baseKey), length); - return bits; - } - - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { - return EdCrypto.exportKey(format, getCryptoKey(key)); - } - - public async onImportKey(format: KeyFormat, keyData: ArrayBuffer | JsonWebKey, algorithm: EcKeyImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); - return setCryptoKey(key); - } - -} \ No newline at end of file diff --git a/src/mechs/ed/private_key.ts b/src/mechs/ed/private_key.ts deleted file mode 100644 index df4b1f6..0000000 --- a/src/mechs/ed/private_key.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { IJsonConvertible, JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys"; -import { getOidByNamedCurve } from "./helper"; - -export class EdPrivateKey extends AsymmetricKey implements IJsonConvertible { - public readonly type: "private" = "private"; - public override algorithm!: EcKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo); - return AsnParser.parse(keyInfo.privateKey, core.asn1.CurvePrivateKey); - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "OKP", - crv: this.algorithm.namedCurve, - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, JsonSerializer.toJSON(key)); - } - - public fromJSON(json: JsonWebKey) { - if (!json.crv) { - throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); - } - - const keyInfo = new core.asn1.PrivateKeyInfo(); - keyInfo.privateKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); - const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.CurvePrivateKey }); - keyInfo.privateKey = AsnSerializer.serialize(key); - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - - return this; - } - -} diff --git a/src/mechs/ed/public_key.ts b/src/mechs/ed/public_key.ts deleted file mode 100644 index 939a013..0000000 --- a/src/mechs/ed/public_key.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { IJsonConvertible } from "@peculiar/json-schema"; -import { Convert } from "pvtsutils"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys/asymmetric"; -import { getOidByNamedCurve } from "./helper"; - -export class EdPublicKey extends AsymmetricKey implements IJsonConvertible { - - public readonly type: "public" = "public"; - public override algorithm!: EcKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo); - return keyInfo.publicKey; - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "OKP", - crv: this.algorithm.namedCurve, - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, { - x: Convert.ToBase64Url(key) - }); - } - - public fromJSON(json: JsonWebKey) { - if (!json.crv) { - throw new core.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); - } - if (!json.x) { - throw new core.OperationError(`Cannot get property from JWK. Property 'x' is required`); - } - - const keyInfo = new core.asn1.PublicKeyInfo(); - keyInfo.publicKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); - keyInfo.publicKey = Convert.FromBase64Url(json.x); - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - - return this; - } -} diff --git a/src/mechs/hkdf/hkdf.ts b/src/mechs/hkdf/hkdf.ts deleted file mode 100644 index 58a0e21..0000000 --- a/src/mechs/hkdf/hkdf.ts +++ /dev/null @@ -1,53 +0,0 @@ -import crypto from "crypto"; -import * as core from "webcrypto-core"; -import { BufferSourceConverter, CryptoKey } from "webcrypto-core"; -import { setCryptoKey, getCryptoKey } from "../storage"; -import { HkdfCryptoKey } from "./key"; - -export class HkdfProvider extends core.HkdfProvider { - - public async onImportKey(format: KeyFormat, keyData: ArrayBuffer, algorithm: HmacImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - if (format.toLowerCase() !== "raw") { - throw new core.OperationError("Operation not supported"); - } - - const key: HkdfCryptoKey = new HkdfCryptoKey(); - key.data = Buffer.from(keyData); - key.algorithm = { name: this.name }; - key.extractable = extractable; - key.usages = keyUsages; - return setCryptoKey(key); - } - - public async onDeriveBits(params: HkdfParams, baseKey: HkdfCryptoKey, length: number): Promise { - const hash = (params.hash as Algorithm).name.replace("-", ""); - const hashLength = crypto.createHash(hash).digest().length; - - const byteLength = length / 8; - const info = BufferSourceConverter.toUint8Array(params.info); - - const PRK = crypto.createHmac(hash, BufferSourceConverter.toUint8Array(params.salt)) - .update(BufferSourceConverter.toUint8Array(getCryptoKey(baseKey).data)) - .digest(); - - const blocks = [Buffer.alloc(0)]; - const blockCount = Math.ceil(byteLength / hashLength) + 1; // Includes empty buffer - for (let i = 1; i < blockCount; ++i) { - blocks.push( - crypto.createHmac(hash, PRK) - .update(Buffer.concat([blocks[i - 1], info, Buffer.from([i])])) - .digest(), - ); - } - - return Buffer.concat(blocks).slice(0, byteLength); - } - - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { - super.checkCryptoKey(key, keyUsage); - if (!(getCryptoKey(key) instanceof HkdfCryptoKey)) { - throw new TypeError("key: Is not HKDF CryptoKey"); - } - } - -} diff --git a/src/mechs/rsa/private_key.ts b/src/mechs/rsa/private_key.ts deleted file mode 100644 index 0fd17b6..0000000 --- a/src/mechs/rsa/private_key.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys"; -import { getJwkAlgorithm } from "./helper"; - -export class RsaPrivateKey extends AsymmetricKey { - public readonly type: "private" = "private"; - public override algorithm!: RsaHashedKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PrivateKeyInfo); - return AsnParser.parse(keyInfo.privateKey, core.asn1.RsaPrivateKey); - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "RSA", - alg: getJwkAlgorithm(this.algorithm), - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, JsonSerializer.toJSON(key)); - } - - public fromJSON(json: JsonWebKey) { - const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.RsaPrivateKey }); - - const keyInfo = new core.asn1.PrivateKeyInfo(); - keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; - keyInfo.privateKeyAlgorithm.parameters = null; - keyInfo.privateKey = AsnSerializer.serialize(key); - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - } - -} diff --git a/src/mechs/rsa/public_key.ts b/src/mechs/rsa/public_key.ts deleted file mode 100644 index 32f01d3..0000000 --- a/src/mechs/rsa/public_key.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AsnParser, AsnSerializer } from "@peculiar/asn1-schema"; -import { JsonParser, JsonSerializer } from "@peculiar/json-schema"; -import * as core from "webcrypto-core"; -import { AsymmetricKey } from "../../keys/asymmetric"; -import { getJwkAlgorithm } from "./helper"; - -export class RsaPublicKey extends AsymmetricKey { - public readonly type: "public" = "public"; - public override algorithm!: RsaHashedKeyAlgorithm; - - public getKey() { - const keyInfo = AsnParser.parse(this.data, core.asn1.PublicKeyInfo); - return AsnParser.parse(keyInfo.publicKey, core.asn1.RsaPublicKey); - } - - public toJSON() { - const key = this.getKey(); - - const json: JsonWebKey = { - kty: "RSA", - alg: getJwkAlgorithm(this.algorithm), - key_ops: this.usages, - ext: this.extractable, - }; - - return Object.assign(json, JsonSerializer.toJSON(key)); - } - - public fromJSON(json: JsonWebKey) { - const key = JsonParser.fromJSON(json, { targetSchema: core.asn1.RsaPublicKey }); - - const keyInfo = new core.asn1.PublicKeyInfo(); - keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; - keyInfo.publicKeyAlgorithm.parameters = null; - keyInfo.publicKey = AsnSerializer.serialize(key); - - this.data = Buffer.from(AsnSerializer.serialize(keyInfo)); - } -} diff --git a/src/mechs/rsa/rsa_pss.ts b/src/mechs/rsa/rsa_pss.ts deleted file mode 100644 index 12ddb0d..0000000 --- a/src/mechs/rsa/rsa_pss.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as core from "webcrypto-core"; -import { setCryptoKey, getCryptoKey } from "../storage"; -import { RsaCrypto } from "./crypto"; -import { RsaPrivateKey } from "./private_key"; -import { RsaPublicKey } from "./public_key"; - -export class RsaPssProvider extends core.RsaPssProvider { - - public override hashAlgorithms = [ - "SHA-1", "SHA-256", "SHA-384", "SHA-512", - "shake128", "shake256", - "SHA3-256", "SHA3-384", "SHA3-512"]; - - public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const keys = await RsaCrypto.generateKey( - { - ...algorithm, - name: this.name, - }, - extractable, - keyUsages); - - return { - privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), - publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), - }; - } - - public async onSign(algorithm: RsaPssParams, key: RsaPrivateKey, data: ArrayBuffer): Promise { - return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data)); - } - - public async onVerify(algorithm: RsaPssParams, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { - return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data)); - } - - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { - return RsaCrypto.exportKey(format, getCryptoKey(key)); - } - - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); - return setCryptoKey(key); - } - - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { - super.checkCryptoKey(key, keyUsage); - const internalKey = getCryptoKey(key); - if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { - throw new TypeError("key: Is not RSA CryptoKey"); - } - } - -} diff --git a/src/mechs/rsa/rsa_ssa.ts b/src/mechs/rsa/rsa_ssa.ts deleted file mode 100644 index 3b6bb98..0000000 --- a/src/mechs/rsa/rsa_ssa.ts +++ /dev/null @@ -1,54 +0,0 @@ -import * as core from "webcrypto-core"; -import { setCryptoKey, getCryptoKey } from "../storage"; -import { RsaCrypto } from "./crypto"; -import { RsaPrivateKey } from "./private_key"; -import { RsaPublicKey } from "./public_key"; - -export class RsaSsaProvider extends core.RsaSsaProvider { - - public override hashAlgorithms = [ - "SHA-1", "SHA-256", "SHA-384", "SHA-512", - "shake128", "shake256", - "SHA3-256", "SHA3-384", "SHA3-512"]; - - public async onGenerateKey(algorithm: RsaHashedKeyGenParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const keys = await RsaCrypto.generateKey( - { - ...algorithm, - name: this.name, - }, - extractable, - keyUsages); - - return { - privateKey: setCryptoKey(keys.privateKey as RsaPrivateKey), - publicKey: setCryptoKey(keys.publicKey as RsaPublicKey), - }; - } - - public async onSign(algorithm: Algorithm, key: RsaPrivateKey, data: ArrayBuffer): Promise { - return RsaCrypto.sign(algorithm, getCryptoKey(key) as RsaPrivateKey, new Uint8Array(data)); - } - - public async onVerify(algorithm: Algorithm, key: RsaPublicKey, signature: ArrayBuffer, data: ArrayBuffer): Promise { - return RsaCrypto.verify(algorithm, getCryptoKey(key) as RsaPublicKey, new Uint8Array(signature), new Uint8Array(data)); - } - - public async onExportKey(format: KeyFormat, key: CryptoKey): Promise { - return RsaCrypto.exportKey(format, getCryptoKey(key)); - } - - public async onImportKey(format: KeyFormat, keyData: JsonWebKey | ArrayBuffer, algorithm: RsaHashedImportParams, extractable: boolean, keyUsages: KeyUsage[]): Promise { - const key = await RsaCrypto.importKey(format, keyData, {...algorithm, name: this.name}, extractable, keyUsages); - return setCryptoKey(key); - } - - public override checkCryptoKey(key: CryptoKey, keyUsage?: KeyUsage) { - super.checkCryptoKey(key, keyUsage); - const internalKey = getCryptoKey(key); - if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { - throw new TypeError("key: Is not RSA CryptoKey"); - } - } - -} diff --git a/src/mechs/sha/sha3_256.ts b/src/mechs/sha/sha3_256.ts deleted file mode 100644 index 907ec60..0000000 --- a/src/mechs/sha/sha3_256.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha3256Provider extends core.ProviderCrypto { - public name = "SHA3-256"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha3_384.ts b/src/mechs/sha/sha3_384.ts deleted file mode 100644 index 169a605..0000000 --- a/src/mechs/sha/sha3_384.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha3384Provider extends core.ProviderCrypto { - public name = "SHA3-384"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha3_512.ts b/src/mechs/sha/sha3_512.ts deleted file mode 100644 index 8b10713..0000000 --- a/src/mechs/sha/sha3_512.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha3512Provider extends core.ProviderCrypto { - public name = "SHA3-512"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha_1.ts b/src/mechs/sha/sha_1.ts deleted file mode 100644 index 1c56b58..0000000 --- a/src/mechs/sha/sha_1.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha1Provider extends core.ProviderCrypto { - public name = "SHA-1"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha_256.ts b/src/mechs/sha/sha_256.ts deleted file mode 100644 index 6067dbe..0000000 --- a/src/mechs/sha/sha_256.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha256Provider extends core.ProviderCrypto { - public name = "SHA-256"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha_384.ts b/src/mechs/sha/sha_384.ts deleted file mode 100644 index b82462d..0000000 --- a/src/mechs/sha/sha_384.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha384Provider extends core.ProviderCrypto { - public name = "SHA-384"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/src/mechs/sha/sha_512.ts b/src/mechs/sha/sha_512.ts deleted file mode 100644 index 06e09da..0000000 --- a/src/mechs/sha/sha_512.ts +++ /dev/null @@ -1,12 +0,0 @@ -import * as core from "webcrypto-core"; -import { ShaCrypto } from "./crypto"; - -export class Sha512Provider extends core.ProviderCrypto { - public name = "SHA-512"; - public usages = []; - - public override async onDigest(algorithm: Algorithm, data: ArrayBuffer): Promise { - return ShaCrypto.digest(algorithm, data); - } - -} diff --git a/tsconfig.compile.json b/tsconfig.compile.json new file mode 100644 index 0000000..7ea1b8e --- /dev/null +++ b/tsconfig.compile.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "target": "ES2019", + "module": "CommonJS", + "lib": [ + "ES2019" + ], + "moduleResolution": "node", + "importHelpers": true, + "strict": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "noImplicitOverride": true, + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 806f4a3..af1db7e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,23 @@ { + "extends": "./tsconfig.compile.json", "compilerOptions": { - "target": "es2019", - "module": "commonjs", - "lib": [ - "dom" - ], - "removeComments": true, - "importHelpers": true, - "strict": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "noImplicitOverride": true - }, - "exclude": [ - "build/**/*", - "index.d.ts" - ] + "baseUrl": ".", + "paths": { + "@peculiar/webcrypto-types": [ + "./packages/types/src" + ], + "@peculiar/webcrypto-core": [ + "./packages/core/src" + ], + "@peculiar/webcrypto": [ + "./packages/node/src" + ], + "@peculiar/webcrypto-test": [ + "./packages/test/src" + ], + "@peculiar/webcrypto-pkcs11": [ + "./packages/pkcs11/src" + ], + } + } } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 2078b4c..2efcb7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,204 +2,35 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.1.0": - version "2.1.2" - resolved "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.1.2.tgz" - integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg== - dependencies: - "@jridgewell/trace-mapping" "^0.3.0" - "@babel/code-frame@^7.16.7": version "7.16.7" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.16.7.tgz" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789" integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg== dependencies: "@babel/highlight" "^7.16.7" -"@babel/compat-data@^7.16.4": - version "7.17.0" - resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.17.0.tgz" - integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng== - -"@babel/core@^7.7.5": - version "7.17.5" - resolved "https://registry.npmjs.org/@babel/core/-/core-7.17.5.tgz" - integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA== - dependencies: - "@ampproject/remapping" "^2.1.0" - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-compilation-targets" "^7.16.7" - "@babel/helper-module-transforms" "^7.16.7" - "@babel/helpers" "^7.17.2" - "@babel/parser" "^7.17.3" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - convert-source-map "^1.7.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.1.2" - semver "^6.3.0" - -"@babel/generator@^7.17.3": - version "7.17.3" - resolved "https://registry.npmjs.org/@babel/generator/-/generator-7.17.3.tgz" - integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg== - dependencies: - "@babel/types" "^7.17.0" - jsesc "^2.5.1" - source-map "^0.5.0" - -"@babel/helper-compilation-targets@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz" - integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA== - dependencies: - "@babel/compat-data" "^7.16.4" - "@babel/helper-validator-option" "^7.16.7" - browserslist "^4.17.5" - semver "^6.3.0" - -"@babel/helper-environment-visitor@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz" - integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-function-name@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz" - integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA== - dependencies: - "@babel/helper-get-function-arity" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/helper-get-function-arity@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz" - integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-hoist-variables@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz" - integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-imports@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz" - integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-module-transforms@^7.16.7": - version "7.17.6" - resolved "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz" - integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA== - dependencies: - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-module-imports" "^7.16.7" - "@babel/helper-simple-access" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/helper-validator-identifier" "^7.16.7" - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.3" - "@babel/types" "^7.17.0" - -"@babel/helper-simple-access@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz" - integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g== - dependencies: - "@babel/types" "^7.16.7" - -"@babel/helper-split-export-declaration@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz" - integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw== - dependencies: - "@babel/types" "^7.16.7" - "@babel/helper-validator-identifier@^7.16.7": version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad" integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw== -"@babel/helper-validator-option@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz" - integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ== - -"@babel/helpers@^7.17.2": - version "7.17.2" - resolved "https://registry.npmjs.org/@babel/helpers/-/helpers-7.17.2.tgz" - integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ== - dependencies: - "@babel/template" "^7.16.7" - "@babel/traverse" "^7.17.0" - "@babel/types" "^7.17.0" - "@babel/highlight@^7.16.7": - version "7.16.10" - resolved "https://registry.npmjs.org/@babel/highlight/-/highlight-7.16.10.tgz" - integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw== + version "7.17.12" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351" + integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg== dependencies: "@babel/helper-validator-identifier" "^7.16.7" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.16.7", "@babel/parser@^7.17.3": - version "7.17.3" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.17.3.tgz" - integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA== - -"@babel/template@^7.16.7": - version "7.16.7" - resolved "https://registry.npmjs.org/@babel/template/-/template-7.16.7.tgz" - integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/parser" "^7.16.7" - "@babel/types" "^7.16.7" - -"@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3": - version "7.17.3" - resolved "https://registry.npmjs.org/@babel/traverse/-/traverse-7.17.3.tgz" - integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw== - dependencies: - "@babel/code-frame" "^7.16.7" - "@babel/generator" "^7.17.3" - "@babel/helper-environment-visitor" "^7.16.7" - "@babel/helper-function-name" "^7.16.7" - "@babel/helper-hoist-variables" "^7.16.7" - "@babel/helper-split-export-declaration" "^7.16.7" - "@babel/parser" "^7.17.3" - "@babel/types" "^7.17.0" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/types@^7.16.7", "@babel/types@^7.17.0": - version "7.17.0" - resolved "https://registry.npmjs.org/@babel/types/-/types-7.17.0.tgz" - integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw== - dependencies: - "@babel/helper-validator-identifier" "^7.16.7" - to-fast-properties "^2.0.0" - "@cspotcode/source-map-consumer@0.8.0": version "0.8.0" - resolved "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b" integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg== "@cspotcode/source-map-support@0.7.0": version "0.7.0" - resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5" integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA== dependencies: "@cspotcode/source-map-consumer" "0.8.0" @@ -221,7 +52,7 @@ "@humanwhocodes/config-array@^0.9.2": version "0.9.5" - resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7" integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw== dependencies: "@humanwhocodes/object-schema" "^1.2.1" @@ -230,46 +61,12 @@ "@humanwhocodes/object-schema@^1.2.1": version "1.2.1" - resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== -"@istanbuljs/load-nyc-config@^1.0.0": - version "1.1.0" - resolved "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz" - integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== - dependencies: - camelcase "^5.3.1" - find-up "^4.1.0" - get-package-type "^0.1.0" - js-yaml "^3.13.1" - resolve-from "^5.0.0" - -"@istanbuljs/schema@^0.1.2": - version "0.1.3" - resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" - integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== - -"@jridgewell/resolve-uri@^3.0.3": - version "3.0.5" - resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz" - integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew== - -"@jridgewell/sourcemap-codec@^1.4.10": - version "1.4.11" - resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz" - integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg== - -"@jridgewell/trace-mapping@^0.3.0": - version "0.3.4" - resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz" - integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ== - dependencies: - "@jridgewell/resolve-uri" "^3.0.3" - "@jridgewell/sourcemap-codec" "^1.4.10" - "@nodelib/fs.scandir@2.1.5": version "2.1.5" - resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: "@nodelib/fs.stat" "2.0.5" @@ -277,182 +74,174 @@ "@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": version "2.0.5" - resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": version "1.2.8" - resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== dependencies: "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@peculiar/asn1-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.1.6.tgz#f587f1d8907c7a2180e5e1ce6b4831bf78d7560a" - integrity sha512-6ewdxD32vsjxbI/MvTef7PQxZIfLyV4w/5XzjOkosIGNt726zj8evLitCbjTeMHSZ/VeU4ZFSnrPXdCBHI6NWQ== +"@peculiar/asn1-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.1.7.tgz#17d9b79f7df748ef84158ea61a24fc11d9f3f4d9" + integrity sha512-RxnHrl7WgNxWPsGeSw7YUGTS3s5En7JwhdOilRpEShQJQ9TH8v1nZtslyZGX5GxgUJ1P4dnRsCnt7R5EYmvtUg== dependencies: - asn1js "^3.0.0" + asn1js "^3.0.3" pvtsutils "^1.3.2" tslib "^2.4.0" "@peculiar/json-schema@^1.1.12": version "1.1.12" - resolved "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== dependencies: tslib "^2.0.0" -"@peculiar/webcrypto-test@^1.0.7": - version "1.0.7" - resolved "https://registry.npmjs.org/@peculiar/webcrypto-test/-/webcrypto-test-1.0.7.tgz" - integrity sha512-dJCHiNvdqZy6vWujhOxqNDlsP1226eXAZ8i1xkcNRdFiavfAgvRlRU8guNnb3DWolzzSJ8M9HOp3nk3P1RIYlQ== - dependencies: - pvtsutils "^1.0.14" - tslib "^2.0.1" - "@rollup/pluginutils@^4.1.2": - version "4.1.2" - resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.1.2.tgz" - integrity sha512-ROn4qvkxP9SyPeHaf7uQC/GPFY6L/OWy9+bd9AwcjOAWQwxRscoEyAUD8qCY5o5iL4jqQwoLk2kaTKJPb/HwzQ== + version "4.2.1" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" + integrity sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ== dependencies: estree-walker "^2.0.1" picomatch "^2.2.2" "@tsconfig/node10@^1.0.7": version "1.0.8" - resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== "@tsconfig/node12@^1.0.7": version "1.0.9" - resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== "@tsconfig/node14@^1.0.0": version "1.0.1" - resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== "@tsconfig/node16@^1.0.2": version "1.0.2" - resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.2.tgz#423c77877d0569db20e1fc80885ac4118314010e" integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA== "@types/json-schema@^7.0.9": - version "7.0.10" - resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.10.tgz" - integrity sha512-BLO9bBq59vW3fxCpD4o0N4U+DXsvwvIcl+jofw0frQo/GrBFC+/jRZj1E7kgp6dvTyNmA4y6JCV5Id/r3mNP5A== + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/json5@^0.0.29": version "0.0.29" - resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz" - integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== "@types/mocha@^9.1.1": version "9.1.1" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== -"@types/node@^17.0.32": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.32.tgz#51d59d7a90ef2d0ae961791e0900cad2393a0149" - integrity sha512-eAIcfAvhf/BkHcf4pkLJ7ECpBAhh9kcxRBpip9cTiO+hf+aJrsxYxBeS6OXvOd9WqNAJmavXVpZvY1rBjNsXmw== +"@types/node@*", "@types/node@^17.0.27": + version "17.0.34" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.34.tgz#3b0b6a50ff797280b8d000c6281d229f9c538cef" + integrity sha512-XImEz7XwTvDBtzlTnm8YvMqGW/ErMWBsKZ+hMTvnDIjGCKxwK5Xpc+c/oQjOauwq8M4OS11hEkpjX8rrI/eEgA== -"@typescript-eslint/eslint-plugin@^5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.23.0.tgz#bc4cbcf91fbbcc2e47e534774781b82ae25cc3d8" - integrity sha512-hEcSmG4XodSLiAp1uxv/OQSGsDY6QN3TcRU32gANp+19wGE1QQZLRS8/GV58VRUoXhnkuJ3ZxNQ3T6Z6zM59DA== +"@typescript-eslint/eslint-plugin@^5.21.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.25.0.tgz#e8ce050990e4d36cc200f2de71ca0d3eb5e77a31" + integrity sha512-icYrFnUzvm+LhW0QeJNKkezBu6tJs9p/53dpPLFH8zoM9w1tfaKzVurkPotEpAqQ8Vf8uaFyL5jHd0Vs6Z0ZQg== dependencies: - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/type-utils" "5.23.0" - "@typescript-eslint/utils" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/scope-manager" "5.25.0" + "@typescript-eslint/type-utils" "5.25.0" + "@typescript-eslint/utils" "5.25.0" + debug "^4.3.4" functional-red-black-tree "^1.0.1" - ignore "^5.1.8" + ignore "^5.2.0" regexpp "^3.2.0" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/parser@^5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.23.0.tgz#443778e1afc9a8ff180f91b5e260ac3bec5e2de1" - integrity sha512-V06cYUkqcGqpFjb8ttVgzNF53tgbB/KoQT/iB++DOIExKmzI9vBJKjZKt/6FuV9c+zrDsvJKbJ2DOCYwX91cbw== +"@typescript-eslint/parser@^5.21.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.25.0.tgz#fb533487147b4b9efd999a4d2da0b6c263b64f7f" + integrity sha512-r3hwrOWYbNKP1nTcIw/aZoH+8bBnh/Lh1iDHoFpyG4DnCpvEdctrSl6LOo19fZbzypjQMHdajolxs6VpYoChgA== dependencies: - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/typescript-estree" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/scope-manager" "5.25.0" + "@typescript-eslint/types" "5.25.0" + "@typescript-eslint/typescript-estree" "5.25.0" + debug "^4.3.4" -"@typescript-eslint/scope-manager@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.23.0.tgz#4305e61c2c8e3cfa3787d30f54e79430cc17ce1b" - integrity sha512-EhjaFELQHCRb5wTwlGsNMvzK9b8Oco4aYNleeDlNuL6qXWDF47ch4EhVNPh8Rdhf9tmqbN4sWDk/8g+Z/J8JVw== +"@typescript-eslint/scope-manager@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.25.0.tgz#e78f1484bca7e484c48782075219c82c6b77a09f" + integrity sha512-p4SKTFWj+2VpreUZ5xMQsBMDdQ9XdRvODKXN4EksyBjFp2YvQdLkyHqOffakYZPuWJUDNu3jVXtHALDyTv3cww== dependencies: - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/visitor-keys" "5.23.0" + "@typescript-eslint/types" "5.25.0" + "@typescript-eslint/visitor-keys" "5.25.0" -"@typescript-eslint/type-utils@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.23.0.tgz#f852252f2fc27620d5bb279d8fed2a13d2e3685e" - integrity sha512-iuI05JsJl/SUnOTXA9f4oI+/4qS/Zcgk+s2ir+lRmXI+80D8GaGwoUqs4p+X+4AxDolPpEpVUdlEH4ADxFy4gw== +"@typescript-eslint/type-utils@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.25.0.tgz#5750d26a5db4c4d68d511611e0ada04e56f613bc" + integrity sha512-B6nb3GK3Gv1Rsb2pqalebe/RyQoyG/WDy9yhj8EE0Ikds4Xa8RR28nHz+wlt4tMZk5bnAr0f3oC8TuDAd5CPrw== dependencies: - "@typescript-eslint/utils" "5.23.0" - debug "^4.3.2" + "@typescript-eslint/utils" "5.25.0" + debug "^4.3.4" tsutils "^3.21.0" -"@typescript-eslint/types@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.23.0.tgz#8733de0f58ae0ed318dbdd8f09868cdbf9f9ad09" - integrity sha512-NfBsV/h4dir/8mJwdZz7JFibaKC3E/QdeMEDJhiAE3/eMkoniZ7MjbEMCGXw6MZnZDMN3G9S0mH/6WUIj91dmw== +"@typescript-eslint/types@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.25.0.tgz#dee51b1855788b24a2eceeae54e4adb89b088dd8" + integrity sha512-7fWqfxr0KNHj75PFqlGX24gWjdV/FDBABXL5dyvBOWHpACGyveok8Uj4ipPX/1fGU63fBkzSIycEje4XsOxUFA== -"@typescript-eslint/typescript-estree@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.23.0.tgz#dca5f10a0a85226db0796e8ad86addc9aee52065" - integrity sha512-xE9e0lrHhI647SlGMl+m+3E3CKPF1wzvvOEWnuE3CCjjT7UiRnDGJxmAcVKJIlFgK6DY9RB98eLr1OPigPEOGg== +"@typescript-eslint/typescript-estree@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.25.0.tgz#a7ab40d32eb944e3fb5b4e3646e81b1bcdd63e00" + integrity sha512-MrPODKDych/oWs/71LCnuO7NyR681HuBly2uLnX3r5i4ME7q/yBqC4hW33kmxtuauLTM0OuBOhhkFaxCCOjEEw== dependencies: - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/visitor-keys" "5.23.0" - debug "^4.3.2" - globby "^11.0.4" + "@typescript-eslint/types" "5.25.0" + "@typescript-eslint/visitor-keys" "5.25.0" + debug "^4.3.4" + globby "^11.1.0" is-glob "^4.0.3" - semver "^7.3.5" + semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/utils@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.23.0.tgz#4691c3d1b414da2c53d8943310df36ab1c50648a" - integrity sha512-dbgaKN21drqpkbbedGMNPCtRPZo1IOUr5EI9Jrrh99r5UW5Q0dz46RKXeSBoPV+56R6dFKpbrdhgUNSJsDDRZA== +"@typescript-eslint/utils@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.25.0.tgz#272751fd737733294b4ab95e16c7f2d4a75c2049" + integrity sha512-qNC9bhnz/n9Kba3yI6HQgQdBLuxDoMgdjzdhSInZh6NaDnFpTUlwNGxplUFWfY260Ya0TRPvkg9dd57qxrJI9g== dependencies: "@types/json-schema" "^7.0.9" - "@typescript-eslint/scope-manager" "5.23.0" - "@typescript-eslint/types" "5.23.0" - "@typescript-eslint/typescript-estree" "5.23.0" + "@typescript-eslint/scope-manager" "5.25.0" + "@typescript-eslint/types" "5.25.0" + "@typescript-eslint/typescript-estree" "5.25.0" eslint-scope "^5.1.1" eslint-utils "^3.0.0" -"@typescript-eslint/visitor-keys@5.23.0": - version "5.23.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.23.0.tgz#057c60a7ca64667a39f991473059377a8067c87b" - integrity sha512-Vd4mFNchU62sJB8pX19ZSPog05B0Y0CE2UxAZPT5k4iqhRYjPnqyY3woMxCd0++t9OTqkgjST+1ydLBi7e2Fvg== +"@typescript-eslint/visitor-keys@5.25.0": + version "5.25.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.25.0.tgz#33aa5fdcc5cedb9f4c8828c6a019d58548d4474b" + integrity sha512-yd26vFgMsC4h2dgX4+LR+GeicSKIfUvZREFLf3DDjZPtqgLx5AJZr6TetMNwFP9hcKreTTeztQYBTNbNoOycwA== dependencies: - "@typescript-eslint/types" "5.23.0" - eslint-visitor-keys "^3.0.0" + "@typescript-eslint/types" "5.25.0" + eslint-visitor-keys "^3.3.0" "@ungap/promise-all-settled@1.1.2": version "1.1.2" - resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== "@yarn-tool/resolve-package@^1.0.40": - version "1.0.45" - resolved "https://registry.npmjs.org/@yarn-tool/resolve-package/-/resolve-package-1.0.45.tgz" - integrity sha512-xnfY8JceApkSTliZtr7X6yl1wZYhGbRp0beBMi1OtmvTVTm/ZSt3881Fw1M3ZwhHqr7OEfl8828LJK2q62BvoQ== + version "1.0.47" + resolved "https://registry.yarnpkg.com/@yarn-tool/resolve-package/-/resolve-package-1.0.47.tgz#8ec25f291a316280a281632331e88926a66fdf19" + integrity sha512-Zaw58gQxjQceJqhqybJi1oUDaORT8i2GTgwICPs8v/X/Pkx35FXQba69ldHVg5pQZ6YLKpROXgyHvBaCJOFXiA== dependencies: pkg-dir "< 6 >= 5" - tslib "^2.3.1" - upath2 "^3.1.12" + tslib "^2" + upath2 "^3.1.13" acorn-jsx@^5.3.2: version "5.3.2" @@ -461,7 +250,7 @@ acorn-jsx@^5.3.2: acorn-walk@^8.1.1: version "8.2.0" - resolved "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== acorn@^8.4.1, acorn@^8.7.1: @@ -469,17 +258,9 @@ acorn@^8.4.1, acorn@^8.7.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30" integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A== -aggregate-error@^3.0.0: - version "3.1.0" - resolved "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz" - integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - -ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" - resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" @@ -489,227 +270,103 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4: ansi-colors@4.1.1: version "4.1.1" - resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-regex@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== ansi-styles@^3.2.1: version "3.2.1" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" - resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" anymatch@~3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" -append-transform@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz" - integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== - dependencies: - default-require-extensions "^3.0.0" - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - arg@^4.1.0: version "4.1.3" - resolved "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - argparse@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -array-includes@^3.1.4: - version "3.1.4" - resolved "https://registry.npmjs.org/array-includes/-/array-includes-3.1.4.tgz" - integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - get-intrinsic "^1.1.1" - is-string "^1.0.7" - array-union@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.flat@^1.2.5: - version "1.2.5" - resolved "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz" - integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - -asn1@~0.2.3: - version "0.2.6" - resolved "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz" - integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ== - dependencies: - safer-buffer "~2.1.0" - -asn1js@^3.0.0, asn1js@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.1.tgz#b9657f6377eaf1fa3c4f9a52f49c12ae9322b1b1" - integrity sha512-7RX/y1foVCz6QXITV3IycqP7FMAC/gbd680gHpO5xGWn8vri1mCJxRJuMFmmkXDQt2/ToeYAcf8VrkNu2cLW+A== +asn1js@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.3.tgz#fbecdcced2c046552db0c63af284eccc494e0e74" + integrity sha512-Oz62ld3K3n6KlRUr4iZSMbSFDDPCW84G1yX7b/gWK5a0Ka7ZYOmCxFpu91lFdQygkBi2Hgoft1/WxRqFrONqLA== dependencies: pvtsutils "^1.3.2" pvutils "^1.1.3" tslib "^2.4.0" -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.11.0" - resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" - integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== - balanced-match@^1.0.0: version "1.0.2" - resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - binary-extensions@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== brace-expansion@^1.1.7: version "1.1.11" - resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" browser-stdout@1.3.1: version "1.3.1" - resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -browserslist@^4.17.5: - version "4.19.3" - resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.19.3.tgz" - integrity sha512-XK3X4xtKJ+Txj8G5c30B4gsm71s69lqXlkYui4s6EkKxuv49qjYlY6oVd+IFJ73d4YymtM3+djvvt/R/iJwwDg== - dependencies: - caniuse-lite "^1.0.30001312" - electron-to-chromium "^1.4.71" - escalade "^3.1.1" - node-releases "^2.0.2" - picocolors "^1.0.0" - -caching-transform@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz" - integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== - dependencies: - hasha "^5.0.0" - make-dir "^3.0.0" - package-hash "^4.0.0" - write-file-atomic "^3.0.0" - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - callsites@^3.0.0: version "3.1.0" - resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - camelcase@^6.0.0: version "6.3.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001312: - version "1.0.30001312" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001312.tgz" - integrity sha512-Wiz1Psk2MEK0pX3rUzWaunLTZzqS2JYZFzNKqAiJGiuxIjRPLgV6+VDPOg6lQOUxmDwhTlh198JsTTi8Hzw6aQ== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - chalk@^2.0.0: version "2.4.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" @@ -718,7 +375,7 @@ chalk@^2.0.0: chalk@^4.0.0, chalk@^4.1.0: version "4.1.2" - resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== dependencies: ansi-styles "^4.1.0" @@ -726,7 +383,7 @@ chalk@^4.0.0, chalk@^4.1.0: chokidar@3.5.3: version "3.5.3" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" @@ -739,23 +396,9 @@ chokidar@3.5.3: optionalDependencies: fsevents "~2.3.2" -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - cliui@^7.0.2: version "7.0.4" - resolved "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== dependencies: string-width "^4.2.0" @@ -764,286 +407,123 @@ cliui@^7.0.2: color-convert@^1.9.0: version "1.9.3" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-convert@^2.0.1: version "2.0.1" - resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== dependencies: color-name "~1.1.4" color-name@1.1.3: version "1.1.3" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= color-name@~1.1.4: version "1.1.4" - resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - commondir@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= concat-map@0.0.1: version "0.0.1" - resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -coveralls@^3.1.1: - version "3.1.1" - resolved "https://registry.npmjs.org/coveralls/-/coveralls-3.1.1.tgz" - integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== - dependencies: - js-yaml "^3.13.1" - lcov-parse "^1.0.0" - log-driver "^1.2.7" - minimist "^1.2.5" - request "^2.88.2" - create-require@^1.1.0: version "1.1.1" - resolved "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.0, cross-spawn@^7.0.2: +cross-spawn@^7.0.2: version "7.0.3" - resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: path-key "^3.1.0" shebang-command "^2.0.0" which "^2.0.1" -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= +debug@4.3.3: + version "4.3.3" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" + integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== dependencies: - assert-plus "^1.0.0" + ms "2.1.2" -debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -debug@^2.6.9: - version "2.6.9" - resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@^3.2.7: - version "3.2.7" - resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - decamelize@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== deep-is@^0.1.3: version "0.1.4" - resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -default-require-extensions@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz" - integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== - dependencies: - strip-bom "^4.0.0" - -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - diff@5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== diff@^4.0.1: version "4.0.2" - resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== dir-glob@^3.0.1: version "3.0.1" - resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== dependencies: path-type "^4.0.0" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - doctrine@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -electron-to-chromium@^1.4.71: - version "1.4.75" - resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.75.tgz" - integrity sha512-LxgUNeu3BVU7sXaKjUDD9xivocQLxFtq6wgERrutdY/yIOps3ODOZExK1jg8DTEg4U8TUCb5MLGeWFOYuxjF3Q== - emoji-regex@^8.0.0: version "8.0.0" - resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== -es-abstract@^1.19.0, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" - is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es6-error@^4.0.1: - version "4.1.1" - resolved "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz" - integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== - escalade@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-import-resolver-node@^0.3.6: - version "0.3.6" - resolved "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz" - integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw== - dependencies: - debug "^3.2.7" - resolve "^1.20.0" - -eslint-module-utils@^2.7.3: - version "2.7.3" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee" - integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ== - dependencies: - debug "^3.2.7" - find-up "^2.1.0" - -eslint-plugin-import@^2.26.0: - version "2.26.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b" - integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA== - dependencies: - array-includes "^3.1.4" - array.prototype.flat "^1.2.5" - debug "^2.6.9" - doctrine "^2.1.0" - eslint-import-resolver-node "^0.3.6" - eslint-module-utils "^2.7.3" - has "^1.0.3" - is-core-module "^2.8.1" - is-glob "^4.0.3" - minimatch "^3.1.2" - object.values "^1.1.5" - resolve "^1.22.0" - tsconfig-paths "^3.14.1" - eslint-scope@^5.1.1: version "5.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: esrecurse "^4.3.0" @@ -1051,7 +531,7 @@ eslint-scope@^5.1.1: eslint-scope@^7.1.1: version "7.1.1" - resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== dependencies: esrecurse "^4.3.0" @@ -1059,22 +539,22 @@ eslint-scope@^7.1.1: eslint-utils@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== dependencies: eslint-visitor-keys "^2.0.0" eslint-visitor-keys@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0: version "3.3.0" - resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== -eslint@^8.15.0: +eslint@^8.14.0: version "8.15.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.15.0.tgz#fea1d55a7062da48d82600d2e0974c55612a11e9" integrity sha512-GG5USZ1jhCu8HJkzGgeK8/+RGnHaNYZGrGDzUtigK3BsGESW/rs2az23XqE0WVwDxy1VRvvjSSGu5nB0Bu+6SA== @@ -1124,68 +604,48 @@ espree@^9.3.2: acorn-jsx "^5.3.2" eslint-visitor-keys "^3.3.0" -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - esquery@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== dependencies: estraverse "^5.1.0" esrecurse@^4.3.0: version "4.3.0" - resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: estraverse "^5.2.0" estraverse@^4.1.1: version "4.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== estraverse@^5.1.0, estraverse@^5.2.0: version "5.3.0" - resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== estree-walker@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== esutils@^2.0.2: version "2.0.3" - resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.1" - resolved "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz" - integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== - fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" - resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-glob@^3.2.9: version "3.2.11" - resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9" integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew== dependencies: "@nodelib/fs.stat" "^2.0.2" @@ -1196,38 +656,38 @@ fast-glob@^3.2.9: fast-json-stable-stringify@^2.0.0: version "2.1.0" - resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@^2.0.6: version "2.0.6" - resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= fastq@^1.6.0: version "1.13.0" - resolved "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== dependencies: reusify "^1.0.4" file-entry-cache@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== dependencies: flat-cache "^3.0.4" fill-range@^7.0.1: version "7.0.1" - resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== dependencies: to-regex-range "^5.0.1" -find-cache-dir@^3.2.0, find-cache-dir@^3.3.2: +find-cache-dir@^3.3.2: version "3.3.2" - resolved "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== dependencies: commondir "^1.0.1" @@ -1236,22 +696,15 @@ find-cache-dir@^3.2.0, find-cache-dir@^3.3.2: find-up@5.0.0, find-up@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== dependencies: locate-path "^6.0.0" path-exists "^4.0.0" -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.0.0: version "4.1.0" - resolved "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: locate-path "^5.0.0" @@ -1259,7 +712,7 @@ find-up@^4.0.0, find-up@^4.1.0: flat-cache@^3.0.4: version "3.0.4" - resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== dependencies: flatted "^3.1.0" @@ -1267,45 +720,18 @@ flat-cache@^3.0.4: flat@^5.0.2: version "5.0.2" - resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: version "3.2.5" - resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3" integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg== -foreground-child@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz" - integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== - dependencies: - cross-spawn "^7.0.0" - signal-exit "^3.0.2" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -fromentries@^1.2.0: - version "1.3.2" - resolved "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz" - integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== - fs-extra@^10.0.0: - version "10.0.1" - resolved "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz" - integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag== + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -1313,80 +739,46 @@ fs-extra@^10.0.0: fs.realpath@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@~2.3.2: version "2.3.2" - resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== function-bind@^1.1.1: version "1.1.1" - resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -gensync@^1.0.0-beta.2: - version "1.0.0-beta.2" - resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" - integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== - -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" - resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - -get-package-type@^0.1.0: - version "0.1.0" - resolved "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz" - integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" glob-parent@^6.0.1: version "6.0.2" - resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== dependencies: is-glob "^4.0.3" -glob@7.2.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.2.0: version "7.2.0" - resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: fs.realpath "^1.0.0" @@ -1396,21 +788,28 @@ glob@7.2.0, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" globals@^13.6.0, globals@^13.9.0: - version "13.12.1" - resolved "https://registry.npmjs.org/globals/-/globals-13.12.1.tgz" - integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw== + version "13.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac" + integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog== dependencies: type-fest "^0.20.2" -globby@^11.0.4: +globby@^11.1.0: version "11.1.0" - resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" @@ -1420,93 +819,54 @@ globby@^11.0.4: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.1.15, graceful-fs@^4.1.6, graceful-fs@^4.2.0: - version "4.2.9" - resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz" - integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== +graphene-pk11@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/graphene-pk11/-/graphene-pk11-2.3.0.tgz#4fd3d0ab6c633decd9d443a999c4a257a1650c8e" + integrity sha512-mgc3ux5yyJs0G5YAaO3hkNT4D86D1bPgLQH4ts2Wfn41braLAC2utlzB7R9bp4w9zPNPfJPXPb8mE8md/1BEZg== dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" + pkcs11js "^1.2.3" + tslib "^2.3.1" -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== has-flag@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-flag@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.3" - resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - has@^1.0.3: version "1.0.3" - resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" -hasha@^5.0.0: - version "5.2.2" - resolved "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz" - integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== - dependencies: - is-stream "^2.0.0" - type-fest "^0.8.0" - he@1.2.0: version "1.2.0" - resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -html-escaper@^2.0.0: - version "2.0.2" - resolved "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz" - integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -ignore@^5.1.8, ignore@^5.2.0: +ignore@^5.2.0: version "5.2.0" - resolved "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.3.0" - resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== dependencies: parent-module "^1.0.0" @@ -1514,17 +874,12 @@ import-fresh@^3.0.0, import-fresh@^3.2.1: imurmurhash@^0.1.4: version "0.1.4" - resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - inflight@^1.0.4: version "1.0.6" - resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -1532,359 +887,128 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - is-binary-path@~2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - is-core-module@^2.8.1: - version "2.8.1" - resolved "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz" - integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69" + integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A== dependencies: has "^1.0.3" -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-extglob@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" - resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== dependencies: is-extglob "^2.1.1" -is-negative-zero@^2.0.1: - version "2.0.2" - resolved "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - is-number@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== is-plain-obj@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== - -is-stream@^2.0.0: - version "2.0.1" - resolved "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz" - integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - is-unicode-supported@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -is-weakref@^1.0.1: - version "1.0.2" - resolved "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - isexe@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: - version "3.2.0" - resolved "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz" - integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== - -istanbul-lib-hook@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz" - integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== - dependencies: - append-transform "^2.0.0" - -istanbul-lib-instrument@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz" - integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== - dependencies: - "@babel/core" "^7.7.5" - "@istanbuljs/schema" "^0.1.2" - istanbul-lib-coverage "^3.0.0" - semver "^6.3.0" - -istanbul-lib-processinfo@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz" - integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== - dependencies: - archy "^1.0.0" - cross-spawn "^7.0.0" - istanbul-lib-coverage "^3.0.0-alpha.1" - make-dir "^3.0.0" - p-map "^3.0.0" - rimraf "^3.0.0" - uuid "^3.3.3" - -istanbul-lib-report@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz" - integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== - dependencies: - istanbul-lib-coverage "^3.0.0" - make-dir "^3.0.0" - supports-color "^7.1.0" - -istanbul-lib-source-maps@^4.0.0: - version "4.0.1" - resolved "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz" - integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - source-map "^0.6.1" - -istanbul-reports@^3.0.2: - version "3.1.4" - resolved "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz" - integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw== - dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - js-tokens@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@4.1.0, js-yaml@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== dependencies: argparse "^2.0.1" -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema@0.4.0: - version "0.4.0" - resolved "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz" - integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - json5@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" - jsonfile@^6.0.1: version "6.1.0" - resolved "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae" integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ== dependencies: universalify "^2.0.0" optionalDependencies: graceful-fs "^4.1.6" -jsprim@^1.2.2: - version "1.4.2" - resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz" - integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw== - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.4.0" - verror "1.10.0" - -lcov-parse@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/lcov-parse/-/lcov-parse-1.0.0.tgz" - integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= - levn@^0.4.1: version "0.4.1" - resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== dependencies: prelude-ls "^1.2.1" type-check "~0.4.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== dependencies: p-locate "^4.1.0" locate-path@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== dependencies: p-locate "^5.0.0" -lodash.flattendeep@^4.4.0: - version "4.4.0" - resolved "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz" - integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= - lodash.merge@^4.6.2: version "4.6.2" - resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -log-driver@^1.2.7: - version "1.2.7" - resolved "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz" - integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== - log-symbols@4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== dependencies: chalk "^4.1.0" @@ -1892,214 +1016,132 @@ log-symbols@4.1.0: lru-cache@^6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== dependencies: yallist "^4.0.0" -make-dir@^3.0.0, make-dir@^3.0.2: +magic-string@^0.26.1: + version "0.26.2" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.26.2.tgz#5331700e4158cd6befda738bb6b0c7b93c0d4432" + integrity sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A== + dependencies: + sourcemap-codec "^1.4.8" + +make-dir@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== dependencies: semver "^6.0.0" make-error@^1.1.1: version "1.3.6" - resolved "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" - resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.34" - resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +minimatch@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-4.2.1.tgz#40d9d511a46bdc4e563c22c3080cde9c0d8299b4" + integrity sha512-9Uq1ChtSZO+Mxa/CL1eGizn2vRn3MlLgzhT0Iz8zaY8NdvxvB0d5QdPFmCKf7JKA9Lerx5vRrnwO03jsSfGG9g== dependencies: - mime-db "1.51.0" + brace-expansion "^1.1.7" -minimatch@5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" - integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== - dependencies: - brace-expansion "^2.0.1" - -minimatch@^3.0.4, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" - resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6: +minimist@^1.2.0, minimist@^1.2.6: version "1.2.6" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== -mocha@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" - integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA== +mocha@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.2.tgz#d70db46bdb93ca57402c809333e5a84977a88fb9" + integrity sha512-L6XC3EdwT6YrIk0yXpavvLkn8h+EU+Y5UcCHKECyMbdUIxyMuZj4bX4U9e1nvnvUUvQVsV2VHQr5zLdcUkhW/g== dependencies: "@ungap/promise-all-settled" "1.1.2" ansi-colors "4.1.1" browser-stdout "1.3.1" chokidar "3.5.3" - debug "4.3.4" + debug "4.3.3" diff "5.0.0" escape-string-regexp "4.0.0" find-up "5.0.0" glob "7.2.0" + growl "1.10.5" he "1.2.0" js-yaml "4.1.0" log-symbols "4.1.0" - minimatch "5.0.1" + minimatch "4.2.1" ms "2.1.3" - nanoid "3.3.3" + nanoid "3.3.1" serialize-javascript "6.0.0" strip-json-comments "3.1.1" supports-color "8.1.1" - workerpool "6.2.1" + which "2.0.2" + workerpool "6.2.0" yargs "16.2.0" yargs-parser "20.2.4" yargs-unparser "2.0.0" -ms@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - ms@2.1.2: version "2.1.2" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3, ms@^2.1.1: +ms@2.1.3: version "2.1.3" - resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -nanoid@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" - integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== +nan@^2.15.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + +nanoid@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" + integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw== natural-compare@^1.4.0: version "1.4.0" - resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -node-preload@^0.2.1: - version "0.2.1" - resolved "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz" - integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== - dependencies: - process-on-spawn "^1.0.0" - -node-releases@^2.0.2: - version "2.0.2" - resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.2.tgz" - integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg== - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -nyc@^15.1.0: - version "15.1.0" - resolved "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz" - integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== - dependencies: - "@istanbuljs/load-nyc-config" "^1.0.0" - "@istanbuljs/schema" "^0.1.2" - caching-transform "^4.0.0" - convert-source-map "^1.7.0" - decamelize "^1.2.0" - find-cache-dir "^3.2.0" - find-up "^4.1.0" - foreground-child "^2.0.0" - get-package-type "^0.1.0" - glob "^7.1.6" - istanbul-lib-coverage "^3.0.0" - istanbul-lib-hook "^3.0.0" - istanbul-lib-instrument "^4.0.0" - istanbul-lib-processinfo "^2.0.2" - istanbul-lib-report "^3.0.0" - istanbul-lib-source-maps "^4.0.0" - istanbul-reports "^3.0.2" - make-dir "^3.0.0" - node-preload "^0.2.1" - p-map "^3.0.0" - process-on-spawn "^1.0.0" - resolve-from "^5.0.0" - rimraf "^3.0.0" - signal-exit "^3.0.2" - spawn-wrap "^2.0.0" - test-exclude "^6.0.0" - yargs "^15.0.2" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.12.0" - resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" - integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== - -object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.values@^1.1.5: - version "1.1.5" - resolved "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - once@^1.3.0: version "1.4.0" - resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" optionator@^0.9.1: version "0.9.1" - resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: deep-is "^0.1.3" @@ -2109,178 +1151,122 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.3" -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - p-limit@^2.2.0: version "2.3.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" p-limit@^3.0.2: version "3.1.0" - resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== dependencies: yocto-queue "^0.1.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^4.1.0: version "4.1.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== dependencies: p-limit "^2.2.0" p-locate@^5.0.0: version "5.0.0" - resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== dependencies: p-limit "^3.0.2" -p-map@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz" - integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== - dependencies: - aggregate-error "^3.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" - resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== -package-hash@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz" - integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== - dependencies: - graceful-fs "^4.1.15" - hasha "^5.0.0" - lodash.flattendeep "^4.4.0" - release-zalgo "^1.0.0" - parent-module@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - path-exists@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-network-drive@^1.0.13: - version "1.0.13" - resolved "https://registry.npmjs.org/path-is-network-drive/-/path-is-network-drive-1.0.13.tgz" - integrity sha512-Hg74mRN6mmXV+gTm3INjFK40ncAmC/Lo4qoQaSZ+GT3hZzlKdWQSqAjqyPeW0SvObP2W073WyYEBWY9d3wOm3A== +path-is-network-drive@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/path-is-network-drive/-/path-is-network-drive-1.0.15.tgz#305630eebb2c1324c2a94f098a99213bbe7eb4a3" + integrity sha512-bJGs1SxUne+q29P1xCLMkNBhMetku+vPN+yVQu8FGL/7diHesCSSIKoF4Wq42tcbwm7rK72XrGfK8FUXN00LLQ== dependencies: - tslib "^2.3.1" + tslib "^2" path-key@^3.1.0: version "3.1.1" - resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.7: version "1.0.7" - resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-strip-sep@^1.0.10: - version "1.0.10" - resolved "https://registry.npmjs.org/path-strip-sep/-/path-strip-sep-1.0.10.tgz" - integrity sha512-JpCy+8LAJQQTO1bQsb/84s1g+/Stm3h39aOpPRBQ/paMUGVPPZChLTOTKHoaCkc/6sKuF7yVsnq5Pe1S6xQGcA== +path-strip-sep@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/path-strip-sep/-/path-strip-sep-1.0.12.tgz#e395568764c3a21eb7e879d7573a6eb4619e8bcf" + integrity sha512-EJZSC5WBjVlA9XHLCiluiyisYg6yzeMJ4nY3BQVCuedyEHA/I2crcHWdwuQ74h3V599U9nEbEZUTvvSxOK3vbQ== dependencies: - tslib "^2.3.1" + tslib "^2" path-type@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" - resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pkcs11js@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pkcs11js/-/pkcs11js-1.3.0.tgz#7df841051a17c053723fa66758ab6a82bca32ef7" + integrity sha512-owI+M6Gpw0cEU47cTt2eWQs4Iqm9zRyobiJ0q37wIgOrK8BcXVuRM3eVGH58QxYWhItMcRiEBUTE8HUHZX+beQ== + dependencies: + nan "^2.15.0" + "pkg-dir@< 6 >= 5": version "5.0.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== dependencies: find-up "^5.0.0" pkg-dir@^4.1.0: version "4.2.0" - resolved "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: find-up "^4.0.0" prelude-ls@^1.2.1: version "1.2.1" - resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== -process-on-spawn@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz" - integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== - dependencies: - fromentries "^1.2.0" - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -punycode@^2.1.0, punycode@^2.1.1: +punycode@^2.1.0: version "2.1.1" - resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== -pvtsutils@^1.0.14, pvtsutils@^1.3.2: +pvtsutils@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.2.tgz#9f8570d132cdd3c27ab7d51a2799239bf8d8d5de" integrity sha512-+Ipe2iNUyrZz+8K/2IOo+kKikdtfhRKzNpQbruF2URmqPtoqAs8g3xS7TJvFF2GcPXjh7DkqMnpVveRFq4PgEQ== @@ -2292,91 +1278,43 @@ pvutils@^1.1.3: resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== -qs@~6.5.2: - version "6.5.3" - resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz" - integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA== - queue-microtask@^1.2.2: version "1.2.3" - resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== randombytes@^2.1.0: version "2.1.0" - resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: safe-buffer "^5.1.0" readdirp@~3.6.0: version "3.6.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" regexpp@^3.2.0: version "3.2.0" - resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -release-zalgo@^1.0.0: - version "1.0.0" - resolved "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz" - integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= - dependencies: - es6-error "^4.0.1" - -request@^2.88.2: - version "2.88.2" - resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - require-directory@^2.1.1: version "2.1.1" - resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - resolve-from@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.20.0, resolve@^1.22.0: +resolve@^1.20.0: version "1.22.0" - resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== dependencies: is-core-module "^2.8.1" @@ -2385,19 +1323,28 @@ resolve@^1.20.0, resolve@^1.22.0: reusify@^1.0.4: version "1.0.4" - resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^3.0.0, rimraf@^3.0.2: +rimraf@^3.0.2: version "3.0.2" - resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== dependencies: glob "^7.1.3" +rollup-plugin-dts@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-4.2.1.tgz#c17968a0f7c5ae70a9e0ab37e715f3ef63da01c7" + integrity sha512-eaxQZNUJ5iQcxNGlpJ1CUgG4OSVqWjDZ3nNSWBIoGrpcote2aNphSe1RJOaSYkb8dwn3o+rYm1vvld/5z3EGSQ== + dependencies: + magic-string "^0.26.1" + optionalDependencies: + "@babel/code-frame" "^7.16.7" + rollup-plugin-typescript2@^0.31.2: version "0.31.2" - resolved "https://registry.npmjs.org/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz" + resolved "https://registry.yarnpkg.com/rollup-plugin-typescript2/-/rollup-plugin-typescript2-0.31.2.tgz#463aa713a7e2bf85b92860094b9f7fb274c5a4d8" integrity sha512-hRwEYR1C8xDGVVMFJQdEVnNAeWRvpaY97g5mp3IeLnzhNXzSVq78Ye/BJ9PAaUfN4DXa/uDnqerifMOaMFY54Q== dependencies: "@rollup/pluginutils" "^4.1.2" @@ -2407,242 +1354,133 @@ rollup-plugin-typescript2@^0.31.2: resolve "^1.20.0" tslib "^2.3.1" -rollup@^2.72.1: - version "2.72.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.72.1.tgz#861c94790537b10008f0ca0fbc60e631aabdd045" - integrity sha512-NTc5UGy/NWFGpSqF1lFY8z9Adri6uhyMLI6LvPAXdBKoPRFhIIiBUpt+Qg2awixqO3xvzSijjhnb4+QEZwJmxA== +rollup@^2.70.2: + version "2.73.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.73.0.tgz#128fef4b333fd92d02d6929afbb6ee38d7feb32d" + integrity sha512-h/UngC3S4Zt28mB3g0+2YCMegT5yoftnQplwzPqGZcKvlld5e+kT/QRmJiL+qxGyZKOYpgirWGdLyEO1b0dpLQ== optionalDependencies: fsevents "~2.3.2" run-parallel@^1.1.9: version "1.2.0" - resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== dependencies: queue-microtask "^1.2.2" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2: +safe-buffer@^5.1.0: version "5.2.1" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@^6.0.0, semver@^6.3.0: +semver@^6.0.0: version "6.3.0" - resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.3.5: - version "7.3.5" - resolved "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== dependencies: lru-cache "^6.0.0" serialize-javascript@6.0.0: version "6.0.0" - resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== dependencies: randombytes "^2.1.0" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - shebang-command@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: shebang-regex "^3.0.0" shebang-regex@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - slash@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -source-map@^0.5.0: - version "0.5.7" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.1: - version "0.6.1" - resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -spawn-wrap@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz" - integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== - dependencies: - foreground-child "^2.0.0" - is-windows "^1.0.2" - make-dir "^3.0.0" - rimraf "^3.0.0" - signal-exit "^3.0.2" - which "^2.0.1" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.17.0" - resolved "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz" - integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" +sourcemap-codec@^1.4.8: + version "1.4.8" + resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" + integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== string-width@^4.1.0, string-width@^4.2.0: version "4.2.3" - resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== dependencies: emoji-regex "^8.0.0" is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" - resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" strip-bom@^3.0.0: version "3.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= -strip-bom@^4.0.0: - version "4.0.0" - resolved "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz" - integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== - strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== supports-color@8.1.1: version "8.1.1" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: has-flag "^4.0.0" supports-color@^5.3.0: version "5.5.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" supports-color@^7.1.0: version "7.2.0" - resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" - resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== -test-exclude@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz" - integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== - dependencies: - "@istanbuljs/schema" "^0.1.2" - glob "^7.1.4" - minimatch "^3.0.4" - text-table@^0.2.0: version "0.2.0" - resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - to-regex-range@^5.0.1: version "5.0.1" - resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== dependencies: is-number "^7.0.0" -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - ts-node@^10.7.0: version "10.7.0" - resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.7.0.tgz" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5" integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A== dependencies: "@cspotcode/source-map-support" "0.7.0" @@ -2671,173 +1509,90 @@ tsconfig-paths@^3.14.1: tslib@^1.8.1: version "1.14.1" - resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.0.1, tslib@^2.3.1, tslib@^2.4.0: +tslib@^2, tslib@^2.0.0, tslib@^2.3.1, tslib@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== tsutils@^3.21.0: version "3.21.0" - resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" - resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== dependencies: prelude-ls "^1.2.1" type-fest@^0.20.2: version "0.20.2" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-fest@^0.8.0: - version "0.8.1" - resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz" - integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typescript@^4.6.4: +typescript@^4.6.3: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg== -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" - universalify@^2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717" integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ== -upath2@^3.1.12: - version "3.1.12" - resolved "https://registry.npmjs.org/upath2/-/upath2-3.1.12.tgz" - integrity sha512-yC3eZeCyCXFWjy7Nu4pgjLhXNYjuzuUmJiRgSSw6TJp8Emc+E4951HGPJf+bldFC5SL7oBLeNbtm1fGzXn2gxw== +upath2@^3.1.13: + version "3.1.13" + resolved "https://registry.yarnpkg.com/upath2/-/upath2-3.1.13.tgz#18dd1b99789e51d76a0124490e9020e66e0c3aa4" + integrity sha512-M88uBoqgzrkXvXrF/+oSIPsTmL21uRwGhPVJKODrl+3lXkQ5NPKrTYuSBZVa+lgPGFoI6qYyHlSKACFHO0AoNw== dependencies: - path-is-network-drive "^1.0.13" - path-strip-sep "^1.0.10" - tslib "^2.3.1" + "@types/node" "*" + path-is-network-drive "^1.0.15" + path-strip-sep "^1.0.12" + tslib "^2" uri-js@^4.2.2: version "4.4.1" - resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== dependencies: punycode "^2.1.0" -uuid@^3.3.2, uuid@^3.3.3: - version "3.4.0" - resolved "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - v8-compile-cache-lib@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz" - integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== v8-compile-cache@^2.0.3: version "2.3.0" - resolved "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -verror@1.10.0: - version "1.10.0" - resolved "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -webcrypto-core@^1.7.4: - version "1.7.5" - resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.5.tgz#c02104c953ca7107557f9c165d194c6316587ca4" - integrity sha512-gaExY2/3EHQlRNNNVSrbG2Cg94Rutl7fAaKILS1w8ZDhGxdFOaw6EbCfHIxPy9vt/xwp5o0VQAx9aySPF6hU1A== - dependencies: - "@peculiar/asn1-schema" "^2.1.6" - "@peculiar/json-schema" "^1.1.12" - asn1js "^3.0.1" - pvtsutils "^1.3.2" - tslib "^2.4.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@^2.0.1: +which@2.0.2, which@^2.0.1: version "2.0.2" - resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" word-wrap@^1.2.3: version "1.2.3" - resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== -workerpool@6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" - integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== - -wrap-ansi@^6.2.0: +workerpool@6.2.0: version "6.2.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== wrap-ansi@^7.0.0: version "7.0.0" - resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== dependencies: ansi-styles "^4.0.0" @@ -2846,55 +1601,32 @@ wrap-ansi@^7.0.0: wrappy@1: version "1.0.2" - resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= -write-file-atomic@^3.0.0: - version "3.0.3" - resolved "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz" - integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== - dependencies: - imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^3.1.5" - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - y18n@^5.0.5: version "5.0.8" - resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== yallist@^4.0.0: version "4.0.0" - resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== yargs-parser@20.2.4: version "20.2.4" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^20.2.2: version "20.2.9" - resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== yargs-unparser@2.0.0: version "2.0.0" - resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== dependencies: camelcase "^6.0.0" @@ -2904,7 +1636,7 @@ yargs-unparser@2.0.0: yargs@16.2.0: version "16.2.0" - resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: cliui "^7.0.2" @@ -2915,29 +1647,12 @@ yargs@16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" -yargs@^15.0.2: - version "15.4.1" - resolved "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - yn@3.1.1: version "3.1.1" - resolved "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== yocto-queue@^0.1.0: version "0.1.0" - resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==