UNPKG

@taquito/signer

Version:

Provide signing functionality to be with taquito

133 lines (132 loc) 4.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PrivateKey = void 0; /* eslint-disable @typescript-eslint/no-this-alias */ const elliptic_1 = require("elliptic"); const index_1 = require("./index"); const hmac_1 = require("@stablelib/hmac"); const sha512_1 = require("@stablelib/sha512"); const bn_js_1 = require("bn.js"); const utils_1 = require("./utils"); const errors_1 = require("../errors"); const core_1 = require("@taquito/core"); const seedKey = { p256: 'Nist256p1 seed', secp256k1: 'Bitcoin seed', }; // MinSeedSize is the minimal allowed seed byte length const minSeedSize = 16; // MaxSeedSize is the maximal allowed seed byte length const maxSeedSize = 64; class PrivateKey { /** * * @param priv key pair priv (BN) pub (curve.base.BasePint) if applicable * @param chainCode slice 32->n HMAC hash key and seedkey (first instance curve default seedKey. after hmac value slice 32->n) */ constructor(priv, chainCode) { this.chainCode = chainCode; this.keyPair = priv; } /** * @param seedSrc result of Bip39.mnemonicToSeed * @param curve known supported curve p256 or secp256k1 * @returns instance of PrivateKey non-HD keys derived * @throws {@link InvalidBitSize} | {@link InvalidCurveError} | {@link InvalidSeedLengthError} */ static fromSeed(seedSrc, curve) { var _a, _b; let seed = typeof seedSrc === 'string' ? (0, utils_1.parseHex)(seedSrc) : seedSrc; if (seed.length < minSeedSize || seed.length > maxSeedSize) { throw new errors_1.InvalidSeedLengthError(seed.length); } if (!Object.prototype.hasOwnProperty.call(seedKey, curve)) { throw new errors_1.InvalidCurveError(`Unsupported curve "${curve}" expecting either "p256" or "secp256k1"`); } const c = new elliptic_1.ec(curve); if (((_a = c.n) === null || _a === void 0 ? void 0 : _a.bitLength()) !== 256) { throw new errors_1.InvalidBitSize(`Invalid curve "${curve}" with bit size "${(_b = c.n) === null || _b === void 0 ? void 0 : _b.bitLength()}" expecting bit size "256"`); } const key = new TextEncoder().encode(seedKey[curve]); let d = null; let chain = new Uint8Array(); let i = 0; while (i === 0) { const sum = new hmac_1.HMAC(sha512_1.SHA512, key).update(seed).digest(); d = new bn_js_1.default(sum.subarray(0, 32)); chain = sum.subarray(32); if (d.isZero() || d.cmp(c.n) >= 0) { seed = sum; } else { i++; } } const keyPair = c.keyPair({}); keyPair.priv = d; return new PrivateKey(keyPair, chain); } /** * * @param index derivation path item pre-hardened if applicable ie: 44' -> 2^31 + 44 * @returns child PrivateKey of the current PrivateKey */ derive(index) { const data = new Uint8Array(37); if ((index & index_1.Hard) !== 0) { // hardened derivation data.set(this.keyPair.getPrivate().toArray(), 1); } else { data.set(this.keyPair.getPublic().encodeCompressed(), 0); } new DataView(data.buffer).setUint32(33, index); let d = new bn_js_1.default(0); let chain = new Uint8Array(); let i = 0; while (i === 0) { const sum = new hmac_1.HMAC(sha512_1.SHA512, this.chainCode).update(data).digest(); d = new bn_js_1.default(sum.subarray(0, 32)); chain = sum.subarray(32); if (this.keyPair.ec.n && d.cmp(this.keyPair.ec.n) < 0) { d = d.add(this.keyPair.getPrivate()).mod(this.keyPair.ec.n); if (!d.isZero()) { i++; } } data.set(chain, 1); data[0] = 1; } const keyPair = this.keyPair.ec.keyPair({}); keyPair.priv = d; return new PrivateKey(keyPair, chain); } /** * * @param path pre-hardened (if applicable) derivation path items ie 44'/1729'/0/0 -> 2^31 + 44/2^31 + 1729/0/0 * @returns final child of the full HD keys derivation */ derivePath(path) { let key = this; for (const x of path) { key = key.derive(x); } return key; } /** * * @returns Uint8Array (if contains a private key) * @throws {@link InvalidKeyError} */ bytes() { if (!this.keyPair.priv) { throw new core_1.InvalidKeyError('missing private key'); } // pad to 32 bytes as toArray() length argument seems to be ignored (BN bug) const src = this.keyPair.priv.toArray(); const out = new Uint8Array(32); out.set(src, out.length - src.length); return out; } } exports.PrivateKey = PrivateKey;