@taquito/signer
Version:
Provide signing functionality to be with taquito
133 lines (132 loc) • 4.96 kB
JavaScript
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;
;