UNPKG

@harmony-js/crypto

Version:

crypto libraries for harmony

204 lines 9.11 kB
"use strict"; /** * @packageDocumentation * @module harmony-crypto */ Object.defineProperty(exports, "__esModule", { value: true }); exports.decryptPhrase = exports.encryptPhrase = exports.decrypt = exports.encrypt = void 0; var tslib_1 = require("tslib"); var aes_js_1 = tslib_1.__importDefault(require("aes-js")); // import scrypt from 'scrypt.js'; var scrypt_shim_1 = tslib_1.__importDefault(require("scrypt-shim")); var pbkdf2_1 = require("pbkdf2"); var uuid_1 = tslib_1.__importDefault(require("uuid")); var utils_1 = require("@harmony-js/utils"); var random_1 = require("./random"); var keyTool_1 = require("./keyTool"); var bytes_1 = require("./bytes"); var keccak256_1 = require("./keccak256"); /** @hidden */ var DEFAULT_ALGORITHM = 'aes-128-ctr'; /** * getDerivedKey * * NOTE: only scrypt and pbkdf2 are supported. * * @param {Buffer} key - the passphrase * @param {KDF} kdf - the key derivation function to be used * @param {KDFParams} params - params for the kdf * * @returns {Promise<Buffer>} */ function getDerivedKey(key, kdf, params) { return tslib_1.__awaiter(this, void 0, void 0, function () { var salt, _a, c, dklen, _b, n, r, p, dklen; return tslib_1.__generator(this, function (_c) { salt = Buffer.from(params.salt, 'hex'); if (kdf === 'pbkdf2') { _a = params, c = _a.c, dklen = _a.dklen; return [2 /*return*/, pbkdf2_1.pbkdf2Sync(key, salt, c, dklen, 'sha256')]; } if (kdf === 'scrypt') { _b = params, n = _b.n, r = _b.r, p = _b.p, dklen = _b.dklen; return [2 /*return*/, scrypt_shim_1.default(key, salt, n, r, p, dklen)]; } throw new Error('Only pbkdf2 and scrypt are supported'); }); }); } /** * This method will map the current Account object to V3Keystore object. * * @method encrypt * * @param {string} privateKey * @param {string} password * @param {object} options * * @return {{version, id, address, crypto}} */ exports.encrypt = function (privateKey, password, options) { return tslib_1.__awaiter(void 0, void 0, void 0, function () { var address, salt, iv, kdf, level, uuidRandom, n, kdfparams, derivedKey, cipher, ciphertext, mac; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (!utils_1.isPrivateKey(privateKey)) { throw new Error('privateKey is not correct'); } if (typeof password !== 'string') { throw new Error('password is not found'); } address = keyTool_1.getAddressFromPrivateKey(privateKey); salt = random_1.randomBytes(32); iv = Buffer.from(random_1.randomBytes(16), 'hex'); kdf = options !== undefined ? (options.kdf ? options.kdf : 'scrypt') : 'scrypt'; level = options !== undefined ? (options.level ? options.level : 8192) : 8192; uuidRandom = options !== undefined ? options.uuid : undefined; n = kdf === 'pbkdf2' ? 262144 : level; kdfparams = { salt: salt, n: n, r: 8, p: 1, dklen: 32, }; return [4 /*yield*/, getDerivedKey(Buffer.from(password), kdf, kdfparams)]; case 1: derivedKey = _a.sent(); cipher = new aes_js_1.default.ModeOfOperation.ctr(derivedKey.slice(0, 16), new aes_js_1.default.Counter(iv)); if (!cipher) { throw new Error('Unsupported cipher'); } ciphertext = Buffer.from(cipher.encrypt(Buffer.from(privateKey.replace('0x', ''), 'hex'))); mac = keccak256_1.keccak256(bytes_1.concat([derivedKey.slice(16, 32), ciphertext])); return [2 /*return*/, JSON.stringify({ version: 3, id: uuid_1.default.v4({ random: uuidRandom || bytes_1.hexToIntArray(random_1.randomBytes(16)) }), address: address.toLowerCase().replace('0x', ''), crypto: { ciphertext: ciphertext.toString('hex'), cipherparams: { iv: iv.toString('hex'), }, cipher: DEFAULT_ALGORITHM, kdf: kdf, kdfparams: kdfparams, mac: mac.replace('0x', ''), }, })]; } }); }); }; /** * @function decrypt * @param {Keystore} keystore - Keystore file * @param {string} password - password string * @return {string} privateKey */ exports.decrypt = function (keystore, password) { return tslib_1.__awaiter(void 0, void 0, void 0, function () { var ciphertext, iv, kdfparams, derivedKey, mac, CTR, cipher, decrypted; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: ciphertext = Buffer.from(keystore.crypto.ciphertext, 'hex'); iv = Buffer.from(keystore.crypto.cipherparams.iv, 'hex'); kdfparams = keystore.crypto.kdfparams; return [4 /*yield*/, getDerivedKey(Buffer.from(password), keystore.crypto.kdf, kdfparams)]; case 1: derivedKey = _a.sent(); mac = keccak256_1.keccak256(bytes_1.concat([derivedKey.slice(16, 32), ciphertext])).replace('0x', ''); if (mac.toUpperCase() !== keystore.crypto.mac.toUpperCase()) { return [2 /*return*/, Promise.reject(new Error('Failed to decrypt.'))]; } CTR = aes_js_1.default.ModeOfOperation.ctr; cipher = new CTR(derivedKey.slice(0, 16), new aes_js_1.default.Counter(iv)); decrypted = '0x' + Buffer.from(cipher.decrypt(ciphertext)).toString('hex'); return [2 /*return*/, decrypted]; } }); }); }; /** * encrypt Phrase */ exports.encryptPhrase = function (phrase, password, options) { return tslib_1.__awaiter(void 0, void 0, void 0, function () { var salt, iv, kdf, level, uuidRandom, n, kdfparams, derivedKey, cipher, ciphertext, mac; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: if (typeof password !== 'string') { throw new Error('password is not found'); } salt = random_1.randomBytes(32); iv = Buffer.from(random_1.randomBytes(16), 'hex'); kdf = options !== undefined ? (options.kdf ? options.kdf : 'scrypt') : 'scrypt'; level = options !== undefined ? (options.level ? options.level : 8192) : 8192; uuidRandom = options !== undefined ? options.uuid : undefined; n = kdf === 'pbkdf2' ? 262144 : level; kdfparams = { salt: salt, n: n, r: 8, p: 1, dklen: 32, }; return [4 /*yield*/, getDerivedKey(Buffer.from(password), kdf, kdfparams)]; case 1: derivedKey = _a.sent(); cipher = new aes_js_1.default.ModeOfOperation.ctr(derivedKey.slice(0, 16), new aes_js_1.default.Counter(iv)); if (!cipher) { throw new Error('Unsupported cipher'); } ciphertext = Buffer.from(cipher.encrypt(Buffer.from(phrase))); mac = keccak256_1.keccak256(bytes_1.concat([derivedKey.slice(16, 32), ciphertext])); return [2 /*return*/, JSON.stringify({ version: 3, id: uuid_1.default.v4({ random: uuidRandom || bytes_1.hexToIntArray(random_1.randomBytes(16)) }), crypto: { ciphertext: ciphertext.toString('hex'), cipherparams: { iv: iv.toString('hex'), }, cipher: DEFAULT_ALGORITHM, kdf: kdf, kdfparams: kdfparams, mac: mac.replace('0x', ''), }, })]; } }); }); }; /** * decrypt phrase */ exports.decryptPhrase = function (keystore, password) { return tslib_1.__awaiter(void 0, void 0, void 0, function () { var result; return tslib_1.__generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, exports.decrypt(keystore, password)]; case 1: result = _a.sent(); return [2 /*return*/, Buffer.from(result.replace('0x', ''), 'hex').toString()]; } }); }); }; //# sourceMappingURL=keystore.js.map