webcrypto-liner
Version:
A WebCrypto polyfill that "smooths out" the rough-edges in existing User Agent implementations.
1,266 lines (1,235 loc) • 96.1 kB
JavaScript
/**
* Copyright (c) 2024, Peculiar Ventures, LLC.
*/
'use strict';
var core = require('webcrypto-core');
var tslib = require('tslib');
var asn1Schema = require('@peculiar/asn1-schema');
var jsonSchema = require('@peculiar/json-schema');
var pvtsutils = require('pvtsutils');
var asmCrypto = require('asmcrypto.js');
var elliptic = require('elliptic');
var sha3 = require('@stablelib/sha3');
var des = require('des.js');
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 asmCrypto__namespace = /*#__PURE__*/_interopNamespaceDefault(asmCrypto);
var elliptic__namespace = /*#__PURE__*/_interopNamespaceDefault(elliptic);
var des__namespace = /*#__PURE__*/_interopNamespaceDefault(des);
let window = {};
if (typeof self !== "undefined") {
window = self;
}
exports.nativeCrypto = window["msCrypto"]
|| window.crypto
|| {};
exports.nativeSubtle = null;
try {
exports.nativeSubtle = (exports.nativeCrypto === null || exports.nativeCrypto === void 0 ? void 0 : exports.nativeCrypto.subtle) || (exports.nativeCrypto === null || exports.nativeCrypto === void 0 ? void 0 : exports.nativeCrypto["webkitSubtle"]) || null;
}
catch (err) {
console.warn("Cannot get subtle from crypto", err);
}
function setCrypto(crypto) {
exports.nativeCrypto = crypto;
exports.nativeSubtle = crypto.subtle;
}
class Debug {
static get enabled() {
return typeof self !== "undefined" && self.PV_WEBCRYPTO_LINER_LOG;
}
static log(...args) {
if (this.enabled) {
console.log(...args);
}
}
static error(...args) {
if (this.enabled) {
console.error(...args);
}
}
static info(...args) {
if (this.enabled) {
console.info(...args);
}
}
static warn(...args) {
if (this.enabled) {
console.warn(...args);
}
}
static trace(...args) {
if (this.enabled) {
console.trace(...args);
}
}
}
var Browser;
(function (Browser) {
Browser["Unknown"] = "Unknown";
Browser["IE"] = "Internet Explorer";
Browser["Safari"] = "Safari";
Browser["Edge"] = "Edge";
Browser["Chrome"] = "Chrome";
Browser["Firefox"] = "Firefox Mozilla";
Browser["Mobile"] = "Mobile";
})(Browser || (Browser = {}));
function BrowserInfo() {
const res = {
name: Browser.Unknown,
version: "0",
};
if (typeof self === "undefined") {
return res;
}
const userAgent = self.navigator.userAgent;
const reg = /edge\/([\d.]+)/i.exec(userAgent);
if (reg) {
res.name = Browser.Edge;
res.version = reg[1];
}
else if (/msie/i.test(userAgent)) {
res.name = Browser.IE;
res.version = /msie ([\d.]+)/i.exec(userAgent)[1];
}
else if (/Trident/i.test(userAgent)) {
res.name = Browser.IE;
res.version = /rv:([\d.]+)/i.exec(userAgent)[1];
}
else if (/chrome/i.test(userAgent)) {
res.name = Browser.Chrome;
res.version = /chrome\/([\d.]+)/i.exec(userAgent)[1];
}
else if (/firefox/i.test(userAgent)) {
res.name = Browser.Firefox;
res.version = /firefox\/([\d.]+)/i.exec(userAgent)[1];
}
else if (/mobile/i.test(userAgent)) {
res.name = Browser.Mobile;
res.version = /mobile\/([\w]+)/i.exec(userAgent)[1];
}
else if (/safari/i.test(userAgent)) {
res.name = Browser.Safari;
res.version = /version\/([\d.]+)/i.exec(userAgent)[1];
}
return res;
}
function concat(...buf) {
const res = new Uint8Array(buf.map((item) => item.length).reduce((prev, cur) => prev + cur));
let offset = 0;
buf.forEach((item) => {
for (let i = 0; i < item.length; i++) {
res[offset + i] = item[i];
}
offset += item.length;
});
return res;
}
class CryptoKey extends core__namespace.CryptoKey {
constructor(algorithm, extractable, type, usages) {
super();
this.extractable = extractable;
this.type = type;
this.usages = usages;
this.algorithm = Object.assign({}, algorithm);
}
}
function isAlgorithm(algorithm, name) {
return algorithm.name.toUpperCase() === name.toUpperCase();
}
class AesCryptoKey extends CryptoKey {
constructor(algorithm, extractable, usages, raw) {
super(algorithm, extractable, "secret", usages);
this.raw = raw;
}
toJSON() {
const jwk = {
kty: "oct",
alg: this.getJwkAlgorithm(),
k: pvtsutils.Convert.ToBase64Url(this.raw),
ext: this.extractable,
key_ops: this.usages,
};
return jwk;
}
getJwkAlgorithm() {
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-ECB":
return `A${this.algorithm.length}ECB`;
default:
throw new core__namespace.AlgorithmError("Unsupported algorithm name");
}
}
}
class AesCrypto {
static checkCryptoKey(key) {
if (!(key instanceof AesCryptoKey)) {
throw new TypeError("key: Is not AesCryptoKey");
}
}
static generateKey(algorithm, extractable, usages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const raw = exports.nativeCrypto.getRandomValues(new Uint8Array(algorithm.length / 8));
return new AesCryptoKey(algorithm, extractable, usages, raw);
});
}
static encrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return this.cipher(algorithm, key, core__namespace.BufferSourceConverter.toUint8Array(data), true);
});
}
static decrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return this.cipher(algorithm, key, core__namespace.BufferSourceConverter.toUint8Array(data), false);
});
}
static exportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
switch (format) {
case "jwk":
return key.toJSON();
case "raw":
return key.raw.buffer;
default:
throw new core__namespace.OperationError("format: Must be 'jwk' or 'raw'");
}
});
}
static importKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
let raw;
if (core__namespace.isJWK(keyData)) {
raw = pvtsutils.Convert.FromBase64Url(keyData.k);
}
else {
raw = core__namespace.BufferSourceConverter.toArrayBuffer(keyData);
}
switch (raw.byteLength << 3) {
case 128:
case 192:
case 256:
break;
default:
throw new core__namespace.OperationError("keyData: Is wrong key length");
}
const key = new AesCryptoKey({ name: algorithm.name, length: raw.byteLength << 3 }, extractable, keyUsages, new Uint8Array(raw));
return key;
});
}
static cipher(algorithm, key, data, encrypt) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const action = encrypt ? "encrypt" : "decrypt";
let result;
if (isAlgorithm(algorithm, AesCrypto.AesCBC)) {
const iv = core__namespace.BufferSourceConverter.toUint8Array(algorithm.iv);
result = asmCrypto__namespace.AES_CBC[action](data, key.raw, undefined, iv);
}
else if (isAlgorithm(algorithm, AesCrypto.AesGCM)) {
const iv = core__namespace.BufferSourceConverter.toUint8Array(algorithm.iv);
let additionalData;
if (algorithm.additionalData) {
additionalData = core__namespace.BufferSourceConverter.toUint8Array(algorithm.additionalData);
}
const tagLength = (algorithm.tagLength || 128) / 8;
result = asmCrypto__namespace.AES_GCM[action](data, key.raw, iv, additionalData, tagLength);
}
else if (isAlgorithm(algorithm, AesCrypto.AesECB)) {
result = asmCrypto__namespace.AES_ECB[action](data, key.raw, true);
}
else {
throw new core__namespace.OperationError(`algorithm: Is not recognized`);
}
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
}
AesCrypto.AesCBC = "AES-CBC";
AesCrypto.AesECB = "AES-ECB";
AesCrypto.AesGCM = "AES-GCM";
class AesCbcProvider extends core__namespace.AesCbcProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.encrypt(algorithm, key, data);
});
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.decrypt(algorithm, key, data);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
AesCrypto.checkCryptoKey(key);
}
}
class AesEcbProvider extends core__namespace.AesEcbProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.encrypt(algorithm, key, data);
});
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.decrypt(algorithm, key, data);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
AesCrypto.checkCryptoKey(key);
}
}
class AesGcmProvider extends core__namespace.AesGcmProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.encrypt(algorithm, key, data);
});
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.decrypt(algorithm, key, data);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
AesCrypto.checkCryptoKey(key);
}
}
class AesCtrProvider extends core__namespace.AesCtrProvider {
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const result = new asmCrypto__namespace.AES_CTR(key.raw, core__namespace.BufferSourceConverter.toUint8Array(algorithm.counter))
.encrypt(core__namespace.BufferSourceConverter.toUint8Array(data));
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const result = new asmCrypto__namespace.AES_CTR(key.raw, core__namespace.BufferSourceConverter.toUint8Array(algorithm.counter))
.decrypt(core__namespace.BufferSourceConverter.toUint8Array(data));
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return AesCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
AesCrypto.checkCryptoKey(key);
}
}
class AesKwProvider extends core__namespace.AesKwProvider {
onEncrypt(_algorithm, _key, _data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
throw new Error("Method not implemented.");
});
}
onDecrypt(_algorithm, _key, _data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
throw new Error("Method not implemented.");
});
}
onGenerateKey(_algorithm, _extractable, _keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
throw new Error("Method not implemented.");
});
}
onExportKey(_format, _key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
throw new Error("Method not implemented.");
});
}
onImportKey(_format, _keyData, _algorithm, _extractable, _keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
throw new Error("Method not implemented.");
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
AesCrypto.checkCryptoKey(key);
}
}
class RsaCryptoKey extends CryptoKey {
constructor(algorithm, extractable, type, usages, data) {
super(algorithm, extractable, type, usages);
this.data = data;
}
}
class RsaCrypto {
static checkCryptoKey(key) {
if (!(key instanceof RsaCryptoKey)) {
throw new TypeError("key: Is not RsaCryptoKey");
}
}
static generateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const alg = {
name: "RSA-PSS",
hash: "SHA-256",
publicExponent: algorithm.publicExponent,
modulusLength: algorithm.modulusLength,
};
const keys = (yield exports.nativeSubtle.generateKey(alg, true, ["sign", "verify"]));
const crypto = new Crypto();
const pkcs8 = yield crypto.subtle.exportKey("pkcs8", keys.privateKey);
const privateKey = yield crypto.subtle.importKey("pkcs8", pkcs8, algorithm, extractable, keyUsages.filter((o) => this.privateUsages.includes(o)));
const spki = yield crypto.subtle.exportKey("spki", keys.publicKey);
const publicKey = yield crypto.subtle.importKey("spki", spki, algorithm, true, keyUsages.filter((o) => this.publicUsages.includes(o)));
return { privateKey, publicKey };
});
}
static exportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
switch (format) {
case "pkcs8":
return this.exportPkcs8Key(key);
case "spki":
return this.exportSpkiKey(key);
case "jwk":
return this.exportJwkKey(key);
default:
throw new core__namespace.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
}
});
}
static importKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
let asmKey;
switch (format) {
case "pkcs8":
asmKey = this.importPkcs8Key(keyData);
break;
case "spki":
asmKey = this.importSpkiKey(keyData);
break;
case "jwk":
asmKey = this.importJwkKey(keyData);
break;
default:
throw new core__namespace.OperationError("format: Must be 'jwk', 'pkcs8' or 'spki'");
}
const key = new RsaCryptoKey(Object.assign({ publicExponent: asmKey[1][1] === 1
? asmKey[1].slice(1)
: asmKey[1].slice(3), modulusLength: asmKey[0].byteLength << 3 }, algorithm), extractable, asmKey.length === 2 ? "public" : "private", keyUsages, asmKey);
return key;
});
}
static randomNonZeroValues(data) {
data = exports.nativeCrypto.getRandomValues(data);
return data.map((n) => {
while (!n) {
n = exports.nativeCrypto.getRandomValues(new Uint8Array(1))[0];
}
return n;
});
}
static exportPkcs8Key(key) {
const keyInfo = new core__namespace.asn1.PrivateKeyInfo();
keyInfo.privateKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
keyInfo.privateKeyAlgorithm.parameters = null;
keyInfo.privateKey = asn1Schema.AsnConvert.serialize(this.exportAsmKey(key.data));
return asn1Schema.AsnConvert.serialize(keyInfo);
}
static importPkcs8Key(data) {
const keyInfo = asn1Schema.AsnConvert.parse(data, core__namespace.asn1.PrivateKeyInfo);
const privateKey = asn1Schema.AsnConvert.parse(keyInfo.privateKey, core__namespace.asn1.RsaPrivateKey);
return this.importAsmKey(privateKey);
}
static importSpkiKey(data) {
const keyInfo = asn1Schema.AsnConvert.parse(data, core__namespace.asn1.PublicKeyInfo);
const publicKey = asn1Schema.AsnConvert.parse(keyInfo.publicKey, core__namespace.asn1.RsaPublicKey);
return this.importAsmKey(publicKey);
}
static exportSpkiKey(key) {
const publicKey = new core__namespace.asn1.RsaPublicKey();
publicKey.modulus = key.data[0].buffer;
publicKey.publicExponent = key.data[1][1] === 1
? key.data[1].buffer.slice(1)
: key.data[1].buffer.slice(3);
const keyInfo = new core__namespace.asn1.PublicKeyInfo();
keyInfo.publicKeyAlgorithm.algorithm = "1.2.840.113549.1.1.1";
keyInfo.publicKeyAlgorithm.parameters = null;
keyInfo.publicKey = asn1Schema.AsnConvert.serialize(publicKey);
return asn1Schema.AsnConvert.serialize(keyInfo);
}
static importJwkKey(data) {
let key;
if (data.d) {
key = jsonSchema.JsonParser.fromJSON(data, { targetSchema: core__namespace.asn1.RsaPrivateKey });
}
else {
key = jsonSchema.JsonParser.fromJSON(data, { targetSchema: core__namespace.asn1.RsaPublicKey });
}
return this.importAsmKey(key);
}
static exportJwkKey(key) {
const asnKey = this.exportAsmKey(key.data);
const jwk = jsonSchema.JsonSerializer.toJSON(asnKey);
jwk.ext = true;
jwk.key_ops = key.usages;
jwk.kty = "RSA";
jwk.alg = this.getJwkAlgorithm(key.algorithm);
return jwk;
}
static 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 "RSAES-PKCS1-V1_5":
return `PS1`;
default:
throw new core__namespace.OperationError("algorithm: Is not recognized");
}
}
static exportAsmKey(asmKey) {
let key;
if (asmKey.length > 2) {
const privateKey = new core__namespace.asn1.RsaPrivateKey();
privateKey.privateExponent = asmKey[2].buffer;
privateKey.prime1 = asmKey[3].buffer;
privateKey.prime2 = asmKey[4].buffer;
privateKey.exponent1 = asmKey[5].buffer;
privateKey.exponent2 = asmKey[6].buffer;
privateKey.coefficient = asmKey[7].buffer;
key = privateKey;
}
else {
key = new core__namespace.asn1.RsaPublicKey();
}
key.modulus = asmKey[0].buffer;
key.publicExponent = asmKey[1][1] === 1
? asmKey[1].buffer.slice(1)
: asmKey[1].buffer.slice(3);
return key;
}
static importAsmKey(key) {
const expPadding = new Uint8Array(4 - key.publicExponent.byteLength);
const asmKey = [
new Uint8Array(key.modulus),
concat(expPadding, new Uint8Array(key.publicExponent)),
];
if (key instanceof core__namespace.asn1.RsaPrivateKey) {
asmKey.push(new Uint8Array(key.privateExponent));
asmKey.push(new Uint8Array(key.prime1));
asmKey.push(new Uint8Array(key.prime2));
asmKey.push(new Uint8Array(key.exponent1));
asmKey.push(new Uint8Array(key.exponent2));
asmKey.push(new Uint8Array(key.coefficient));
}
return asmKey;
}
}
RsaCrypto.RsaSsa = "RSASSA-PKCS1-v1_5";
RsaCrypto.RsaPss = "RSA-PSS";
RsaCrypto.RsaOaep = "RSA-OAEP";
RsaCrypto.privateUsages = ["sign", "decrypt", "unwrapKey"];
RsaCrypto.publicUsages = ["verify", "encrypt", "wrapKey"];
class ShaCrypto {
static getDigest(name) {
switch (name) {
case "SHA-1":
return new asmCrypto__namespace.Sha1();
case "SHA-256":
return new asmCrypto__namespace.Sha256();
case "SHA-512":
return new asmCrypto__namespace.Sha512();
default:
throw new core__namespace.AlgorithmError("keyAlgorithm.hash: Is not recognized");
}
}
static digest(algorithm, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const mech = this.getDigest(algorithm.name);
const result = mech
.process(core__namespace.BufferSourceConverter.toUint8Array(data))
.finish().result;
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
}
class RsaOaepProvider extends core__namespace.RsaOaepProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return this.cipher(algorithm, key, data);
});
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return this.cipher(algorithm, key, data);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
RsaCrypto.checkCryptoKey(key);
}
cipher(algorithm, key, data) {
const digest = ShaCrypto.getDigest(key.algorithm.hash.name);
let label;
if (algorithm.label) {
label = core__namespace.BufferSourceConverter.toUint8Array(algorithm.label);
}
const cipher = new asmCrypto__namespace.RSA_OAEP(key.data, digest, label);
let res;
const u8Data = core__namespace.BufferSourceConverter.toUint8Array(data);
if (key.type === "public") {
res = cipher.encrypt(u8Data);
}
else {
res = cipher.decrypt(u8Data);
}
return core__namespace.BufferSourceConverter.toArrayBuffer(res);
}
}
class RsaPssProvider extends core__namespace.RsaPssProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
onSign(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const rsa = new asmCrypto__namespace.RSA_PSS(key.data, ShaCrypto.getDigest(key.algorithm.hash.name), algorithm.saltLength);
const result = rsa.sign(core__namespace.BufferSourceConverter.toUint8Array(data));
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
onVerify(algorithm, key, signature, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const rsa = new asmCrypto__namespace.RSA_PSS(key.data, ShaCrypto.getDigest(key.algorithm.hash.name), algorithm.saltLength);
try {
rsa.verify(core__namespace.BufferSourceConverter.toUint8Array(signature), core__namespace.BufferSourceConverter.toUint8Array(data));
}
catch (_a) {
return false;
}
return true;
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
RsaCrypto.checkCryptoKey(key);
}
}
class RsaSsaProvider extends core__namespace.RsaSsaProvider {
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
onSign(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const rsa = new asmCrypto__namespace.RSA_PKCS1_v1_5(key.data, ShaCrypto.getDigest(key.algorithm.hash.name));
const result = rsa.sign(core__namespace.BufferSourceConverter.toUint8Array(data));
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
onVerify(algorithm, key, signature, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const rsa = new asmCrypto__namespace.RSA_PKCS1_v1_5(key.data, ShaCrypto.getDigest(key.algorithm.hash.name));
try {
rsa.verify(core__namespace.BufferSourceConverter.toUint8Array(signature), core__namespace.BufferSourceConverter.toUint8Array(data));
}
catch (_a) {
return false;
}
return true;
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
RsaCrypto.checkCryptoKey(key);
}
}
class RsaEsProvider extends core__namespace.ProviderCrypto {
constructor() {
super(...arguments);
this.name = "RSAES-PKCS1-v1_5";
this.usages = {
publicKey: ["encrypt", "wrapKey"],
privateKey: ["decrypt", "unwrapKey"],
};
this.hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"];
}
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
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");
}
}
onDecrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const EM = new asmCrypto__namespace.RSA(key.data).decrypt(new asmCrypto__namespace.BigNumber(core__namespace.BufferSourceConverter.toUint8Array(data))).result;
const k = key.algorithm.modulusLength >> 3;
if (data.byteLength !== k) {
throw new core__namespace.CryptoError("Decryption error. Encrypted message size doesn't match to key length");
}
let offset = 0;
if (EM[offset++] || EM[offset++] !== 2) {
throw new core__namespace.CryptoError("Decryption error");
}
do {
if (EM[offset++] === 0) {
break;
}
} while (offset < EM.length);
if (offset < 11) {
throw new core__namespace.CryptoError("Decryption error. PS is less than 8 octets.");
}
if (offset === EM.length) {
throw new core__namespace.CryptoError("Decryption error. There is no octet with hexadecimal value 0x00 to separate PS from M");
}
return EM.buffer.slice(offset);
});
}
onEncrypt(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const k = key.algorithm.modulusLength >> 3;
if (data.byteLength > k - 11) {
throw new core__namespace.CryptoError("Message too long");
}
const psLen = k - data.byteLength - 3;
const PS = RsaCrypto.randomNonZeroValues(new Uint8Array(psLen));
const EM = new Uint8Array(k);
EM[0] = 0;
EM[1] = 2;
EM.set(PS, 2);
EM[2 + psLen] = 0;
EM.set(new Uint8Array(data), 3 + psLen);
const result = new asmCrypto__namespace.RSA(key.data).encrypt(new asmCrypto__namespace.BigNumber(EM)).result;
return core__namespace.BufferSourceConverter.toArrayBuffer(result);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return RsaCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
const key = yield RsaCrypto.importKey(format, keyData, Object.assign(Object.assign({}, algorithm), { name: this.name }), extractable, keyUsages);
return key;
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
RsaCrypto.checkCryptoKey(key);
}
}
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",
"1.3.36.3.3.2.8.1.1.7": "brainpoolP256r1",
"brainpoolP256r1": "1.3.36.3.3.2.8.1.1.7",
"1.3.36.3.3.2.8.1.1.11": "brainpoolP384r1",
"brainpoolP384r1": "1.3.36.3.3.2.8.1.1.11",
"1.3.36.3.3.2.8.1.1.13": "brainpoolP512r1",
"brainpoolP512r1": "1.3.36.3.3.2.8.1.1.13",
};
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 EcCryptoKey extends CryptoKey {
constructor(algorithm, extractable, type, usages, data) {
super(algorithm, extractable, type, usages);
this.data = data;
}
}
class EcCrypto {
static checkLib() {
if (typeof (elliptic__namespace) === "undefined") {
throw new core__namespace.OperationError("Cannot implement EC mechanism. Add 'https://peculiarventures.github.io/pv-webcrypto-tests/src/elliptic.js' script to your project");
}
}
static generateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
this.checkLib();
const key = this.initEcKey(algorithm.namedCurve);
const ecKey = key.genKeyPair();
ecKey.getPublic();
const prvKey = new EcCryptoKey(Object.assign({}, algorithm), extractable, "private", keyUsages.filter((usage) => ~this.privateUsages.indexOf(usage)), ecKey);
const pubKey = new EcCryptoKey(Object.assign({}, algorithm), true, "public", keyUsages.filter((usage) => ~this.publicUsages.indexOf(usage)), ecKey);
return {
privateKey: prvKey,
publicKey: pubKey,
};
});
}
static checkCryptoKey(key) {
if (!(key instanceof EcCryptoKey)) {
throw new TypeError("key: Is not EcCryptoKey");
}
}
static concat(...buf) {
const res = new Uint8Array(buf.map((item) => item.length).reduce((prev, cur) => prev + cur));
let offset = 0;
buf.forEach((item) => {
for (let i = 0; i < item.length; i++) {
res[offset + i] = item[i];
}
offset += item.length;
});
return res;
}
static exportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
this.checkLib();
switch (format) {
case "pkcs8":
return this.exportPkcs8Key(key);
case "spki":
return this.exportSpkiKey(key);
case "jwk":
return this.exportJwkKey(key);
case "raw":
return new Uint8Array(key.data.getPublic("der")).buffer;
default:
throw new core__namespace.OperationError("format: Must be 'jwk', 'raw, 'pkcs8' or 'spki'");
}
});
}
static importKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
this.checkLib();
let ecKey;
switch (format) {
case "pkcs8":
ecKey = this.importPkcs8Key(keyData, algorithm.namedCurve);
break;
case "spki":
ecKey = this.importSpkiKey(keyData, algorithm.namedCurve);
break;
case "raw":
ecKey = this.importEcKey(new core__namespace.asn1.EcPublicKey(keyData), algorithm.namedCurve);
break;
case "jwk":
ecKey = this.importJwkKey(keyData);
break;
default:
throw new core__namespace.OperationError("format: Must be 'jwk', 'raw', 'pkcs8' or 'spki'");
}
const key = new EcCryptoKey(Object.assign({}, algorithm), extractable, ecKey.priv ? "private" : "public", keyUsages, ecKey);
return key;
});
}
static getNamedCurve(wcNamedCurve) {
const crv = wcNamedCurve.toUpperCase();
let res = "";
if (["P-256", "P-384", "P-521"].indexOf(crv) > -1) {
res = crv.replace("-", "").toLowerCase();
}
else if (crv === "K-256") {
res = "secp256k1";
}
else if (["brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"].includes(wcNamedCurve)) {
res = wcNamedCurve;
}
else {
throw new core__namespace.OperationError(`Unsupported named curve '${wcNamedCurve}'`);
}
return res;
}
static initEcKey(namedCurve) {
return elliptic__namespace.ec(this.getNamedCurve(namedCurve));
}
static exportPkcs8Key(key) {
const keyInfo = new core__namespace.asn1.PrivateKeyInfo();
keyInfo.privateKeyAlgorithm.algorithm = this.ASN_ALGORITHM;
keyInfo.privateKeyAlgorithm.parameters = asn1Schema.AsnConvert.serialize(new core__namespace.asn1.ObjectIdentifier(getOidByNamedCurve$1(key.algorithm.namedCurve)));
keyInfo.privateKey = asn1Schema.AsnConvert.serialize(this.exportEcKey(key));
return asn1Schema.AsnConvert.serialize(keyInfo);
}
static importPkcs8Key(data, namedCurve) {
const keyInfo = asn1Schema.AsnConvert.parse(data, core__namespace.asn1.PrivateKeyInfo);
const privateKey = asn1Schema.AsnConvert.parse(keyInfo.privateKey, core__namespace.asn1.EcPrivateKey);
return this.importEcKey(privateKey, namedCurve);
}
static importSpkiKey(data, namedCurve) {
const keyInfo = asn1Schema.AsnConvert.parse(data, core__namespace.asn1.PublicKeyInfo);
const publicKey = new core__namespace.asn1.EcPublicKey(keyInfo.publicKey);
return this.importEcKey(publicKey, namedCurve);
}
static exportSpkiKey(key) {
const publicKey = new core__namespace.asn1.EcPublicKey(new Uint8Array(key.data.getPublic("der")).buffer);
const keyInfo = new core__namespace.asn1.PublicKeyInfo();
keyInfo.publicKeyAlgorithm.algorithm = this.ASN_ALGORITHM;
keyInfo.publicKeyAlgorithm.parameters = asn1Schema.AsnConvert.serialize(new core__namespace.asn1.ObjectIdentifier(getOidByNamedCurve$1(key.algorithm.namedCurve)));
keyInfo.publicKey = publicKey.value;
return asn1Schema.AsnConvert.serialize(keyInfo);
}
static importJwkKey(data) {
let key;
if (data.d) {
key = jsonSchema.JsonParser.fromJSON(data, { targetSchema: core__namespace.asn1.EcPrivateKey });
}
else {
key = jsonSchema.JsonParser.fromJSON(data, { targetSchema: core__namespace.asn1.EcPublicKey });
}
return this.importEcKey(key, data.crv);
}
static exportJwkKey(key) {
const asnKey = this.exportEcKey(key);
const jwk = jsonSchema.JsonSerializer.toJSON(asnKey);
jwk.ext = true;
jwk.key_ops = key.usages;
jwk.crv = key.algorithm.namedCurve;
jwk.kty = "EC";
return jwk;
}
static exportEcKey(ecKey) {
if (ecKey.type === "private") {
const privateKey = new core__namespace.asn1.EcPrivateKey();
const point = new Uint8Array(ecKey.data.getPrivate("der").toArray());
const pointPad = new Uint8Array(this.getPointSize(ecKey.algorithm.namedCurve) - point.length);
privateKey.privateKey = concat(pointPad, point);
privateKey.publicKey = new Uint8Array(ecKey.data.getPublic("der"));
return privateKey;
}
else if (ecKey.data.pub) {
return new core__namespace.asn1.EcPublicKey(new Uint8Array(ecKey.data.getPublic("der")).buffer);
}
else {
throw new Error("Cannot get private or public key");
}
}
static importEcKey(key, namedCurve) {
const ecKey = this.initEcKey(namedCurve);
if (key instanceof core__namespace.asn1.EcPublicKey) {
return ecKey.keyFromPublic(new Uint8Array(key.value));
}
return ecKey.keyFromPrivate(new Uint8Array(key.privateKey));
}
static getPointSize(namedCurve) {
switch (namedCurve) {
case "P-256":
case "K-256":
return 32;
case "P-384":
return 48;
case "P-521":
return 66;
}
throw new Error("namedCurve: Is not recognized");
}
}
EcCrypto.privateUsages = ["sign", "deriveKey", "deriveBits"];
EcCrypto.publicUsages = ["verify"];
EcCrypto.ASN_ALGORITHM = "1.2.840.10045.2.1";
class EcdhProvider extends core__namespace.EcdhProvider {
constructor() {
super(...arguments);
this.namedCurves = ["P-256", "P-384", "P-521", "K-256", "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"];
}
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
onDeriveBits(algorithm, baseKey, length) {
return tslib.__awaiter(this, void 0, void 0, function* () {
EcCrypto.checkLib();
const shared = baseKey.data.derive(algorithm.public.data.getPublic());
let array = new Uint8Array(shared.toArray());
let len = array.length;
len = (len > 32 ? (len > 48 ? 66 : 48) : 32);
if (array.length < len) {
array = EcCrypto.concat(new Uint8Array(len - array.length), array);
}
const buf = array.slice(0, length / 8).buffer;
return buf;
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
EcCrypto.checkCryptoKey(key);
}
}
function b2a(buffer) {
const buf = new Uint8Array(buffer);
const res = [];
for (let i = 0; i < buf.length; i++) {
res.push(buf[i]);
}
return res;
}
class EcdsaProvider extends core__namespace.EcdsaProvider {
constructor() {
super(...arguments);
this.hashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512", "SHA3-256", "SHA3-384", "SHA3-512"];
this.namedCurves = ["P-256", "P-384", "P-521", "K-256", "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"];
}
onGenerateKey(algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.generateKey(algorithm, extractable, keyUsages);
});
}
onExportKey(format, key) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.exportKey(format, key);
});
}
onImportKey(format, keyData, algorithm, extractable, keyUsages) {
return tslib.__awaiter(this, void 0, void 0, function* () {
return EcCrypto.importKey(format, keyData, algorithm, extractable, keyUsages);
});
}
onSign(algorithm, key, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
EcCrypto.checkLib();
const crypto = new Crypto();
const hash = yield crypto.subtle.digest(algorithm.hash, data);
const array = b2a(hash);
const signature = yield key.data.sign(array);
const asnSignature = new core__namespace.asn1.EcDsaSignature();
asnSignature.r = new Uint8Array(signature.r.toArray()).buffer;
asnSignature.s = new Uint8Array(signature.s.toArray()).buffer;
return asnSignature.toWebCryptoSignature();
});
}
onVerify(algorithm, key, signature, data) {
return tslib.__awaiter(this, void 0, void 0, function* () {
EcCrypto.checkLib();
const crypto = new Crypto();
const sig = {
r: new Uint8Array(signature.slice(0, signature.byteLength / 2)),
s: new Uint8Array(signature.slice(signature.byteLength / 2)),
};
const hashedData = yield crypto.subtle.digest(algorithm.hash, data);
const array = b2a(hashedData);
return key.data.verify(array, sig);
});
}
checkCryptoKey(key, keyUsage) {
super.checkCryptoKey(key, keyUsage);
EcCrypto.checkCryptoKey(key);
}
}
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 CryptoKey {
constructor(algorithm, extractable, usages, data) {
super(algorithm, extractable, "private", usages);
this.data = data;
}
toJSON() {
const json = {
kty: "OKP",
crv: this.algorithm.namedCurve,
key_ops: this.usages,
ext: this.extractable,
};
return Object.assign(json, {
d: pvtsutils.Convert.ToBase64Url(pvtsutils.Convert.FromHex(/^ed/i.test(json.crv) ? this.data.getSecret("hex") : this.data.getPrivate("hex"))),
});
}
fromJSON(json) {
if (!json.d) {
throw new core__namespace.OperationError(`Cannot get private data from JWK. Property 'd' is required`);
}
if (!json.crv) {
throw new core__namespace.OperationError(`Cannot get named curve from JWK. Property 'crv' is required`);
}
const hexPrivateKey = pvtsutils.Convert.ToHex(pvtsutils.Convert.FromBase64Url(json.d));
if (/^ed/i.test(json.crv)) {
const eddsa = new elliptic__namespace.eddsa("ed25519");
this.data = eddsa.keyFromSecret(hexPrivateKey);
}
else {
const ecdhEs = elliptic__namespace.ec(json.crv.replace(/^x/i, "curve"));
this.data = ecdhEs.keyFromPrivate(hexPrivateKey, "hex");
}
return this;
}
}
class EdPublicKey extends CryptoKey {
constructor(algorithm, extractable, usages, data) {
super(algorithm, extractable, "public", usages);
this.data = data;
}
toJSON() {
const json = {
kty: "OKP",
crv: this.algorithm.namedCurve,
key_ops: this.usages,
ext: this.extractable,
};
return Object.assign(json, {
x: pvtsutils.Convert.ToBase64Url(pvtsutils.Convert.FromHex(this.data.getPublic("hex"))),
});
}
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_