UNPKG

@harmony-js/crypto

Version:

crypto libraries for harmony

166 lines 6.52 kB
"use strict"; /** * @packageDocumentation * @module harmony-crypto */ Object.defineProperty(exports, "__esModule", { value: true }); exports.validatePrivateKey = exports.isValidChecksumAddress = exports.recoverAddress = exports.recoverPublicKey = exports.verifySignature = exports.getContractAddress = exports.sign = exports.toChecksumAddress = exports.getAddressFromPublicKey = exports.getPublic = exports.getAddressFromPrivateKey = exports.getPubkeyFromPrivateKey = exports.generatePrivateKey = void 0; var tslib_1 = require("tslib"); var elliptic_1 = tslib_1.__importDefault(require("elliptic")); var bytes = tslib_1.__importStar(require("./bytes")); var errors = tslib_1.__importStar(require("./errors")); var keccak256_1 = require("./keccak256"); var random_1 = require("./random"); var utils_1 = require("@harmony-js/utils"); var bech32_1 = require("./bech32"); var rlp_1 = require("./rlp"); var secp256k1 = elliptic_1.default.ec('secp256k1'); /** * @function generatePrivateKey * @description generatePrivate key using `eth-lib` settings * @return {string} */ exports.generatePrivateKey = function () { var entropy = '0x' + random_1.randomBytes(16); var innerHex = keccak256_1.keccak256(bytes.concat(['0x' + random_1.randomBytes(32), entropy || '0x' + random_1.randomBytes(32)])); var middleHex = bytes.concat([ bytes.concat(['0x' + random_1.randomBytes(32), innerHex]), '0x' + random_1.randomBytes(32), ]); var outerHex = keccak256_1.keccak256(middleHex); return outerHex; }; /** * @function getPubkeyFromPrivateKey * @param {string} privateKey - private key String * @return {string} */ exports.getPubkeyFromPrivateKey = function (privateKey) { return '0x' + exports.getPublic(privateKey, true); }; /** * @function getAddressFromPrivateKey * @param {string} privateKey - private key string * @return {string} address with `length = 40` */ exports.getAddressFromPrivateKey = function (privateKey) { var publicHash = '0x' + exports.getPublic(privateKey).slice(2); var publicKey = keccak256_1.keccak256(publicHash); var address = '0x' + publicKey.slice(-40); return address; }; exports.getPublic = function (privateKey, compress) { if (!utils_1.isPrivateKey(privateKey) || !exports.validatePrivateKey(privateKey)) { throw new Error(privateKey + " is not PrivateKey"); } var ecKey = secp256k1.keyFromPrivate(utils_1.strip0x(privateKey), 'hex'); return ecKey.getPublic(compress || false, 'hex'); }; /** * @function getAddressFromPublicKey * @param {string} publicKey - public key string * @return {string} address with `length = 40` */ exports.getAddressFromPublicKey = function (publicKey) { var ecKey = secp256k1.keyFromPublic(publicKey.slice(2), 'hex'); var publicHash = ecKey.getPublic(false, 'hex'); var address = '0x' + keccak256_1.keccak256('0x' + publicHash.slice(2)).slice(-40); return address; }; /** * @function toChecksumAddress * @param {string} address - raw address * @return {string} checksumed address */ exports.toChecksumAddress = function (address) { if (typeof address === 'string' && utils_1.isBech32Address(address)) { address = bech32_1.fromBech32(address); } if (typeof address !== 'string' || !address.match(/^0x[0-9A-Fa-f]{40}$/)) { errors.throwError('invalid address', errors.INVALID_ARGUMENT, { arg: 'address', value: address, }); } address = address.toLowerCase(); var chars = address.substring(2).split(''); var hashed = new Uint8Array(40); for (var i = 0; i < 40; i++) { hashed[i] = chars[i].charCodeAt(0); } hashed = bytes.arrayify(keccak256_1.keccak256(hashed)) || hashed; for (var i = 0; i < 40; i += 2) { if (hashed[i >> 1] >> 4 >= 8) { chars[i] = chars[i].toUpperCase(); } if ((hashed[i >> 1] & 0x0f) >= 8) { chars[i + 1] = chars[i + 1].toUpperCase(); } } return '0x' + chars.join(''); }; exports.sign = function (digest, privateKey) { if (!utils_1.isPrivateKey(privateKey)) { throw new Error(privateKey + " is not PrivateKey"); } var keyPair = secp256k1.keyFromPrivate(utils_1.strip0x(privateKey), 'hex'); var signature = keyPair.sign(bytes.arrayify(digest), { canonical: true }); var publicKey = '0x' + keyPair.getPublic(true, 'hex'); var result = { recoveryParam: signature.recoveryParam, r: bytes.hexZeroPad('0x' + signature.r.toString(16), 32), s: bytes.hexZeroPad('0x' + signature.s.toString(16), 32), v: 27 + signature.recoveryParam, }; if (verifySignature(digest, result, publicKey)) { return result; } else { throw new Error('signing process failed'); } }; function getContractAddress(from, nonce) { if (!from) { throw new Error('missing from address'); } var addr = keccak256_1.keccak256(rlp_1.encode([from, bytes.stripZeros(bytes.hexlify(nonce))])); return '0x' + addr.substring(26); } exports.getContractAddress = getContractAddress; function verifySignature(digest, signature, publicKey) { return recoverPublicKey(digest, signature) === publicKey; } exports.verifySignature = verifySignature; function recoverPublicKey(digest, signature) { var sig = bytes.splitSignature(signature); var rs = { r: bytes.arrayify(sig.r), s: bytes.arrayify(sig.s) }; //// var recovered = secp256k1.recoverPubKey(bytes.arrayify(digest), rs, sig.recoveryParam); var key = recovered.encode('hex', false); var ecKey = secp256k1.keyFromPublic(key, 'hex'); var publicKey = '0x' + ecKey.getPublic(true, 'hex'); /// return publicKey; } exports.recoverPublicKey = recoverPublicKey; function recoverAddress(digest, signature) { return exports.getAddressFromPublicKey(recoverPublicKey(bytes.arrayify(digest) || new Uint8Array(), signature)); } exports.recoverAddress = recoverAddress; /** * isValidChecksumAddress * * takes hex-encoded string and returns boolean if address is checksumed * * @param {string} address * @returns {boolean} */ exports.isValidChecksumAddress = function (address) { return utils_1.isAddress(address.replace('0x', '')) && exports.toChecksumAddress(address) === address; }; exports.validatePrivateKey = function (privateKey) { var ecKey = secp256k1.keyFromPrivate(utils_1.strip0x(privateKey), 'hex'); var result = ecKey.validate().result; return result; }; //# sourceMappingURL=keyTool.js.map