UNPKG

@meterio/devkit

Version:

Typescript library to aid DApp development on Meter network

406 lines 35.2 kB
'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.encrypt = exports.decrypt = exports.decryptCrowdsale = void 0; const aes_js_1 = __importDefault(require("aes-js")); const scrypt_js_1 = __importDefault(require("scrypt-js")); const uuid_1 = require("uuid"); const signing_key_1 = require("@ethersproject/signing-key"); const hdnode_1 = require("@ethersproject/hdnode"); const address_1 = require("@ethersproject/address"); const utils_1 = require("ethers/lib/utils"); const bytes_1 = require("@ethersproject/bytes"); const pbkdf2_1 = require("@ethersproject/pbkdf2"); const keccak256_1 = require("@ethersproject/keccak256"); const strings_1 = require("@ethersproject/strings"); const random_1 = require("@ethersproject/random"); function looseArrayify(hexString) { if (typeof hexString === 'string' && hexString.substring(0, 2) !== '0x') { hexString = '0x' + hexString; } return (0, bytes_1.arrayify)(hexString); } function zpad(value, length) { value = String(value); while (value.length < length) { value = '0' + value; } return value; } function getPassword(password) { if (typeof password === 'string') { return (0, strings_1.toUtf8Bytes)(password, strings_1.UnicodeNormalizationForm.NFKC); } return (0, bytes_1.arrayify)(password); } // Search an Object and its children recursively, caselessly. function searchPath(object, path) { var currentChild = object; var comps = path.toLowerCase().split('/'); for (var i = 0; i < comps.length; i++) { // Search for a child object with a case-insensitive matching key var matchingChild = null; for (var key in currentChild) { if (key.toLowerCase() === comps[i]) { matchingChild = currentChild[key]; break; } } // Didn't find one. :'( if (matchingChild === null) { return ''; //null; } // Now check this child... currentChild = matchingChild; } return currentChild; } // @TODO: Make a type for string or BytesLike // See: https://github.com/ethereum/pyethsaletool function decryptCrowdsale(json, password) { var data = JSON.parse(json); password = getPassword(password); // Ethereum Address var ethaddr = (0, address_1.getAddress)(searchPath(data, 'ethaddr')); // Encrypted Seed var encseed = looseArrayify(searchPath(data, 'encseed')); if (!encseed || encseed.length % 16 !== 0) { throw new Error('invalid encseed'); } let key = (0, pbkdf2_1.pbkdf2)(password, password, 2000, 32, 'sha256').slice(0, 16); var iv = encseed.slice(0, 16); var encryptedSeed = encseed.slice(16); // Decrypt the seed var aesCbc = new aes_js_1.default.ModeOfOperation.cbc(Buffer.from(key, 'hex'), iv); var seed = (0, bytes_1.arrayify)(aesCbc.decrypt(encryptedSeed)); seed = aes_js_1.default.padding.pkcs7.strip(seed); // This wallet format is weird... Convert the binary encoded hex to a string. var seedHex = ''; for (var i = 0; i < seed.length; i++) { seedHex += String.fromCharCode(seed[i]); } var seedHexBytesLike = (0, strings_1.toUtf8Bytes)(seedHex); const pk = (0, keccak256_1.keccak256)(seedHexBytesLike); var signingKey = new signing_key_1.SigningKey(pk); const signer = (0, utils_1.computeAddress)(pk); if (signer !== ethaddr) { throw new Error('corrupt crowdsale wallet'); } return signingKey; } exports.decryptCrowdsale = decryptCrowdsale; //@TODO: string or BytesLike function decrypt(json, password, progressCallback) { var data = JSON.parse(json); let passwordBytesLike = getPassword(password); var decrypt = function (key, ciphertext) { var cipher = searchPath(data, 'crypto/cipher'); if (cipher === 'aes-128-ctr') { var iv = looseArrayify(searchPath(data, 'crypto/cipherparams/iv')); var counter = new aes_js_1.default.Counter(iv); var aesCtr = new aes_js_1.default.ModeOfOperation.ctr(key, counter); return (0, bytes_1.arrayify)(aesCtr.decrypt(ciphertext)); } return new Uint8Array(); }; var computeMAC = function (derivedHalf, ciphertext) { return (0, keccak256_1.keccak256)((0, bytes_1.concat)([derivedHalf, ciphertext])); }; var getSigningKey = function (key, reject) { var ciphertext = looseArrayify(searchPath(data, 'crypto/ciphertext')); var computedMAC = (0, bytes_1.hexlify)(computeMAC(key.slice(16, 32), ciphertext)).substring(2); if (computedMAC !== searchPath(data, 'crypto/mac').toLowerCase()) { reject(new Error('invalid password')); return null; } var privateKey = decrypt(key.slice(0, 16), ciphertext); var mnemonicKey = key.slice(32, 64); if (!privateKey) { reject(new Error('unsupported cipher')); return null; } var signingKey = new signing_key_1.SigningKey(privateKey); const signer = (0, utils_1.computeAddress)(privateKey); if (signer !== (0, address_1.getAddress)(data.address)) { reject(new Error('address mismatch')); return null; } // Version 0.1 x-ethers metadata must contain an encrypted mnemonic phrase if (searchPath(data, 'x-ethers/version') === '0.1') { var mnemonicCiphertext = looseArrayify(searchPath(data, 'x-ethers/mnemonicCiphertext')); var mnemonicIv = looseArrayify(searchPath(data, 'x-ethers/mnemonicCounter')); var mnemonicCounter = new aes_js_1.default.Counter(mnemonicIv); var mnemonicAesCtr = new aes_js_1.default.ModeOfOperation.ctr(mnemonicKey, mnemonicCounter); var path = searchPath(data, 'x-ethers/path') || hdnode_1.defaultPath; var entropy = (0, bytes_1.arrayify)(mnemonicAesCtr.decrypt(mnemonicCiphertext)); var mnemonic = (0, hdnode_1.entropyToMnemonic)(entropy); var node = hdnode_1.HDNode.fromMnemonic(mnemonic).derivePath(path); if (node.privateKey != (0, bytes_1.hexlify)(privateKey)) { reject(new Error('mnemonic mismatch')); return null; } signingKey = new signing_key_1.SigningKey(node.privateKey); } return signingKey; }; return new Promise(function (resolve, reject) { var kdf = searchPath(data, 'crypto/kdf'); if (kdf && typeof kdf === 'string') { if (kdf.toLowerCase() === 'scrypt') { var salt = looseArrayify(searchPath(data, 'crypto/kdfparams/salt')); var N = parseInt(searchPath(data, 'crypto/kdfparams/n')); var r = parseInt(searchPath(data, 'crypto/kdfparams/r')); var p = parseInt(searchPath(data, 'crypto/kdfparams/p')); if (!N || !r || !p) { reject(new Error('unsupported key-derivation function parameters')); return; } // Make sure N is a power of 2 if ((N & (N - 1)) !== 0) { reject(new Error('unsupported key-derivation function parameter value for N')); return; } var dkLen = parseInt(searchPath(data, 'crypto/kdfparams/dklen')); if (dkLen !== 32) { reject(new Error('unsupported key-derivation derived-key length')); return; } if (progressCallback) { progressCallback(0); } (0, scrypt_js_1.default)(passwordBytesLike, salt, N, r, p, 64, function (error, progress, key) { if (error) { error.progress = progress; reject(error); } else if (key) { key = (0, bytes_1.arrayify)(key); var signingKey = getSigningKey(key, reject); if (!signingKey) { return; } if (progressCallback) { progressCallback(1); } resolve(signingKey); } else if (progressCallback) { return progressCallback(progress); } }); } else if (kdf.toLowerCase() === 'pbkdf2') { var salt = looseArrayify(searchPath(data, 'crypto/kdfparams/salt')); var prfFunc = null; var prf = searchPath(data, 'crypto/kdfparams/prf'); if (prf === 'hmac-sha256') { prfFunc = 'sha256'; } else if (prf === 'hmac-sha512') { prfFunc = 'sha512'; } else { reject(new Error('unsupported prf')); return; } var c = parseInt(searchPath(data, 'crypto/kdfparams/c')); var dkLen = parseInt(searchPath(data, 'crypto/kdfparams/dklen')); if (dkLen !== 32) { reject(new Error('unsupported key-derivation derived-key length')); return; } var key = (0, pbkdf2_1.pbkdf2)(passwordBytesLike, salt, c, dkLen, prfFunc); var signingKey = getSigningKey(Buffer.from(key, 'hex'), reject); if (!signingKey) { return; } resolve(signingKey); } else { reject(new Error('unsupported key-derivation function')); } } else { reject(new Error('unsupported key-derivation function')); } }); } exports.decrypt = decrypt; function encrypt(privateKey, password, options, progressCallback) { // the options are optional, so adjust the call as needed if (typeof options === 'function' && !progressCallback) { progressCallback = options; options = {}; } if (!options) { options = {}; } // Check the private key let privateKeyBytesLike; if (signing_key_1.SigningKey.isSigningKey(privateKey)) { privateKeyBytesLike = (0, bytes_1.arrayify)(privateKey.privateKey); } else { privateKeyBytesLike = (0, bytes_1.arrayify)(privateKey); } if (privateKeyBytesLike.length !== 32) { throw new Error('invalid private key'); } let passwordBytesLike = getPassword(password); let entropy = null; if (options.entropy) { entropy = (0, bytes_1.arrayify)(options.entropy); } if (options.mnemonic) { if (entropy) { if ((0, hdnode_1.entropyToMnemonic)(entropy) !== options.mnemonic) { throw new Error('entropy and mnemonic mismatch'); } } else { entropy = (0, bytes_1.arrayify)((0, hdnode_1.mnemonicToEntropy)(options.mnemonic)); } } var path = options.path; if (entropy && !path) { path = hdnode_1.defaultPath; } var client = options.client; if (!client) { client = 'ethers.js'; } // Check/generate the salt let salt; if (options.salt) { salt = (0, bytes_1.arrayify)(options.salt); } else { salt = (0, random_1.randomBytes)(32); } // Override initialization vector let iv; if (options.iv) { iv = (0, bytes_1.arrayify)(options.iv); if (iv.length !== 16) { throw new Error('invalid iv'); } } else { iv = (0, random_1.randomBytes)(16); } // Override the uuid let uuidRandom; if (options.uuid) { uuidRandom = (0, bytes_1.arrayify)(options.uuid); if (uuidRandom.length !== 16) { throw new Error('invalid uuid'); } } else { uuidRandom = (0, random_1.randomBytes)(16); } // Override the scrypt password-based key derivation function parameters var N = 1 << 17, r = 8, p = 1; if (options.scrypt) { if (options.scrypt.N) { N = options.scrypt.N; } if (options.scrypt.r) { r = options.scrypt.r; } if (options.scrypt.p) { p = options.scrypt.p; } } return new Promise(function (resolve, reject) { if (progressCallback) { progressCallback(0); } // We take 64 bytes: // - 32 bytes As normal for the Web3 secret storage (derivedKey, macPrefix) // - 32 bytes AES key to encrypt mnemonic with (required here to be Ethers Wallet) (0, scrypt_js_1.default)(passwordBytesLike, salt, N, r, p, 64, function (error, progress, key) { if (error) { error.progress = progress; reject(error); } else if (key) { key = (0, bytes_1.arrayify)(key); // This will be used to encrypt the wallet (as per Web3 secret storage) var derivedKey = key.slice(0, 16); var macPrefix = key.slice(16, 32); // This will be used to encrypt the mnemonic phrase (if any) var mnemonicKey = key.slice(32, 64); // Get the address for this private key var address = (0, utils_1.computeAddress)(privateKeyBytesLike); // Encrypt the private key var counter = new aes_js_1.default.Counter(iv); var aesCtr = new aes_js_1.default.ModeOfOperation.ctr(derivedKey, counter); var ciphertext = (0, bytes_1.arrayify)(aesCtr.encrypt(privateKeyBytesLike)); // Compute the message authentication code, used to check the password var mac = (0, keccak256_1.keccak256)((0, bytes_1.concat)([macPrefix, ciphertext])); // See: https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition var data = { address: address.substring(2).toLowerCase(), id: (0, uuid_1.v4)({ random: uuidRandom }), version: 3, Crypto: { cipher: 'aes-128-ctr', cipherparams: { iv: (0, bytes_1.hexlify)(iv).substring(2), }, ciphertext: (0, bytes_1.hexlify)(ciphertext).substring(2), kdf: 'scrypt', kdfparams: { salt: (0, bytes_1.hexlify)(salt).substring(2), n: N, dklen: 32, p: p, r: r, }, mac: mac.substring(2), }, }; // If we have a mnemonic, encrypt it into the JSON wallet if (entropy) { var mnemonicIv = (0, random_1.randomBytes)(16); var mnemonicCounter = new aes_js_1.default.Counter(mnemonicIv); var mnemonicAesCtr = new aes_js_1.default.ModeOfOperation.ctr(mnemonicKey, mnemonicCounter); var mnemonicCiphertext = (0, bytes_1.arrayify)(mnemonicAesCtr.encrypt(entropy)); var now = new Date(); var timestamp = now.getUTCFullYear() + '-' + zpad(now.getUTCMonth() + 1, 2) + '-' + zpad(now.getUTCDate(), 2) + 'T' + zpad(now.getUTCHours(), 2) + '-' + zpad(now.getUTCMinutes(), 2) + '-' + zpad(now.getUTCSeconds(), 2) + '.0Z'; data['x-ethers'] = { client: client, gethFilename: 'UTC--' + timestamp + '--' + data.address, mnemonicCounter: (0, bytes_1.hexlify)(mnemonicIv).substring(2), mnemonicCiphertext: (0, bytes_1.hexlify)(mnemonicCiphertext).substring(2), path: path, version: '0.1', }; } if (progressCallback) { progressCallback(1); } resolve(JSON.stringify(data)); } else if (progressCallback) { return progressCallback(progress); } }); }); } exports.encrypt = encrypt; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VjcmV0LXN0b3JhZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvc2VjcmV0LXN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWSxDQUFDOzs7Ozs7QUFFYixvREFBeUI7QUFDekIsMERBQStCO0FBQy9CLCtCQUFvQztBQUVwQyw0REFBd0Q7QUFDeEQsa0RBQWtHO0FBRWxHLG9EQUFvRDtBQUNwRCw0Q0FBa0Q7QUFDbEQsZ0RBQWlFO0FBQ2pFLGtEQUErQztBQUMvQyx3REFBcUQ7QUFDckQsb0RBQStFO0FBQy9FLGtEQUFvRDtBQXVCcEQsU0FBUyxhQUFhLENBQUMsU0FBaUI7SUFDdEMsSUFBSSxPQUFPLFNBQVMsS0FBSyxRQUFRLElBQUksU0FBUyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFO1FBQ3ZFLFNBQVMsR0FBRyxJQUFJLEdBQUcsU0FBUyxDQUFDO0tBQzlCO0lBQ0QsT0FBTyxJQUFBLGdCQUFRLEVBQUMsU0FBUyxDQUFDLENBQUM7QUFDN0IsQ0FBQztBQUVELFNBQVMsSUFBSSxDQUFDLEtBQXNCLEVBQUUsTUFBYztJQUNsRCxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RCLE9BQU8sS0FBSyxDQUFDLE1BQU0sR0FBRyxNQUFNLEVBQUU7UUFDNUIsS0FBSyxHQUFHLEdBQUcsR0FBRyxLQUFLLENBQUM7S0FDckI7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxRQUFtQjtJQUN0QyxJQUFJLE9BQU8sUUFBUSxLQUFLLFFBQVEsRUFBRTtRQUNoQyxPQUFPLElBQUEscUJBQVcsRUFBQyxRQUFRLEVBQUUsa0NBQXdCLENBQUMsSUFBSSxDQUFDLENBQUM7S0FDN0Q7SUFDRCxPQUFPLElBQUEsZ0JBQVEsRUFBQyxRQUFRLENBQUMsQ0FBQztBQUM1QixDQUFDO0FBRUQsNkRBQTZE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