UNPKG

blockstack

Version:

The Blockstack Javascript library for authentication, identity, and storage.

124 lines 5.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const cryptoUtils_1 = require("./cryptoUtils"); class NodeCryptoPbkdf2 { constructor(nodePbkdf2) { this.nodePbkdf2 = nodePbkdf2; } derive(password, salt, iterations, keyLength, digest) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (digest !== 'sha512' && digest !== 'sha256') { throw new Error(`Unsupported digest "${digest}" for Pbkdf2`); } return new Promise((resolve, reject) => { this.nodePbkdf2(password, salt, iterations, keyLength, digest, (error, result) => { if (error) { reject(error); } resolve(result); }); }); }); } } exports.NodeCryptoPbkdf2 = NodeCryptoPbkdf2; class WebCryptoPbkdf2 { constructor(subtleCrypto) { this.subtleCrypto = subtleCrypto; } derive(password, salt, iterations, keyLength, digest) { return tslib_1.__awaiter(this, void 0, void 0, function* () { let algo; if (digest === 'sha256') { algo = 'SHA-256'; } else if (digest === 'sha512') { algo = 'SHA-512'; } else { throw new Error(`Unsupported Pbkdf2 digest algorithm "${digest}"`); } let result; const passwordBytes = Buffer.from(password, 'utf8'); try { const key = yield this.subtleCrypto.importKey('raw', passwordBytes, 'PBKDF2', false, ['deriveBits']); result = yield this.subtleCrypto.deriveBits({ name: 'PBKDF2', salt, iterations, hash: { name: algo } }, key, keyLength * 8); } catch (error) { // Browser appears to support WebCrypto but missing pbkdf2 support. const partialWebCrypto = new WebCryptoPartialPbkdf2(this.subtleCrypto); return partialWebCrypto.derive(password, salt, iterations, keyLength, digest); } return Buffer.from(result); }); } } exports.WebCryptoPbkdf2 = WebCryptoPbkdf2; class WebCryptoPartialPbkdf2 { constructor(subtleCrypto) { this.subtleCrypto = subtleCrypto; } derive(password, salt, iterations, keyLength, digest) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (digest !== 'sha512' && digest !== 'sha256') { throw new Error(`Unsupported digest "${digest}" for Pbkdf2`); } const key = Buffer.from(password, 'utf8'); const algo = digest === 'sha512' ? 'SHA-512' : 'SHA-256'; const algoOpts = { name: 'HMAC', hash: algo }; const hmacDigest = (key, data) => this.subtleCrypto .importKey('raw', key, algoOpts, true, ['sign']) .then(cryptoKey => this.subtleCrypto.sign(algoOpts, cryptoKey, data)) .then(result => new Uint8Array(result)); const DK = new Uint8Array(keyLength); const saltLength = salt.length; const block1 = new Uint8Array(saltLength + 4); block1.set(salt); let destPos = 0; const hLen = digest === 'sha512' ? 64 : 32; const l = Math.ceil(keyLength / hLen); function writeUInt32BE(data, value, offset) { value = +value; offset >>>= 0; data[offset] = (value >>> 24); data[offset + 1] = (value >>> 16); data[offset + 2] = (value >>> 8); data[offset + 3] = (value & 0xff); return offset + 4; } for (let i = 1; i <= l; i++) { writeUInt32BE(block1, i, saltLength); // eslint-disable-next-line no-await-in-loop const T = yield hmacDigest(key, block1); let U = T; for (let j = 1; j < iterations; j++) { // eslint-disable-next-line no-await-in-loop U = yield hmacDigest(key, U); for (let k = 0; k < hLen; k++) { T[k] ^= U[k]; } } DK.set(T.subarray(0, DK.byteLength - destPos), destPos); destPos += hLen; } return Buffer.from(DK.buffer); }); } } exports.WebCryptoPartialPbkdf2 = WebCryptoPartialPbkdf2; function createPbkdf2() { return tslib_1.__awaiter(this, void 0, void 0, function* () { const cryptoLib = yield cryptoUtils_1.getCryptoLib(); if (cryptoLib.name === 'subtleCrypto') { return new WebCryptoPbkdf2(cryptoLib.lib); } else { return new NodeCryptoPbkdf2(cryptoLib.lib.pbkdf2); } }); } exports.createPbkdf2 = createPbkdf2; //# sourceMappingURL=pbkdf2.js.map