/*! Copyright (c) Peculiar Ventures, LLC */ 'use strict'; var core = require('webcrypto-core'); var buffer = require('buffer'); var crypto = require('crypto'); var process = require('process'); var tslib = require('tslib'); var jsonSchema = require('@peculiar/json-schema'); var pvtsutils = require('pvtsutils'); var asn1Schema = require('@peculiar/asn1-schema'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var core__namespace = /*#__PURE__*/_interopNamespaceDefault(core); var crypto__namespace = /*#__PURE__*/_interopNamespaceDefault(crypto); var process__namespace = /*#__PURE__*/_interopNamespaceDefault(process); const JsonBase64UrlConverter = { fromJSON: (value) => buffer.Buffer.from(pvtsutils.Convert.FromBase64Url(value)), toJSON: (value) => pvtsutils.Convert.ToBase64Url(value), }; class CryptoKey extends core__namespace.CryptoKey { constructor() { super(...arguments); this.data = buffer.Buffer.alloc(0); this.algorithm = { name: "" }; this.extractable = false; this.type = "secret"; this.usages = []; this.kty = "oct"; this.alg = ""; } } tslib.__decorate([ jsonSchema.JsonProp({ name: "ext", type: jsonSchema.JsonPropTypes.Boolean, optional: true }) ], CryptoKey.prototype, "extractable", void 0); tslib.__decorate([ jsonSchema.JsonProp({ name: "key_ops", type: jsonSchema.JsonPropTypes.String, repeated: true, optional: true, }) ], CryptoKey.prototype, "usages", void 0); tslib.__decorate([ jsonSchema.JsonProp({ type: jsonSchema.JsonPropTypes.String }) ], CryptoKey.prototype, "kty", void 0); tslib.__decorate([ jsonSchema.JsonProp({ type: jsonSchema.JsonPropTypes.String, optional: true }) ], CryptoKey.prototype, "alg", void 0); class SymmetricKey extends CryptoKey { constructor() { super(...arguments); this.kty = "oct"; this.type = "secret"; } } class AsymmetricKey extends CryptoKey { } class AesCryptoKey extends SymmetricKey { get alg() { switch (this.algorithm.name.toUpperCase()) { case "AES-CBC": return `A${this.algorithm.length}CBC`; case "AES-CTR": return `A${this.algorithm.length}CTR`; case "AES-GCM": return `A${this.algorithm.length}GCM`; case "AES-KW": return `A${this.algorithm.length}KW`; case "AES-CMAC": return `A${this.algorithm.length}CMAC`; case "AES-ECB": return `A${this.algorithm.length}ECB`; default: throw new core__namespace.AlgorithmError("Unsupported algorithm name"); } } set alg(value) { } } tslib.__decorate([ jsonSchema.JsonProp({ name: "k", converter: JsonBase64UrlConverter }) ], AesCryptoKey.prototype, "data", void 0); class AesCrypto { static async generateKey(algorithm, extractable, keyUsages) { const key = new AesCryptoKey(); key.algorithm = algorithm; key.extractable = extractable; key.usages = keyUsages; key.data = crypto.randomBytes(algorithm.length >> 3); return key; } static async exportKey(format, key) { if (!(key instanceof AesCryptoKey)) { throw new Error("key: Is not AesCryptoKey"); } switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(key); case "raw": return new Uint8Array(key.data).buffer; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } } static async importKey(format, keyData, algorithm, extractable, keyUsages) { let key; switch (format.toLowerCase()) { case "jwk": key = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: AesCryptoKey }); break; case "raw": key = new AesCryptoKey(); key.data = buffer.Buffer.from(keyData); break; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } key.algorithm = algorithm; key.algorithm.length = key.data.length << 3; key.extractable = extractable; key.usages = keyUsages; switch (key.algorithm.length) { case 128: case 192: case 256: break; default: throw new core__namespace.OperationError("keyData: Is wrong key length"); } return key; } static async encrypt(algorithm, key, data) { switch (algorithm.name.toUpperCase()) { case "AES-CBC": return this.encryptAesCBC(algorithm, key, buffer.Buffer.from(data)); case "AES-CTR": return this.encryptAesCTR(algorithm, key, buffer.Buffer.from(data)); case "AES-GCM": return this.encryptAesGCM(algorithm, key, buffer.Buffer.from(data)); case "AES-KW": return this.encryptAesKW(algorithm, key, buffer.Buffer.from(data)); case "AES-ECB": return this.encryptAesECB(algorithm, key, buffer.Buffer.from(data)); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async decrypt(algorithm, key, data) { if (!(key instanceof AesCryptoKey)) { throw new Error("key: Is not AesCryptoKey"); } switch (algorithm.name.toUpperCase()) { case "AES-CBC": return this.decryptAesCBC(algorithm, key, buffer.Buffer.from(data)); case "AES-CTR": return this.decryptAesCTR(algorithm, key, buffer.Buffer.from(data)); case "AES-GCM": return this.decryptAesGCM(algorithm, key, buffer.Buffer.from(data)); case "AES-KW": return this.decryptAesKW(algorithm, key, buffer.Buffer.from(data)); case "AES-ECB": return this.decryptAesECB(algorithm, key, buffer.Buffer.from(data)); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async encryptAesCBC(algorithm, key, data) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv)); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptAesCBC(algorithm, key, data) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv)); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } static async encryptAesCTR(algorithm, key, data) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-ctr`, key.data, buffer.Buffer.from(algorithm.counter)); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptAesCTR(algorithm, key, data) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-ctr`, key.data, new Uint8Array(algorithm.counter)); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } static async encryptAesGCM(algorithm, key, data) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-gcm`, key.data, buffer.Buffer.from(algorithm.iv), { authTagLength: (algorithm.tagLength || 128) >> 3, }); if (algorithm.additionalData) { cipher.setAAD(buffer.Buffer.from(algorithm.additionalData)); } let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final(), cipher.getAuthTag()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptAesGCM(algorithm, key, data) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-gcm`, key.data, new Uint8Array(algorithm.iv)); const tagLength = (algorithm.tagLength || 128) >> 3; const enc = data.slice(0, data.length - tagLength); const tag = data.slice(data.length - tagLength); if (algorithm.additionalData) { decipher.setAAD(buffer.Buffer.from(algorithm.additionalData)); } decipher.setAuthTag(tag); let dec = decipher.update(enc); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } static async encryptAesKW(algorithm, key, data) { const cipher = crypto.createCipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); return new Uint8Array(enc).buffer; } static async decryptAesKW(algorithm, key, data) { const decipher = crypto.createDecipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } static async encryptAesECB(algorithm, key, data) { const cipher = crypto.createCipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0)); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptAesECB(algorithm, key, data) { const decipher = crypto.createDecipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0)); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } } AesCrypto.AES_KW_IV = buffer.Buffer.from("A6A6A6A6A6A6A6A6", "hex"); const keyStorage = new WeakMap(); function getCryptoKey(key) { const res = keyStorage.get(key); if (!res) { throw new core__namespace.OperationError("Cannot get CryptoKey from secure storage"); } return res; } function setCryptoKey(value) { const key = core__namespace.CryptoKey.create(value.algorithm, value.type, value.extractable, value.usages); Object.freeze(key); keyStorage.set(key, value); return key; } class AesCbcProvider extends core__namespace.AesCbcProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const key = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } const zero = buffer.Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]); const rb = buffer.Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135]); const blockSize = 16; function bitShiftLeft(buffer$1) { const shifted = buffer.Buffer.alloc(buffer$1.length); const last = buffer$1.length - 1; for (let index = 0; index < last; index++) { shifted[index] = buffer$1[index] << 1; if (buffer$1[index + 1] & 0x80) { shifted[index] += 0x01; } } shifted[last] = buffer$1[last] << 1; return shifted; } function xor(a, b) { const length = Math.min(a.length, b.length); const output = buffer.Buffer.alloc(length); for (let index = 0; index < length; index++) { output[index] = a[index] ^ b[index]; } return output; } function aes(key, message) { const cipher = crypto__namespace.createCipheriv(`aes${key.length << 3}`, key, zero); const result = cipher.update(message); cipher.final(); return result; } function getMessageBlock(message, blockIndex) { const block = buffer.Buffer.alloc(blockSize); const start = blockIndex * blockSize; const end = start + blockSize; message.copy(block, 0, start, end); return block; } function getPaddedMessageBlock(message, blockIndex) { const block = buffer.Buffer.alloc(blockSize); const start = blockIndex * blockSize; const end = message.length; block.fill(0); message.copy(block, 0, start, end); block[end - start] = 0x80; return block; } function generateSubkeys(key) { const l = aes(key, zero); let subkey1 = bitShiftLeft(l); if (l[0] & 0x80) { subkey1 = xor(subkey1, rb); } let subkey2 = bitShiftLeft(subkey1); if (subkey1[0] & 0x80) { subkey2 = xor(subkey2, rb); } return { subkey1, subkey2 }; } function aesCmac(key, message) { const subkeys = generateSubkeys(key); let blockCount = Math.ceil(message.length / blockSize); let lastBlockCompleteFlag; let lastBlock; if (blockCount === 0) { blockCount = 1; lastBlockCompleteFlag = false; } else { lastBlockCompleteFlag = message.length % blockSize === 0; } const lastBlockIndex = blockCount - 1; if (lastBlockCompleteFlag) { lastBlock = xor(getMessageBlock(message, lastBlockIndex), subkeys.subkey1); } else { lastBlock = xor(getPaddedMessageBlock(message, lastBlockIndex), subkeys.subkey2); } let x = zero; let y; for (let index = 0; index < lastBlockIndex; index++) { y = xor(x, getMessageBlock(message, index)); x = aes(key, y); } y = xor(lastBlock, x); return aes(key, y); } class AesCmacProvider extends core__namespace.AesCmacProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const key = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(key); } async onSign(algorithm, key, data) { const result = aesCmac(getCryptoKey(key).data, buffer.Buffer.from(data)); return new Uint8Array(result).buffer; } async onVerify(algorithm, key, signature, data) { const signature2 = await this.sign(algorithm, key, data); return buffer.Buffer.from(signature).compare(buffer.Buffer.from(signature2)) === 0; } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } class AesCtrProvider extends core__namespace.AesCtrProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const key = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } class AesGcmProvider extends core__namespace.AesGcmProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const key = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } class AesKwProvider extends core__namespace.AesKwProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const res = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(res); } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } async onEncrypt(algorithm, key, data) { return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } class AesEcbProvider extends core__namespace.AesEcbProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const key = await AesCrypto.generateKey({ name: this.name, length: algorithm.length, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return AesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return AesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return AesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const res = await AesCrypto.importKey(format, keyData, { name: algorithm.name }, extractable, keyUsages); return setCryptoKey(res); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof AesCryptoKey)) { throw new TypeError("key: Is not a AesCryptoKey"); } } } class DesCryptoKey extends SymmetricKey { get alg() { switch (this.algorithm.name.toUpperCase()) { case "DES-CBC": return `DES-CBC`; case "DES-EDE3-CBC": return `3DES-CBC`; default: throw new core__namespace.AlgorithmError("Unsupported algorithm name"); } } set alg(value) { } } tslib.__decorate([ jsonSchema.JsonProp({ name: "k", converter: JsonBase64UrlConverter }) ], DesCryptoKey.prototype, "data", void 0); class DesCrypto { static async generateKey(algorithm, extractable, keyUsages) { const key = new DesCryptoKey(); key.algorithm = algorithm; key.extractable = extractable; key.usages = keyUsages; key.data = crypto.randomBytes(algorithm.length >> 3); return key; } static async exportKey(format, key) { switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(key); case "raw": return new Uint8Array(key.data).buffer; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } } static async importKey(format, keyData, algorithm, extractable, keyUsages) { let key; switch (format.toLowerCase()) { case "jwk": key = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: DesCryptoKey }); break; case "raw": key = new DesCryptoKey(); key.data = buffer.Buffer.from(keyData); break; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } key.algorithm = algorithm; key.extractable = extractable; key.usages = keyUsages; return key; } static async encrypt(algorithm, key, data) { switch (algorithm.name.toUpperCase()) { case "DES-CBC": return this.encryptDesCBC(algorithm, key, buffer.Buffer.from(data)); case "DES-EDE3-CBC": return this.encryptDesEDE3CBC(algorithm, key, buffer.Buffer.from(data)); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async decrypt(algorithm, key, data) { if (!(key instanceof DesCryptoKey)) { throw new Error("key: Is not DesCryptoKey"); } switch (algorithm.name.toUpperCase()) { case "DES-CBC": return this.decryptDesCBC(algorithm, key, buffer.Buffer.from(data)); case "DES-EDE3-CBC": return this.decryptDesEDE3CBC(algorithm, key, buffer.Buffer.from(data)); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async encryptDesCBC(algorithm, key, data) { const cipher = crypto.createCipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv)); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptDesCBC(algorithm, key, data) { const decipher = crypto.createDecipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv)); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } static async encryptDesEDE3CBC(algorithm, key, data) { const cipher = crypto.createCipheriv(`des-ede3-cbc`, key.data, buffer.Buffer.from(algorithm.iv)); let enc = cipher.update(data); enc = buffer.Buffer.concat([enc, cipher.final()]); const res = new Uint8Array(enc).buffer; return res; } static async decryptDesEDE3CBC(algorithm, key, data) { const decipher = crypto.createDecipheriv(`des-ede3-cbc`, key.data, new Uint8Array(algorithm.iv)); let dec = decipher.update(data); dec = buffer.Buffer.concat([dec, decipher.final()]); return new Uint8Array(dec).buffer; } } class DesCbcProvider extends core__namespace.DesProvider { constructor() { super(...arguments); this.keySizeBits = 64; this.ivSize = 8; this.name = "DES-CBC"; } async onGenerateKey(algorithm, extractable, keyUsages) { const key = await DesCrypto.generateKey({ name: this.name, length: this.keySizeBits, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return DesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return DesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return DesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { 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__namespace.OperationError("keyData: Wrong key size"); } return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof DesCryptoKey)) { throw new TypeError("key: Is not a DesCryptoKey"); } } } class DesEde3CbcProvider extends core__namespace.DesProvider { constructor() { super(...arguments); this.keySizeBits = 192; this.ivSize = 8; this.name = "DES-EDE3-CBC"; } async onGenerateKey(algorithm, extractable, keyUsages) { const key = await DesCrypto.generateKey({ name: this.name, length: this.keySizeBits, }, extractable, keyUsages); return setCryptoKey(key); } async onEncrypt(algorithm, key, data) { return DesCrypto.encrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onDecrypt(algorithm, key, data) { return DesCrypto.decrypt(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onExportKey(format, key) { return DesCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { 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__namespace.OperationError("keyData: Wrong key size"); } return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof DesCryptoKey)) { throw new TypeError("key: Is not a DesCryptoKey"); } } } function getJwkAlgorithm(algorithm) { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": { const mdSize = /(\d+)$/.exec(algorithm.hash.name)[1]; return `RSA-OAEP${mdSize !== "1" ? `-${mdSize}` : ""}`; } case "RSASSA-PKCS1-V1_5": return `RS${/(\d+)$/.exec(algorithm.hash.name)[1]}`; case "RSA-PSS": return `PS${/(\d+)$/.exec(algorithm.hash.name)[1]}`; case "RSA-PKCS1": return `RS1`; default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } class RsaPrivateKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "private"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PrivateKeyInfo); return asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.RsaPrivateKey); } toJSON() { const key = this.getKey(); const json = { kty: "RSA", alg: getJwkAlgorithm(this.algorithm), key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); } fromJSON(json) { const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core__namespace.asn1.RsaPrivateKey, }); const keyInfo = new core__namespace.asn1.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.privateKeyAlgorithm.parameters = null; keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); } } class RsaPublicKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "public"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PublicKeyInfo); return asn1Schema.AsnParser.parse(keyInfo.publicKey, core__namespace.asn1.RsaPublicKey); } toJSON() { const key = this.getKey(); const json = { kty: "RSA", alg: getJwkAlgorithm(this.algorithm), key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); } fromJSON(json) { const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core__namespace.asn1.RsaPublicKey, }); const keyInfo = new core__namespace.asn1.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.publicKeyAlgorithm.parameters = null; keyInfo.publicKey = asn1Schema.AsnSerializer.serialize(key); this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); } } class RsaCrypto { static async generateKey(algorithm, extractable, keyUsages) { const privateKey = new RsaPrivateKey(); privateKey.algorithm = algorithm; privateKey.extractable = extractable; privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1); const publicKey = new RsaPublicKey(); publicKey.algorithm = algorithm; publicKey.extractable = true; publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1); const publicExponent = buffer.Buffer.concat([ buffer.Buffer.alloc(4 - algorithm.publicExponent.byteLength, 0), buffer.Buffer.from(algorithm.publicExponent), ]).readInt32BE(0); const keys = crypto.generateKeyPairSync("rsa", { modulusLength: algorithm.modulusLength, publicExponent, publicKeyEncoding: { format: "der", type: "spki", }, privateKeyEncoding: { format: "der", type: "pkcs8", }, }); privateKey.data = keys.privateKey; publicKey.data = keys.publicKey; const res = { privateKey, publicKey, }; return res; } static async exportKey(format, key) { switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(key); case "pkcs8": case "spki": return new Uint8Array(key.data).buffer; default: throw new core__namespace.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'"); } } static async importKey(format, keyData, algorithm, extractable, keyUsages) { switch (format.toLowerCase()) { case "jwk": { const jwk = keyData; if (jwk.d) { const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core__namespace.asn1.RsaPrivateKey, }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core__namespace.asn1.RsaPublicKey, }); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } } case "spki": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PublicKeyInfo); const asnKey = asn1Schema.AsnParser.parse(keyInfo.publicKey, core__namespace.asn1.RsaPublicKey); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "pkcs8": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PrivateKeyInfo); const asnKey = asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.RsaPrivateKey); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } default: throw new core__namespace.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'"); } } static async sign(algorithm, key, data) { switch (algorithm.name.toUpperCase()) { case "RSA-PSS": case "RSASSA-PKCS1-V1_5": return this.signRsa(algorithm, key, data); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async verify(algorithm, key, signature, data) { switch (algorithm.name.toUpperCase()) { case "RSA-PSS": case "RSASSA-PKCS1-V1_5": return this.verifySSA(algorithm, key, data, signature); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async encrypt(algorithm, key, data) { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": return this.encryptOAEP(algorithm, key, data); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static async decrypt(algorithm, key, data) { switch (algorithm.name.toUpperCase()) { case "RSA-OAEP": return this.decryptOAEP(algorithm, key, data); default: throw new core__namespace.OperationError("algorithm: Is not recognized"); } } static importPrivateKey(asnKey, algorithm, extractable, keyUsages) { const keyInfo = new core__namespace.asn1.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.privateKeyAlgorithm.parameters = null; keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(asnKey); const key = new RsaPrivateKey(); key.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); key.algorithm = Object.assign({}, algorithm); key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent); key.algorithm.modulusLength = asnKey.modulus.byteLength << 3; key.extractable = extractable; key.usages = keyUsages; return key; } static importPublicKey(asnKey, algorithm, extractable, keyUsages) { const keyInfo = new core__namespace.asn1.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1"; keyInfo.publicKeyAlgorithm.parameters = null; keyInfo.publicKey = asn1Schema.AsnSerializer.serialize(asnKey); const key = new RsaPublicKey(); key.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); key.algorithm = Object.assign({}, algorithm); key.algorithm.publicExponent = new Uint8Array(asnKey.publicExponent); key.algorithm.modulusLength = asnKey.modulus.byteLength << 3; key.extractable = extractable; key.usages = keyUsages; return key; } static getCryptoAlgorithm(alg) { switch (alg.hash.name.toUpperCase()) { case "SHA-1": return "RSA-SHA1"; case "SHA-256": return "RSA-SHA256"; case "SHA-384": return "RSA-SHA384"; case "SHA-512": return "RSA-SHA512"; case "SHA3-256": return "RSA-SHA3-256"; case "SHA3-384": return "RSA-SHA3-384"; case "SHA3-512": return "RSA-SHA3-512"; default: throw new core__namespace.OperationError("algorithm.hash: Is not recognized"); } } static signRsa(algorithm, key, data) { const cryptoAlg = this.getCryptoAlgorithm(key.algorithm); const signer = crypto.createSign(cryptoAlg); signer.update(buffer.Buffer.from(data)); if (!key.pem) { key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`; } const options = { key: key.pem, }; if (algorithm.name.toUpperCase() === "RSA-PSS") { options.padding = crypto.constants.RSA_PKCS1_PSS_PADDING; options.saltLength = algorithm.saltLength; } const signature = signer.sign(options); return new Uint8Array(signature).buffer; } static verifySSA(algorithm, key, data, signature) { const cryptoAlg = this.getCryptoAlgorithm(key.algorithm); const signer = crypto.createVerify(cryptoAlg); signer.update(buffer.Buffer.from(data)); if (!key.pem) { key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`; } const options = { key: key.pem, }; if (algorithm.name.toUpperCase() === "RSA-PSS") { options.padding = crypto.constants.RSA_PKCS1_PSS_PADDING; options.saltLength = algorithm.saltLength; } const ok = signer.verify(options, signature); return ok; } static encryptOAEP(algorithm, key, data) { const options = { key: `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, }; if (algorithm.label) ; return new Uint8Array(crypto.publicEncrypt(options, data)).buffer; } static decryptOAEP(algorithm, key, data) { const options = { key: `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`, padding: crypto.constants.RSA_PKCS1_OAEP_PADDING, }; if (algorithm.label) ; return new Uint8Array(crypto.privateDecrypt(options, data)).buffer; } } RsaCrypto.publicKeyUsages = ["verify", "encrypt", "wrapKey"]; RsaCrypto.privateKeyUsages = ["sign", "decrypt", "unwrapKey"]; class RsaSsaProvider extends core__namespace.RsaSsaProvider { constructor() { super(...arguments); this.hashAlgorithms = [ "SHA-1", "SHA-256", "SHA-384", "SHA-512", "shake128", "shake256", "SHA3-256", "SHA3-384", "SHA3-512", ]; } async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await RsaCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onSign(algorithm, key, data) { return RsaCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onVerify(algorithm, key, signature, data) { return RsaCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data)); } async onExportKey(format, key) { return RsaCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { throw new TypeError("key: Is not RSA CryptoKey"); } } } class RsaPssProvider extends core__namespace.RsaPssProvider { constructor() { super(...arguments); this.hashAlgorithms = [ "SHA-1", "SHA-256", "SHA-384", "SHA-512", "shake128", "shake256", "SHA3-256", "SHA3-384", "SHA3-512", ]; } async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await RsaCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onSign(algorithm, key, data) { return RsaCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onVerify(algorithm, key, signature, data) { return RsaCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data)); } async onExportKey(format, key) { return RsaCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { throw new TypeError("key: Is not RSA CryptoKey"); } } } class ShaCrypto { static size(algorithm) { switch (algorithm.name.toUpperCase()) { case "SHA-1": return 160; case "SHA-256": case "SHA3-256": return 256; case "SHA-384": case "SHA3-384": return 384; case "SHA-512": case "SHA3-512": return 512; default: throw new Error("Unrecognized name"); } } static getAlgorithmName(algorithm) { switch (algorithm.name.toUpperCase()) { case "SHA-1": return "sha1"; case "SHA-256": return "sha256"; case "SHA-384": return "sha384"; case "SHA-512": return "sha512"; case "SHA3-256": return "sha3-256"; case "SHA3-384": return "sha3-384"; case "SHA3-512": return "sha3-512"; default: throw new Error("Unrecognized name"); } } static digest(algorithm, data) { const hashAlg = this.getAlgorithmName(algorithm); const hash = crypto.createHash(hashAlg).update(buffer.Buffer.from(data)).digest(); return new Uint8Array(hash).buffer; } } class RsaOaepProvider extends core__namespace.RsaOaepProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await RsaCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onEncrypt(algorithm, key, data) { const internalKey = getCryptoKey(key); const dataView = new Uint8Array(data); const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3); const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3; const dataLength = dataView.byteLength; const psLength = keySize - dataLength - 2 * hashSize - 2; if (dataLength > keySize - 2 * hashSize - 2) { throw new Error("Data too large"); } const message = new Uint8Array(keySize); const seed = message.subarray(1, hashSize + 1); const dataBlock = message.subarray(hashSize + 1); dataBlock.set(dataView, hashSize + psLength + 1); const labelHash = crypto .createHash(internalKey.algorithm.hash.name.replace("-", "")) .update(core__namespace.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .digest(); dataBlock.set(labelHash, 0); dataBlock[hashSize + psLength] = 1; crypto.randomFillSync(seed); const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length); for (let i = 0; i < dataBlock.length; i++) { dataBlock[i] ^= dataBlockMask[i]; } const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length); for (let i = 0; i < seed.length; i++) { seed[i] ^= seedMask[i]; } if (!internalKey.pem) { internalKey.pem = `-----BEGIN PUBLIC KEY-----\n${internalKey.data.toString("base64")}\n-----END PUBLIC KEY-----`; } const pkcs0 = crypto.publicEncrypt({ key: internalKey.pem, padding: crypto.constants.RSA_NO_PADDING, }, buffer.Buffer.from(message)); return new Uint8Array(pkcs0).buffer; } async onDecrypt(algorithm, key, data) { const internalKey = getCryptoKey(key); const keySize = Math.ceil(internalKey.algorithm.modulusLength >> 3); const hashSize = ShaCrypto.size(internalKey.algorithm.hash) >> 3; const dataLength = data.byteLength; if (dataLength !== keySize) { throw new Error("Bad data"); } if (!internalKey.pem) { internalKey.pem = `-----BEGIN PRIVATE KEY-----\n${internalKey.data.toString("base64")}\n-----END PRIVATE KEY-----`; } let pkcs0 = crypto.privateDecrypt({ key: internalKey.pem, padding: crypto.constants.RSA_NO_PADDING, }, buffer.Buffer.from(data)); const z = pkcs0[0]; const seed = pkcs0.subarray(1, hashSize + 1); const dataBlock = pkcs0.subarray(hashSize + 1); if (z !== 0) { throw new Error("Decryption failed"); } const seedMask = this.mgf1(internalKey.algorithm.hash, dataBlock, seed.length); for (let i = 0; i < seed.length; i++) { seed[i] ^= seedMask[i]; } const dataBlockMask = this.mgf1(internalKey.algorithm.hash, seed, dataBlock.length); for (let i = 0; i < dataBlock.length; i++) { dataBlock[i] ^= dataBlockMask[i]; } const labelHash = crypto .createHash(internalKey.algorithm.hash.name.replace("-", "")) .update(core__namespace.BufferSourceConverter.toUint8Array(algorithm.label || new Uint8Array(0))) .digest(); for (let i = 0; i < hashSize; i++) { if (labelHash[i] !== dataBlock[i]) { throw new Error("Decryption failed"); } } let psEnd = hashSize; for (; psEnd < dataBlock.length; psEnd++) { const psz = dataBlock[psEnd]; if (psz === 1) { break; } if (psz !== 0) { throw new Error("Decryption failed"); } } if (psEnd === dataBlock.length) { throw new Error("Decryption failed"); } pkcs0 = dataBlock.subarray(psEnd + 1); return new Uint8Array(pkcs0).buffer; } async onExportKey(format, key) { return RsaCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { throw new TypeError("key: Is not RSA CryptoKey"); } } mgf1(algorithm, seed, length = 0) { const hashSize = ShaCrypto.size(algorithm) >> 3; const mask = new Uint8Array(length); const counter = new Uint8Array(4); const chunks = Math.ceil(length / hashSize); for (let i = 0; i < chunks; i++) { counter[0] = i >>> 24; counter[1] = (i >>> 16) & 255; counter[2] = (i >>> 8) & 255; counter[3] = i & 255; const submask = mask.subarray(i * hashSize); let chunk = crypto .createHash(algorithm.name.replace("-", "")) .update(seed) .update(counter) .digest(); if (chunk.length > submask.length) { chunk = chunk.subarray(0, submask.length); } submask.set(chunk); } return mask; } } class RsaEsProvider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "RSAES-PKCS1-v1_5"; this.usages = { publicKey: ["encrypt", "wrapKey"], privateKey: ["decrypt", "unwrapKey"], }; } async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await RsaCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } checkGenerateKeyParams(algorithm) { this.checkRequiredProperty(algorithm, "publicExponent"); if (!(algorithm.publicExponent && algorithm.publicExponent instanceof Uint8Array)) { throw new TypeError("publicExponent: Missing or not a Uint8Array"); } const publicExponent = pvtsutils.Convert.ToBase64(algorithm.publicExponent); if (!(publicExponent === "Aw==" || publicExponent === "AQAB")) { throw new TypeError("publicExponent: Must be [3] or [1,0,1]"); } this.checkRequiredProperty(algorithm, "modulusLength"); switch (algorithm.modulusLength) { case 1024: case 2048: case 4096: break; default: throw new TypeError("modulusLength: Must be 1024, 2048, or 4096"); } } async onEncrypt(algorithm, key, data) { const options = this.toCryptoOptions(key); const enc = crypto__namespace.publicEncrypt(options, new Uint8Array(data)); return new Uint8Array(enc).buffer; } async onDecrypt(algorithm, key, data) { const options = this.toCryptoOptions(key); const dec = crypto__namespace.privateDecrypt(options, new Uint8Array(data)); return new Uint8Array(dec).buffer; } async onExportKey(format, key) { return RsaCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await RsaCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof RsaPrivateKey || internalKey instanceof RsaPublicKey)) { throw new TypeError("key: Is not RSA CryptoKey"); } } toCryptoOptions(key) { const type = key.type.toUpperCase(); return { key: `-----BEGIN ${type} KEY-----\n${getCryptoKey(key).data.toString("base64")}\n-----END ${type} KEY-----`, padding: crypto__namespace.constants.RSA_PKCS1_PADDING, }; } } const namedOIDs = { "1.2.840.10045.3.1.7": "P-256", "P-256": "1.2.840.10045.3.1.7", "1.3.132.0.34": "P-384", "P-384": "1.3.132.0.34", "1.3.132.0.35": "P-521", "P-521": "1.3.132.0.35", "1.3.132.0.10": "K-256", "K-256": "1.3.132.0.10", brainpoolP160r1: "1.3.36.3.3.2.8.1.1.1", "1.3.36.3.3.2.8.1.1.1": "brainpoolP160r1", brainpoolP160t1: "1.3.36.3.3.2.8.1.1.2", "1.3.36.3.3.2.8.1.1.2": "brainpoolP160t1", brainpoolP192r1: "1.3.36.3.3.2.8.1.1.3", "1.3.36.3.3.2.8.1.1.3": "brainpoolP192r1", brainpoolP192t1: "1.3.36.3.3.2.8.1.1.4", "1.3.36.3.3.2.8.1.1.4": "brainpoolP192t1", brainpoolP224r1: "1.3.36.3.3.2.8.1.1.5", "1.3.36.3.3.2.8.1.1.5": "brainpoolP224r1", brainpoolP224t1: "1.3.36.3.3.2.8.1.1.6", "1.3.36.3.3.2.8.1.1.6": "brainpoolP224t1", brainpoolP256r1: "1.3.36.3.3.2.8.1.1.7", "1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1", brainpoolP256t1: "1.3.36.3.3.2.8.1.1.8", "1.3.36.3.3.2.8.1.1.8": "brainpoolP256t1", brainpoolP320r1: "1.3.36.3.3.2.8.1.1.9", "1.3.36.3.3.2.8.1.1.9": "brainpoolP320r1", brainpoolP320t1: "1.3.36.3.3.2.8.1.1.10", "1.3.36.3.3.2.8.1.1.10": "brainpoolP320t1", brainpoolP384r1: "1.3.36.3.3.2.8.1.1.11", "1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1", brainpoolP384t1: "1.3.36.3.3.2.8.1.1.12", "1.3.36.3.3.2.8.1.1.12": "brainpoolP384t1", brainpoolP512r1: "1.3.36.3.3.2.8.1.1.13", "1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1", brainpoolP512t1: "1.3.36.3.3.2.8.1.1.14", "1.3.36.3.3.2.8.1.1.14": "brainpoolP512t1", }; function getOidByNamedCurve$1(namedCurve) { const oid = namedOIDs[namedCurve]; if (!oid) { throw new core__namespace.OperationError(`Cannot convert WebCrypto named curve '${namedCurve}' to OID`); } return oid; } class EcPrivateKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "private"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PrivateKeyInfo); return asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.EcPrivateKey); } toJSON() { const key = this.getKey(); const json = { kty: "EC", crv: this.algorithm.namedCurve, key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); } fromJSON(json) { if (!json.crv) { throw new core__namespace.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); } const keyInfo = new core__namespace.asn1.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; keyInfo.privateKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize(new core__namespace.asn1.ObjectIdentifier(getOidByNamedCurve$1(json.crv))); const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core__namespace.asn1.EcPrivateKey, }); keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); return this; } } class EcPublicKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "public"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PublicKeyInfo); return new core__namespace.asn1.EcPublicKey(keyInfo.publicKey); } toJSON() { const key = this.getKey(); const json = { kty: "EC", crv: this.algorithm.namedCurve, key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); } fromJSON(json) { if (!json.crv) { throw new core__namespace.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); } const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core__namespace.asn1.EcPublicKey, }); const keyInfo = new core__namespace.asn1.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; keyInfo.publicKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize(new core__namespace.asn1.ObjectIdentifier(getOidByNamedCurve$1(json.crv))); keyInfo.publicKey = asn1Schema.AsnSerializer.toASN(key).valueHex; this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); return this; } } class Sha1Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA-1"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha256Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA-256"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha384Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA-384"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha512Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA-512"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha3256Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA3-256"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha3384Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA3-384"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class Sha3512Provider extends core__namespace.ProviderCrypto { constructor() { super(...arguments); this.name = "SHA3-512"; this.usages = []; } async onDigest(algorithm, data) { return ShaCrypto.digest(algorithm, data); } } class EcCrypto { static async generateKey(algorithm, extractable, keyUsages) { const privateKey = new EcPrivateKey(); privateKey.algorithm = algorithm; privateKey.extractable = extractable; privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1); const publicKey = new EcPublicKey(); publicKey.algorithm = algorithm; publicKey.extractable = true; publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1); const keys = crypto.generateKeyPairSync("ec", { namedCurve: this.getOpenSSLNamedCurve(algorithm.namedCurve), publicKeyEncoding: { format: "der", type: "spki", }, privateKeyEncoding: { format: "der", type: "pkcs8", }, }); privateKey.data = keys.privateKey; publicKey.data = keys.publicKey; const res = { privateKey, publicKey, }; return res; } static async sign(algorithm, key, data) { const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash); const signer = crypto.createSign(cryptoAlg); signer.update(buffer.Buffer.from(data)); if (!key.pem) { key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`; } const options = { key: key.pem, }; const signature = signer.sign(options); const ecSignature = asn1Schema.AsnParser.parse(signature, core__namespace.asn1.EcDsaSignature); const signatureRaw = core__namespace.EcUtils.encodeSignature(ecSignature, core__namespace.EcCurves.get(key.algorithm.namedCurve).size); return signatureRaw.buffer; } static async verify(algorithm, key, signature, data) { const cryptoAlg = ShaCrypto.getAlgorithmName(algorithm.hash); const signer = crypto.createVerify(cryptoAlg); signer.update(buffer.Buffer.from(data)); if (!key.pem) { key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`; } const options = { key: key.pem, }; const ecSignature = new core__namespace.asn1.EcDsaSignature(); const namedCurve = core__namespace.EcCurves.get(key.algorithm.namedCurve); const signaturePoint = core__namespace.EcUtils.decodeSignature(signature, namedCurve.size); ecSignature.r = pvtsutils.BufferSourceConverter.toArrayBuffer(signaturePoint.r); ecSignature.s = pvtsutils.BufferSourceConverter.toArrayBuffer(signaturePoint.s); const ecSignatureRaw = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(ecSignature)); const ok = signer.verify(options, ecSignatureRaw); return ok; } static async deriveBits(algorithm, baseKey, length) { const cryptoAlg = this.getOpenSSLNamedCurve(baseKey.algorithm.namedCurve); const ecdh = crypto.createECDH(cryptoAlg); const asnPrivateKey = asn1Schema.AsnParser.parse(baseKey.data, core__namespace.asn1.PrivateKeyInfo); const asnEcPrivateKey = asn1Schema.AsnParser.parse(asnPrivateKey.privateKey, core__namespace.asn1.EcPrivateKey); ecdh.setPrivateKey(buffer.Buffer.from(asnEcPrivateKey.privateKey)); const asnPublicKey = asn1Schema.AsnParser.parse(algorithm.public.data, core__namespace.asn1.PublicKeyInfo); const bits = ecdh.computeSecret(buffer.Buffer.from(asnPublicKey.publicKey)); if (length === null) { return bits; } return new Uint8Array(bits).buffer.slice(0, length >> 3); } static async exportKey(format, key) { switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(key); case "pkcs8": case "spki": return new Uint8Array(key.data).buffer; case "raw": { const publicKeyInfo = asn1Schema.AsnParser.parse(key.data, core__namespace.asn1.PublicKeyInfo); return publicKeyInfo.publicKey; } default: throw new core__namespace.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'"); } } static async importKey(format, keyData, algorithm, extractable, keyUsages) { switch (format.toLowerCase()) { case "jwk": { const jwk = keyData; if (jwk.d) { const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core__namespace.asn1.EcPrivateKey, }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core__namespace.asn1.EcPublicKey, }); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } } case "raw": { const asnKey = new core__namespace.asn1.EcPublicKey(keyData); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "spki": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PublicKeyInfo); const asnKey = new core__namespace.asn1.EcPublicKey(keyInfo.publicKey); this.assertKeyParameters(keyInfo.publicKeyAlgorithm.parameters, algorithm.namedCurve); return this.importPublicKey(asnKey, algorithm, extractable, keyUsages); } case "pkcs8": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PrivateKeyInfo); const asnKey = asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.EcPrivateKey); this.assertKeyParameters(keyInfo.privateKeyAlgorithm.parameters, algorithm.namedCurve); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } default: throw new core__namespace.OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'"); } } static assertKeyParameters(parameters, namedCurve) { if (!parameters) { throw new core__namespace.CryptoError("Key info doesn't have required parameters"); } let namedCurveIdentifier = ""; try { namedCurveIdentifier = asn1Schema.AsnParser.parse(parameters, core__namespace.asn1.ObjectIdentifier).value; } catch (e) { throw new core__namespace.CryptoError("Cannot read key info parameters"); } if (getOidByNamedCurve$1(namedCurve) !== namedCurveIdentifier) { throw new core__namespace.CryptoError("Key info parameter doesn't match to named curve"); } } static async importPrivateKey(asnKey, algorithm, extractable, keyUsages) { const keyInfo = new core__namespace.asn1.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; keyInfo.privateKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize(new core__namespace.asn1.ObjectIdentifier(getOidByNamedCurve$1(algorithm.namedCurve))); keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(asnKey); const key = new EcPrivateKey(); key.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); key.algorithm = Object.assign({}, algorithm); key.extractable = extractable; key.usages = keyUsages; return key; } static async importPublicKey(asnKey, algorithm, extractable, keyUsages) { const keyInfo = new core__namespace.asn1.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.10045.2.1"; const namedCurve = getOidByNamedCurve$1(algorithm.namedCurve); keyInfo.publicKeyAlgorithm.parameters = asn1Schema.AsnSerializer.serialize(new core__namespace.asn1.ObjectIdentifier(namedCurve)); keyInfo.publicKey = asnKey.value; const key = new EcPublicKey(); key.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); key.algorithm = Object.assign({}, algorithm); key.extractable = extractable; key.usages = keyUsages; return key; } static getOpenSSLNamedCurve(curve) { switch (curve.toUpperCase()) { case "P-256": return "prime256v1"; case "K-256": return "secp256k1"; case "P-384": return "secp384r1"; case "P-521": return "secp521r1"; default: return curve; } } } EcCrypto.publicKeyUsages = ["verify"]; EcCrypto.privateKeyUsages = ["sign", "deriveKey", "deriveBits"]; class EcdsaProvider extends core__namespace.EcdsaProvider { constructor() { super(...arguments); this.namedCurves = core__namespace.EcCurves.names; this.hashAlgorithms = [ "SHA-1", "SHA-256", "SHA-384", "SHA-512", "shake128", "shake256", "SHA3-256", "SHA3-384", "SHA3-512", ]; } async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await EcCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onSign(algorithm, key, data) { return EcCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onVerify(algorithm, key, signature, data) { return EcCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data)); } async onExportKey(format, key) { return EcCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) { throw new TypeError("key: Is not EC CryptoKey"); } } } class EcdhProvider extends core__namespace.EcdhProvider { constructor() { super(...arguments); this.namedCurves = core__namespace.EcCurves.names; } async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await EcCrypto.generateKey({ ...algorithm, name: this.name, }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onExportKey(format, key) { return EcCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await EcCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); const internalKey = getCryptoKey(key); if (!(internalKey instanceof EcPrivateKey || internalKey instanceof EcPublicKey)) { throw new TypeError("key: Is not EC CryptoKey"); } } async onDeriveBits(algorithm, baseKey, length) { const bits = await EcCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length); return bits; } } const edOIDs = { [core__namespace.asn1.idEd448]: "Ed448", ed448: core__namespace.asn1.idEd448, [core__namespace.asn1.idX448]: "X448", x448: core__namespace.asn1.idX448, [core__namespace.asn1.idEd25519]: "Ed25519", ed25519: core__namespace.asn1.idEd25519, [core__namespace.asn1.idX25519]: "X25519", x25519: core__namespace.asn1.idX25519, }; function getOidByNamedCurve(namedCurve) { const oid = edOIDs[namedCurve.toLowerCase()]; if (!oid) { throw new core__namespace.OperationError(`Cannot convert WebCrypto named curve '${namedCurve}' to OID`); } return oid; } class EdPrivateKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "private"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PrivateKeyInfo); return asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.CurvePrivateKey); } toJSON() { const key = this.getKey(); const json = { kty: "OKP", crv: this.algorithm.namedCurve, key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, jsonSchema.JsonSerializer.toJSON(key)); } fromJSON(json) { if (!json.crv) { throw new core__namespace.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); } const keyInfo = new core__namespace.asn1.PrivateKeyInfo(); keyInfo.privateKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); const key = jsonSchema.JsonParser.fromJSON(json, { targetSchema: core__namespace.asn1.CurvePrivateKey, }); keyInfo.privateKey = asn1Schema.AsnSerializer.serialize(key); this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); return this; } } class EdPublicKey extends AsymmetricKey { constructor() { super(...arguments); this.type = "public"; } getKey() { const keyInfo = asn1Schema.AsnParser.parse(this.data, core__namespace.asn1.PublicKeyInfo); return keyInfo.publicKey; } toJSON() { const key = this.getKey(); const json = { kty: "OKP", crv: this.algorithm.namedCurve, key_ops: this.usages, ext: this.extractable, }; return Object.assign(json, { x: pvtsutils.Convert.ToBase64Url(key), }); } fromJSON(json) { if (!json.crv) { throw new core__namespace.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`); } if (!json.x) { throw new core__namespace.OperationError(`Cannot get property from JWK. Property 'x' is required`); } const keyInfo = new core__namespace.asn1.PublicKeyInfo(); keyInfo.publicKeyAlgorithm.algorithm = getOidByNamedCurve(json.crv); keyInfo.publicKey = pvtsutils.Convert.FromBase64Url(json.x); this.data = buffer.Buffer.from(asn1Schema.AsnSerializer.serialize(keyInfo)); return this; } } class EdCrypto { static async generateKey(algorithm, extractable, keyUsages) { const privateKey = new EdPrivateKey(); privateKey.algorithm = algorithm; privateKey.extractable = extractable; privateKey.usages = keyUsages.filter((usage) => this.privateKeyUsages.indexOf(usage) !== -1); const publicKey = new EdPublicKey(); publicKey.algorithm = algorithm; publicKey.extractable = true; publicKey.usages = keyUsages.filter((usage) => this.publicKeyUsages.indexOf(usage) !== -1); const type = algorithm.namedCurve.toLowerCase(); const keys = crypto.generateKeyPairSync(type, { publicKeyEncoding: { format: "der", type: "spki", }, privateKeyEncoding: { format: "der", type: "pkcs8", }, }); privateKey.data = keys.privateKey; publicKey.data = keys.publicKey; const res = { privateKey, publicKey, }; return res; } static async sign(algorithm, key, data) { if (!key.pem) { key.pem = `-----BEGIN PRIVATE KEY-----\n${key.data.toString("base64")}\n-----END PRIVATE KEY-----`; } const options = { key: key.pem, }; const signature = crypto.sign(null, buffer.Buffer.from(data), options); return core__namespace.BufferSourceConverter.toArrayBuffer(signature); } static async verify(algorithm, key, signature, data) { if (!key.pem) { key.pem = `-----BEGIN PUBLIC KEY-----\n${key.data.toString("base64")}\n-----END PUBLIC KEY-----`; } const options = { key: key.pem, }; const ok = crypto.verify(null, buffer.Buffer.from(data), options, buffer.Buffer.from(signature)); return ok; } static async deriveBits(algorithm, baseKey, length) { const publicKey = crypto.createPublicKey({ key: algorithm.public.data, format: "der", type: "spki", }); const privateKey = crypto.createPrivateKey({ key: baseKey.data, format: "der", type: "pkcs8", }); const bits = crypto.diffieHellman({ publicKey, privateKey, }); return new Uint8Array(bits).buffer.slice(0, length >> 3); } static async exportKey(format, key) { switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(key); case "pkcs8": case "spki": return new Uint8Array(key.data).buffer; case "raw": { const publicKeyInfo = asn1Schema.AsnParser.parse(key.data, core__namespace.asn1.PublicKeyInfo); return publicKeyInfo.publicKey; } default: throw new core__namespace.OperationError("format: Must be 'jwk', 'raw', pkcs8' or 'spki'"); } } static async importKey(format, keyData, algorithm, extractable, keyUsages) { switch (format.toLowerCase()) { case "jwk": { const jwk = keyData; if (jwk.d) { const asnKey = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: core__namespace.asn1.CurvePrivateKey, }); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } else { if (!jwk.x) { throw new TypeError("keyData: Cannot get required 'x' filed"); } return this.importPublicKey(pvtsutils.Convert.FromBase64Url(jwk.x), algorithm, extractable, keyUsages); } } case "raw": { return this.importPublicKey(keyData, algorithm, extractable, keyUsages); } case "spki": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PublicKeyInfo); return this.importPublicKey(keyInfo.publicKey, algorithm, extractable, keyUsages); } case "pkcs8": { const keyInfo = asn1Schema.AsnParser.parse(new Uint8Array(keyData), core__namespace.asn1.PrivateKeyInfo); const asnKey = asn1Schema.AsnParser.parse(keyInfo.privateKey, core__namespace.asn1.CurvePrivateKey); return this.importPrivateKey(asnKey, algorithm, extractable, keyUsages); } default: throw new core__namespace.OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'"); } } static importPrivateKey(asnKey, algorithm, extractable, keyUsages) { const key = new EdPrivateKey(); key.fromJSON({ crv: algorithm.namedCurve, d: pvtsutils.Convert.ToBase64Url(asnKey.d), }); key.algorithm = Object.assign({}, algorithm); key.extractable = extractable; key.usages = keyUsages; return key; } static async importPublicKey(asnKey, algorithm, extractable, keyUsages) { const key = new EdPublicKey(); key.fromJSON({ crv: algorithm.namedCurve, x: pvtsutils.Convert.ToBase64Url(asnKey), }); key.algorithm = Object.assign({}, algorithm); key.extractable = extractable; key.usages = keyUsages; return key; } } EdCrypto.publicKeyUsages = ["verify"]; EdCrypto.privateKeyUsages = ["sign", "deriveKey", "deriveBits"]; class EdDsaProvider extends core__namespace.EdDsaProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await EdCrypto.generateKey({ name: this.name, namedCurve: algorithm.namedCurve.replace(/^ed/i, "Ed"), }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onSign(algorithm, key, data) { return EdCrypto.sign(algorithm, getCryptoKey(key), new Uint8Array(data)); } async onVerify(algorithm, key, signature, data) { return EdCrypto.verify(algorithm, getCryptoKey(key), new Uint8Array(signature), new Uint8Array(data)); } async onExportKey(format, key) { return EdCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } } class EcdhEsProvider extends core__namespace.EcdhEsProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const keys = await EdCrypto.generateKey({ name: this.name, namedCurve: algorithm.namedCurve.toUpperCase(), }, extractable, keyUsages); return { privateKey: setCryptoKey(keys.privateKey), publicKey: setCryptoKey(keys.publicKey), }; } async onDeriveBits(algorithm, baseKey, length) { const bits = await EdCrypto.deriveBits({ ...algorithm, public: getCryptoKey(algorithm.public) }, getCryptoKey(baseKey), length); return bits; } async onExportKey(format, key) { return EdCrypto.exportKey(format, getCryptoKey(key)); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { const key = await EdCrypto.importKey(format, keyData, { ...algorithm, name: this.name }, extractable, keyUsages); return setCryptoKey(key); } } class PbkdfCryptoKey extends CryptoKey { } class Pbkdf2Provider extends core__namespace.Pbkdf2Provider { async onDeriveBits(algorithm, baseKey, length) { return new Promise((resolve, reject) => { const salt = core__namespace.BufferSourceConverter.toArrayBuffer(algorithm.salt); const hash = algorithm.hash.name.replace("-", ""); crypto.pbkdf2(getCryptoKey(baseKey).data, buffer.Buffer.from(salt), algorithm.iterations, length >> 3, hash, (err, derivedBits) => { if (err) { reject(err); } else { resolve(new Uint8Array(derivedBits).buffer); } }); }); } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { if (format === "raw") { const key = new PbkdfCryptoKey(); key.data = buffer.Buffer.from(keyData); key.algorithm = { name: this.name }; key.extractable = false; key.usages = keyUsages; return setCryptoKey(key); } throw new core__namespace.OperationError("format: Must be 'raw'"); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof PbkdfCryptoKey)) { throw new TypeError("key: Is not PBKDF CryptoKey"); } } } class HmacCryptoKey extends CryptoKey { get alg() { const hash = this.algorithm.hash.name.toUpperCase(); return `HS${hash.replace("SHA-", "")}`; } set alg(value) { } } tslib.__decorate([ jsonSchema.JsonProp({ name: "k", converter: JsonBase64UrlConverter }) ], HmacCryptoKey.prototype, "data", void 0); class HmacProvider extends core__namespace.HmacProvider { async onGenerateKey(algorithm, extractable, keyUsages) { const length = ((algorithm.length || this.getDefaultLength(algorithm.hash.name)) >> 3) << 3; const key = new HmacCryptoKey(); key.algorithm = { ...algorithm, length, name: this.name, }; key.extractable = extractable; key.usages = keyUsages; key.data = crypto.randomBytes(length >> 3); return setCryptoKey(key); } async onSign(algorithm, key, data) { const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash); const hmac = crypto .createHmac(cryptoAlg, getCryptoKey(key).data) .update(buffer.Buffer.from(data)) .digest(); return new Uint8Array(hmac).buffer; } async onVerify(algorithm, key, signature, data) { const cryptoAlg = ShaCrypto.getAlgorithmName(key.algorithm.hash); const hmac = crypto .createHmac(cryptoAlg, getCryptoKey(key).data) .update(buffer.Buffer.from(data)) .digest(); return hmac.compare(buffer.Buffer.from(signature)) === 0; } async onImportKey(format, keyData, algorithm, extractable, keyUsages) { let key; switch (format.toLowerCase()) { case "jwk": key = jsonSchema.JsonParser.fromJSON(keyData, { targetSchema: HmacCryptoKey }); break; case "raw": key = new HmacCryptoKey(); key.data = buffer.Buffer.from(keyData); break; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } key.algorithm = { hash: { name: algorithm.hash.name }, name: this.name, length: key.data.length << 3, }; key.extractable = extractable; key.usages = keyUsages; return setCryptoKey(key); } async onExportKey(format, key) { switch (format.toLowerCase()) { case "jwk": return jsonSchema.JsonSerializer.toJSON(getCryptoKey(key)); case "raw": return new Uint8Array(getCryptoKey(key).data).buffer; default: throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'"); } } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof HmacCryptoKey)) { throw new TypeError("key: Is not HMAC CryptoKey"); } } } class HkdfCryptoKey extends CryptoKey { } class HkdfProvider extends core__namespace.HkdfProvider { async onImportKey(format, keyData, algorithm, extractable, keyUsages) { if (format.toLowerCase() !== "raw") { throw new core__namespace.OperationError("Operation not supported"); } const key = new HkdfCryptoKey(); key.data = buffer.Buffer.from(keyData); key.algorithm = { name: this.name }; key.extractable = extractable; key.usages = keyUsages; return setCryptoKey(key); } async onDeriveBits(params, baseKey, length) { const hash = params.hash.name.replace("-", ""); const hashLength = crypto.createHash(hash).digest().length; const byteLength = length / 8; const info = core.BufferSourceConverter.toUint8Array(params.info); const PRK = crypto .createHmac(hash, core.BufferSourceConverter.toUint8Array(params.salt)) .update(core.BufferSourceConverter.toUint8Array(getCryptoKey(baseKey).data)) .digest(); const blocks = [buffer.Buffer.alloc(0)]; const blockCount = Math.ceil(byteLength / hashLength) + 1; for (let i = 1; i < blockCount; ++i) { blocks.push(crypto .createHmac(hash, PRK) .update(buffer.Buffer.concat([blocks[i - 1], info, buffer.Buffer.from([i])])) .digest()); } return buffer.Buffer.concat(blocks).slice(0, byteLength); } checkCryptoKey(key, keyUsage) { super.checkCryptoKey(key, keyUsage); if (!(getCryptoKey(key) instanceof HkdfCryptoKey)) { throw new TypeError("key: Is not HKDF CryptoKey"); } } } class ShakeCrypto { static digest(algorithm, data) { const hash = crypto .createHash(algorithm.name.toLowerCase(), { outputLength: algorithm.length, }) .update(buffer.Buffer.from(data)) .digest(); return new Uint8Array(hash).buffer; } } class Shake128Provider extends core__namespace.Shake128Provider { async onDigest(algorithm, data) { return ShakeCrypto.digest(algorithm, data); } } class Shake256Provider extends core__namespace.Shake256Provider { async onDigest(algorithm, data) { return ShakeCrypto.digest(algorithm, data); } } class SubtleCrypto extends core__namespace.SubtleCrypto { constructor() { var _a; super(); this.providers.set(new AesCbcProvider()); this.providers.set(new AesCtrProvider()); this.providers.set(new AesGcmProvider()); this.providers.set(new AesCmacProvider()); this.providers.set(new AesKwProvider()); this.providers.set(new AesEcbProvider()); const ciphers = crypto__namespace.getCiphers(); if (ciphers.includes("des-cbc")) { this.providers.set(new DesCbcProvider()); } this.providers.set(new DesEde3CbcProvider()); this.providers.set(new RsaSsaProvider()); this.providers.set(new RsaPssProvider()); this.providers.set(new RsaOaepProvider()); this.providers.set(new RsaEsProvider()); this.providers.set(new EcdsaProvider()); this.providers.set(new EcdhProvider()); this.providers.set(new Sha1Provider()); this.providers.set(new Sha256Provider()); this.providers.set(new Sha384Provider()); this.providers.set(new Sha512Provider()); this.providers.set(new Pbkdf2Provider()); this.providers.set(new HmacProvider()); this.providers.set(new HkdfProvider()); const nodeMajorVersion = (_a = /^v(\d+)/.exec(process__namespace.version)) === null || _a === void 0 ? void 0 : _a[1]; if (nodeMajorVersion && parseInt(nodeMajorVersion, 10) >= 12) { this.providers.set(new Shake128Provider()); this.providers.set(new Shake256Provider()); } const hashes = crypto__namespace.getHashes(); if (hashes.includes("sha3-256")) { this.providers.set(new Sha3256Provider()); } if (hashes.includes("sha3-384")) { this.providers.set(new Sha3384Provider()); } if (hashes.includes("sha3-512")) { this.providers.set(new Sha3512Provider()); } if (nodeMajorVersion && parseInt(nodeMajorVersion, 10) >= 14) { this.providers.set(new EdDsaProvider()); this.providers.set(new EcdhEsProvider()); } } } class Crypto extends core__namespace.Crypto { constructor() { super(...arguments); this.subtle = new SubtleCrypto(); } getRandomValues(array) { if (!ArrayBuffer.isView(array)) { throw new TypeError("Failed to execute 'getRandomValues' on 'Crypto': parameter 1 is not of type 'ArrayBufferView'"); } const buffer$1 = buffer.Buffer.from(array.buffer, array.byteOffset, array.byteLength); crypto.randomFillSync(buffer$1); return array; } } Object.defineProperty(exports, 'CryptoKey', { enumerable: true, get: function () { return core.CryptoKey; } }); exports.Crypto = Crypto;