@fungible-systems/webcrypto-expo
Version:
A WebCrypto Polyfill for Expo (React Native)
839 lines (807 loc) • 31.8 kB
JavaScript
/**
* Copyright (c) 2020 Peculiar Ventures, LLC
*/
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var buffer = require('buffer');
var core = require('webcrypto-core');
var getRandomValues = require('expo-standard-web-crypto/build/getRandomValues');
var tslib = require('tslib');
var jsonSchema = require('@peculiar/json-schema');
var pvtsutils = require('pvtsutils');
var crypto = require('crypto');
require('@peculiar/asn1-schema');
var cryptoSha = require('micro-stacks/crypto-sha');
var cryptoHmacSha = require('micro-stacks/crypto-hmac-sha');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return 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__*/_interopNamespace(core);
var getRandomValues__default = /*#__PURE__*/_interopDefaultLegacy(getRandomValues);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
const JsonBase64UrlConverter = {
fromJSON: (value) => Buffer.from(pvtsutils.Convert.FromBase64Url(value)),
toJSON: (value) => pvtsutils.Convert.ToBase64Url(value),
};
class CryptoKey extends core__namespace.CryptoKey {
constructor() {
super(...arguments);
this.data = 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 })
], CryptoKey.prototype, "alg", void 0);
class SymmetricKey extends CryptoKey {
constructor() {
super(...arguments);
this.kty = 'oct';
this.type = 'secret';
}
}
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);
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 AesCrypto {
static async generateKey(algorithm, extractable, keyUsages) {
const key = new AesCryptoKey();
key.algorithm = algorithm;
key.extractable = extractable;
key.usages = keyUsages;
key.data = crypto__default['default'].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.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.from(data));
case 'AES-CTR':
return this.encryptAesCTR(algorithm, key, Buffer.from(data));
case 'AES-GCM':
return this.encryptAesGCM(algorithm, key, Buffer.from(data));
case 'AES-KW':
return this.encryptAesKW(algorithm, key, Buffer.from(data));
case 'AES-ECB':
return this.encryptAesECB(algorithm, key, 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.from(data));
case 'AES-CTR':
return this.decryptAesCTR(algorithm, key, Buffer.from(data));
case 'AES-GCM':
return this.decryptAesGCM(algorithm, key, Buffer.from(data));
case 'AES-KW':
return this.decryptAesKW(algorithm, key, Buffer.from(data));
case 'AES-ECB':
return this.decryptAesECB(algorithm, key, Buffer.from(data));
default:
throw new core__namespace.OperationError('algorithm: Is not recognized');
}
}
static async encryptAesCBC(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv));
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptAesCBC(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`aes-${key.algorithm.length}-cbc`, key.data, new Uint8Array(algorithm.iv));
let dec = decipher.update(data);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
static async encryptAesCTR(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`aes-${key.algorithm.length}-ctr`, key.data, Buffer.from(algorithm.counter));
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptAesCTR(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`aes-${key.algorithm.length}-ctr`, key.data, new Uint8Array(algorithm.counter));
let dec = decipher.update(data);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
static async encryptAesGCM(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`aes-${key.algorithm.length}-gcm`, key.data, Buffer.from(algorithm.iv), {
authTagLength: (algorithm.tagLength || 128) >> 3,
});
if (algorithm.additionalData) {
cipher.setAAD(Buffer.from(algorithm.additionalData));
}
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final(), cipher.getAuthTag()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptAesGCM(algorithm, key, data) {
const decipher = crypto__default['default'].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.from(algorithm.additionalData));
}
decipher.setAuthTag(tag);
let dec = decipher.update(enc);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
static async encryptAesKW(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV);
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
return new Uint8Array(enc).buffer;
}
static async decryptAesKW(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`id-aes${key.algorithm.length}-wrap`, key.data, this.AES_KW_IV);
let dec = decipher.update(data);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
static async encryptAesECB(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0));
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptAesECB(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`aes-${key.algorithm.length}-ecb`, key.data, new Uint8Array(0));
let dec = decipher.update(data);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
}
AesCrypto.AES_KW_IV = Buffer.from('A6A6A6A6A6A6A6A6', 'hex');
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');
}
}
}
Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 135]);
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__default['default'].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.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.from(data));
case 'DES-EDE3-CBC':
return this.encryptDesEDE3CBC(algorithm, key, 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.from(data));
case 'DES-EDE3-CBC':
return this.decryptDesEDE3CBC(algorithm, key, Buffer.from(data));
default:
throw new core__namespace.OperationError('algorithm: Is not recognized');
}
}
static async encryptDesCBC(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv));
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptDesCBC(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`des-cbc`, key.data, new Uint8Array(algorithm.iv));
let dec = decipher.update(data);
dec = Buffer.concat([dec, decipher.final()]);
return new Uint8Array(dec).buffer;
}
static async encryptDesEDE3CBC(algorithm, key, data) {
const cipher = crypto__default['default'].createCipheriv(`des-ede3-cbc`, key.data, Buffer.from(algorithm.iv));
let enc = cipher.update(data);
enc = Buffer.concat([enc, cipher.final()]);
const res = new Uint8Array(enc).buffer;
return res;
}
static async decryptDesEDE3CBC(algorithm, key, data) {
const decipher = crypto__default['default'].createDecipheriv(`des-ede3-cbc`, key.data, new Uint8Array(algorithm.iv));
let dec = decipher.update(data);
dec = 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');
}
}
}
class ShaCrypto {
static size(algorithm) {
switch (algorithm.name.toUpperCase()) {
case 'SHA-1':
return 160;
case 'SHA-256':
return 256;
case 'SHA-384':
return 384;
case 'SHA-512':
return 512;
default:
throw new Error('Unrecognized name');
}
}
static digest(algorithm, data) {
const hash = crypto__default['default']
.createHash(algorithm.name.replace('-', ''))
.update(Buffer.from(data))
.digest();
return new Uint8Array(hash).buffer;
}
}
({
[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,
});
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 Sha512Provider extends core__namespace.ProviderCrypto {
constructor() {
super(...arguments);
this.name = 'SHA-512';
this.usages = [];
}
async onDigest(algorithm, data) {
return ShaCrypto.digest(algorithm, data);
}
}
class PbkdfCryptoKey extends CryptoKey {
}
const MAX_ALLOC = Math.pow(2, 30) - 1;
function createHasher(alg) {
let normalizedAlg;
if (alg === 'rmd160') {
normalizedAlg = 'ripemd160';
}
else {
normalizedAlg = alg;
}
return (value) => {
switch (normalizedAlg) {
case 'sha256':
return Buffer.from(cryptoSha.hashSha256(value));
case 'sha512':
return Buffer.from(cryptoSha.hashSha512(value));
default: {
return Buffer.from(crypto.createHash(normalizedAlg).update(value).digest());
}
}
};
}
function getZeroes(zeros) {
return Buffer.alloc(zeros);
}
const sizes = {
md5: 16,
sha1: 20,
sha224: 28,
sha256: 32,
sha384: 48,
sha512: 64,
rmd160: 20,
ripemd160: 20,
};
function toBuffer(bufferable) {
if (bufferable instanceof Uint8Array || typeof bufferable === 'string') {
return Buffer.from(bufferable);
}
else {
return Buffer.from(bufferable.buffer);
}
}
class Hmac {
constructor(alg, key, saltLen) {
this.hash = createHasher(alg);
const blocksize = alg === 'sha512' || alg === 'sha384' ? 128 : 64;
if (key.length > blocksize) {
key = this.hash(key);
}
else if (key.length < blocksize) {
key = Buffer.concat([key, getZeroes(blocksize - key.length)], blocksize);
}
const ipad = Buffer.allocUnsafe(blocksize + sizes[alg]);
const opad = Buffer.allocUnsafe(blocksize + sizes[alg]);
for (let i = 0; i < blocksize; i++) {
ipad[i] = key[i] ^ 0x36;
opad[i] = key[i] ^ 0x5c;
}
const ipad1 = Buffer.allocUnsafe(blocksize + saltLen + 4);
ipad.copy(ipad1, 0, 0, blocksize);
this.ipad1 = ipad1;
this.ipad2 = ipad;
this.opad = opad;
this.alg = alg;
this.blocksize = blocksize;
this.size = sizes[alg];
}
run(data, ipad) {
data.copy(ipad, this.blocksize);
const h = this.hash(ipad);
h.copy(this.opad, this.blocksize);
return this.hash(this.opad);
}
}
function pbkdf2Sync(password, salt, iterations, keylen, digest = 'sha1') {
if (typeof iterations !== 'number' || iterations < 0) {
throw new TypeError('Bad iterations');
}
if (typeof keylen !== 'number' || keylen < 0 || keylen > MAX_ALLOC) {
throw new TypeError('Bad key length');
}
const bufferedPassword = toBuffer(password);
const bufferedSalt = toBuffer(salt);
const hmac = new Hmac(digest, bufferedPassword, bufferedSalt.length);
const DK = Buffer.allocUnsafe(keylen);
const block1 = Buffer.allocUnsafe(bufferedSalt.length + 4);
bufferedSalt.copy(block1, 0, 0, bufferedSalt.length);
let destPos = 0;
const hLen = sizes[digest];
const l = Math.ceil(keylen / hLen);
for (let i = 1; i <= l; i++) {
block1.writeUInt32BE(i, bufferedSalt.length);
const T = hmac.run(block1, hmac.ipad1);
let U = T;
for (let j = 1; j < iterations; j++) {
U = hmac.run(U, hmac.ipad2);
for (let k = 0; k < hLen; k++)
T[k] ^= U[k];
}
T.copy(DK, destPos);
destPos += hLen;
}
return DK;
}
function pbkdf2(password, salt, iterations, keylen, digest = 'sha1', callback) {
console.log('pbkdf2');
setTimeout(() => {
let err = null, res;
try {
res = pbkdf2Sync(password, salt, iterations, keylen, digest);
}
catch (e) {
err = e;
}
if (err) {
callback(err);
}
else {
callback(null, res);
}
}, 0);
}
class Pbkdf2Provider extends core__namespace.Pbkdf2Provider {
async onDeriveBits(algorithm, baseKey, length) {
return new Promise((resolve, reject) => {
const salt = Buffer.from(core__namespace.BufferSourceConverter.toArrayBuffer(algorithm.salt));
const digest = algorithm.hash.name.replace('-', '').toLowerCase();
const password = getCryptoKey(baseKey).data;
const iterations = algorithm.iterations;
const keyLength = length >> 3;
pbkdf2(password, salt, iterations, keyLength, digest, (err, derivedBits) => {
if (err)
reject(err);
derivedBits && resolve(new Uint8Array(derivedBits).buffer);
});
});
}
async onImportKey(format, keyData, algorithm, extractable, keyUsages) {
if (format === 'raw') {
const key = new PbkdfCryptoKey();
key.data = 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__default['default'].randomBytes(length >> 3);
return setCryptoKey(key);
}
async onSign(algorithm, key, data) {
const hash = key.algorithm.hash.name.replace('-', '');
let hmac;
if (hash === 'SHA256')
hmac = cryptoHmacSha.hmacSha256Shim(getCryptoKey(key).data, new Uint8Array(data));
if (hash === 'SHA512')
hmac = cryptoHmacSha.hmacSha512Shim(getCryptoKey(key).data, new Uint8Array(data));
if (!hmac)
hmac = crypto__default['default'].createHmac(hash, getCryptoKey(key).data).update(new Uint8Array(data)).digest();
return new Uint8Array(hmac).buffer;
}
async onVerify(algorithm, key, signature, data) {
const hash = key.algorithm.hash.name.replace('-', '');
let hmac;
if (hash === 'SHA256')
hmac = cryptoHmacSha.hmacSha256Shim(getCryptoKey(key).data, new Uint8Array(data));
if (hash === 'SHA512')
hmac = cryptoHmacSha.hmacSha512Shim(getCryptoKey(key).data, new Uint8Array(data));
if (!hmac)
hmac = crypto__default['default'].createHmac(hash, getCryptoKey(key).data).update(new Uint8Array(data)).digest();
return Buffer.from(hmac).compare(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.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 SubtleCrypto extends core__namespace.SubtleCrypto {
constructor() {
super();
this.providers.set(new AesCbcProvider());
this.providers.set(new DesCbcProvider());
this.providers.set(new DesEde3CbcProvider());
this.providers.set(new Sha256Provider());
this.providers.set(new Sha512Provider());
this.providers.set(new Pbkdf2Provider());
this.providers.set(new HmacProvider());
}
}
class Crypto extends core__namespace.Crypto {
constructor() {
super(...arguments);
this.subtle = new SubtleCrypto();
}
getRandomValues(array) {
return getRandomValues__default['default'](array);
}
}
global.Buffer = buffer.Buffer;
Object.defineProperty(exports, 'CryptoKey', {
enumerable: true,
get: function () {
return core.CryptoKey;
}
});
exports.Crypto = Crypto;