UNPKG

@unification-com/und-js-v2

Version:
229 lines (216 loc) 10.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.getPublicKeyFromPrivateKey = exports.getPrivateKeyFromMnemonic = exports.getPrivateKeyFromKeyStore = exports.getAddressFromPublicKey = exports.getAddressFromPrivateKey = exports.generateMnemonic = exports.generateKeyStore = exports.encodeAddress = exports.decodeAddress = exports.checkAddress = void 0; var _cryptoBrowserify = _interopRequireDefault(require("crypto-browserify")); var _uuid = require("uuid"); var _is_js = _interopRequireDefault(require("is_js")); var bip39 = _interopRequireWildcard(require("bip39")); var _elliptic = _interopRequireDefault(require("elliptic")); var bip32 = _interopRequireWildcard(require("bip32")); var bech32 = _interopRequireWildcard(require("bech32")); var _utils = require("../utils"); var _config = _interopRequireDefault(require("../config")); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /** * @module crypto */ // secp256k1 privkey is 32 bytes var PRIVKEY_LEN = 32; var MNEMONIC_LEN = 256; var DECODED_ADDRESS_LEN = 20; var CURVE = "secp256k1"; var EC = _elliptic["default"].ec; var elliptic = new EC(CURVE); /** * Decodes an address in bech32 format. * @param {string} value the bech32 address to decode */ var decodeAddress = function decodeAddress(value) { var decodeAddress = bech32.decode(value); return Buffer.from(bech32.fromWords(decodeAddress.words)); }; /** * Checks whether an address is valid. * @param {string} address the bech32 address to decode * @param {string} hrp the prefix to check for the bech32 address * @return {boolean} */ exports.decodeAddress = decodeAddress; var checkAddress = function checkAddress(address, hrp) { try { if (!address.startsWith(hrp)) { return false; } var decodedAddress = bech32.decode(address); var decodedAddressLength = decodeAddress(address).length; if (decodedAddressLength === DECODED_ADDRESS_LEN && decodedAddress.prefix === hrp) { return true; } return false; } catch (err) { return false; } }; /** * Encodes an address from input data bytes. * @param {string} value the public key to encode * @param {*} prefix the address prefix * @param {*} type the output type (default: hex) */ exports.checkAddress = checkAddress; var encodeAddress = function encodeAddress(value) { var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "und"; var type = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : "hex"; var words = bech32.toWords(Buffer.from(value, type)); return bech32.encode(prefix, words); }; /** * Calculates the public key from a given private key. * @param {string} privateKeyHex the private key hexstring * @return {string} public key hexstring */ exports.encodeAddress = encodeAddress; var getPublicKeyFromPrivateKey = function getPublicKeyFromPrivateKey(privateKeyHex) { if (!privateKeyHex || privateKeyHex.length !== PRIVKEY_LEN * 2) { throw new Error("invalid privateKey"); } var curve = new EC(CURVE); var keypair = curve.keyFromPrivate(privateKeyHex, "hex"); var unencodedPubKey = keypair.getPublic().encode("hex"); return unencodedPubKey; }; /** * Gets an address from a public key hex. * @param {string} publicKeyHex the public key hexstring * @param {string} prefix the address prefix */ exports.getPublicKeyFromPrivateKey = getPublicKeyFromPrivateKey; var getAddressFromPublicKey = function getAddressFromPublicKey(publicKeyHex, prefix) { var pubKey = elliptic.keyFromPublic(publicKeyHex, "hex"); var pubPoint = pubKey.getPublic(); var compressed = pubPoint.encodeCompressed(); var hexed = (0, _utils.ab2hexstring)(compressed); var hash = (0, _utils.sha256ripemd160)(hexed); // https://git.io/fAn8N var address = encodeAddress(hash, prefix); return address; }; /** * Gets an address from a private key. * @param {string} privateKeyHex the private key hexstring */ exports.getAddressFromPublicKey = getAddressFromPublicKey; var getAddressFromPrivateKey = function getAddressFromPrivateKey(privateKeyHex, prefix) { return getAddressFromPublicKey(getPublicKeyFromPrivateKey(privateKeyHex), prefix); }; /** * Generates a keystore object (web3 secret storage format) given a private key to store and a password. * @param {string} privateKeyHex the private key hexstring. * @param {string} password the password. * @return {object} the keystore object. */ exports.getAddressFromPrivateKey = getAddressFromPrivateKey; var generateKeyStore = function generateKeyStore(privateKeyHex, password) { var salt = _cryptoBrowserify["default"].randomBytes(32); var iv = _cryptoBrowserify["default"].randomBytes(16); var cipherAlg = "aes-256-ctr"; var kdf = "pbkdf2"; var kdfparams = { dklen: 32, salt: salt.toString("hex"), c: 262144, prf: "hmac-sha256" }; var derivedKey = _cryptoBrowserify["default"].pbkdf2Sync(Buffer.from(password), salt, kdfparams.c, kdfparams.dklen, "sha256"); var cipher = _cryptoBrowserify["default"].createCipheriv(cipherAlg, derivedKey.slice(0, 32), iv); if (!cipher) { throw new Error("Unsupported cipher"); } var ciphertext = Buffer.concat([cipher.update(Buffer.from(privateKeyHex, "hex")), cipher["final"]()]); var bufferValue = Buffer.concat([derivedKey.slice(16, 32), Buffer.from(ciphertext, "hex")]); return { version: 1, id: (0, _uuid.v4)({ random: _cryptoBrowserify["default"].randomBytes(16) }), crypto: { ciphertext: ciphertext.toString("hex"), cipherparams: { iv: iv.toString("hex") }, cipher: cipherAlg, kdf: kdf, kdfparams: kdfparams, // mac must use sha3 according to web3 secret storage spec mac: (0, _utils.sha3)(bufferValue.toString("hex")) } }; }; /** * Gets a private key from a keystore given its password. * @param {string} keystore the keystore in json format * @param {string} password the password. */ exports.generateKeyStore = generateKeyStore; var getPrivateKeyFromKeyStore = function getPrivateKeyFromKeyStore(keystore, password) { if (!_is_js["default"].string(password)) { throw new Error("No password given."); } var json = _is_js["default"].object(keystore) ? keystore : JSON.parse(keystore); var kdfparams = json.crypto.kdfparams; if (kdfparams.prf !== "hmac-sha256") { throw new Error("Unsupported parameters to PBKDF2"); } var derivedKey = _cryptoBrowserify["default"].pbkdf2Sync(Buffer.from(password), Buffer.from(kdfparams.salt, "hex"), kdfparams.c, kdfparams.dklen, "sha256"); var ciphertext = Buffer.from(json.crypto.ciphertext, "hex"); var bufferValue = Buffer.concat([derivedKey.slice(16, 32), ciphertext]); // try sha3 (new / ethereum keystore) mac first var mac = (0, _utils.sha3)(bufferValue.toString("hex")); if (mac !== json.crypto.mac) { // the legacy (sha256) mac is next to be checked. pre-testnet keystores used a sha256 digest for the mac. // the sha256 mac was not compatible with ethereum keystores, so it was changed to sha3 for mainnet. var macLegacy = (0, _utils.sha256)(bufferValue.toString("hex")); if (macLegacy !== json.crypto.mac) { throw new Error("Keystore mac check failed (sha3 & sha256) - wrong password?"); } } var decipher = _cryptoBrowserify["default"].createDecipheriv(json.crypto.cipher, derivedKey.slice(0, 32), Buffer.from(json.crypto.cipherparams.iv, "hex")); var privateKey = Buffer.concat([decipher.update(ciphertext), decipher["final"]()]).toString("hex"); return privateKey; }; /** * Generates mnemonic phrase words using random entropy. */ exports.getPrivateKeyFromKeyStore = getPrivateKeyFromKeyStore; var generateMnemonic = function generateMnemonic() { return bip39.generateMnemonic(MNEMONIC_LEN); }; /** * Get a private key from mnemonic words. * @param {string} mnemonic the mnemonic phrase words * @param {Boolean} derive derive a private key using the default HD path (default: true) * @param {number} index the bip44 address index (default: 0) * @param {string} password according to bip39 * @return {Buffer} hexstring */ exports.generateMnemonic = generateMnemonic; var getPrivateKeyFromMnemonic = function getPrivateKeyFromMnemonic(mnemonic) { var derive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; var password = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ""; if (!bip39.validateMnemonic(mnemonic)) { throw new Error("wrong mnemonic format"); } var seed = bip39.mnemonicToSeed(mnemonic, password); if (derive) { var master = bip32.fromSeed(seed); var child = master.derivePath(_config["default"].HD_PATH + index); return child.privateKey; } return seed; }; exports.getPrivateKeyFromMnemonic = getPrivateKeyFromMnemonic;