@meterio/devkit
Version:
Typescript library to aid DApp development on Meter network
406 lines • 35.2 kB
JavaScript
'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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