refactor hd keys.
This commit is contained in:
parent
b20bcf701b
commit
a18a501c37
281
lib/bcoin/hd.js
281
lib/bcoin/hd.js
@ -58,6 +58,7 @@ var bn = require('bn.js');
|
||||
var elliptic = require('elliptic');
|
||||
var utils = bcoin.utils;
|
||||
var assert = utils.assert;
|
||||
var constants = bcoin.protocol.constants;
|
||||
var network = bcoin.protocol.network;
|
||||
|
||||
var EventEmitter = require('events').EventEmitter;
|
||||
@ -74,12 +75,12 @@ function HDSeed(options) {
|
||||
if (!(this instanceof HDSeed))
|
||||
return new HDSeed(options);
|
||||
|
||||
options = options || {};
|
||||
|
||||
this.bits = options.bits || 128;
|
||||
this.entropy = options.entropy || HDSeed._entropy(this.bits / 8);
|
||||
this.mnemonic = options.mnemonic || HDSeed._mnemonic(this.entropy);
|
||||
if (options.passphrase !== undefined) {
|
||||
this.seed = this.createSeed(options.passphrase);
|
||||
}
|
||||
this.seed = this.createSeed(options.passphrase);
|
||||
}
|
||||
|
||||
HDSeed.create = function(options) {
|
||||
@ -112,40 +113,37 @@ HDSeed._mnemonic = function(entropy) {
|
||||
return mnemonic.join(' ');
|
||||
};
|
||||
|
||||
/**
|
||||
* HD Keys
|
||||
*/
|
||||
|
||||
var HARDENED = 0x80000000;
|
||||
var MAX_INDEX = 2 * HARDENED;
|
||||
var MIN_ENTROPY = 128 / 8;
|
||||
var MAX_ENTROPY = 512 / 8;
|
||||
var PARENT_FINGER_PRINT_SIZE = 4;
|
||||
var PATH_ROOTS = ['m', 'M', 'm\'', 'M\''];
|
||||
|
||||
/**
|
||||
* HD Private Key
|
||||
*/
|
||||
|
||||
function HDPriv(options) {
|
||||
function HDPrivateKey(options) {
|
||||
var data;
|
||||
|
||||
if (!(this instanceof HDPriv))
|
||||
return new HDPriv(options);
|
||||
if (!(this instanceof HDPrivateKey))
|
||||
return new HDPrivateKey(options);
|
||||
|
||||
if (!options)
|
||||
options = { seed: new HDSeed({ passphrase: '' }) };
|
||||
options = { seed: bcoin.hd.seed() };
|
||||
|
||||
if (typeof options === 'string' && options.indexOf('xprv') === 0)
|
||||
options = { xkey: options };
|
||||
|
||||
if (options.passphrase !== undefined)
|
||||
options.seed = new HDSeed({ passphrase: options.passphrase });
|
||||
if (options.passphrase !== undefined
|
||||
|| options.bits
|
||||
|| options.entropy
|
||||
|| options.mnemonic) {
|
||||
options.seed = bcoin.hd.seed(options);
|
||||
}
|
||||
|
||||
if (options.seed
|
||||
&& typeof options.seed === 'object'
|
||||
&& !Array.isArray(options.seed)
|
||||
&& !(options.seed instanceof bcoin.hd.seed)) {
|
||||
options.seed = bcoin.hd.seed(options.seed);
|
||||
}
|
||||
|
||||
if (options.seed) {
|
||||
if (typeof options.seed === 'object' && !(options.seed instanceof HDSeed)) {
|
||||
options.seed = new HDSeed(options.seed);
|
||||
}
|
||||
this.seed = options.seed;
|
||||
data = this._seed(options.seed);
|
||||
} else if (options.xkey) {
|
||||
@ -163,26 +161,44 @@ function HDPriv(options) {
|
||||
this._build(data);
|
||||
}
|
||||
|
||||
HDPriv.prototype._normalize = function(data, version) {
|
||||
var b;
|
||||
|
||||
HDPrivateKey.prototype._normalize = function(data, version) {
|
||||
data.version = version || network.prefixes.xprivkey;
|
||||
data.version = +data.version;
|
||||
data.privateKey = data.privateKey || data.priv;
|
||||
data.publicKey = data.publicKey || data.pub;
|
||||
|
||||
data.depth = +data.depth;
|
||||
|
||||
if (typeof data.parentFingerPrint === 'number') {
|
||||
b = [];
|
||||
utils.writeU32BE(b, data.parentFingerPrint, 0);
|
||||
data.parentFingerPrint = b;
|
||||
// version = uint_32be
|
||||
if (typeof data.version === 'string') {
|
||||
data.version = utils.toArray(data.version, 'hex');
|
||||
} else if (typeof data.version === 'number') {
|
||||
data.version = array32(data.version);
|
||||
}
|
||||
|
||||
data.childIndex = +data.childIndex;
|
||||
// depth = unsigned char
|
||||
if (typeof data.depth === 'string')
|
||||
data.depth = utils.toArray(data.depth, 'hex');
|
||||
else if (typeof data.depth === 'number')
|
||||
data.depth = [data.depth];
|
||||
|
||||
if (new bn(data.depth).toNumber() > 0xff)
|
||||
throw new Error('Depth is too high');
|
||||
|
||||
// parent finger print = uint_32be
|
||||
if (typeof data.parentFingerPrint === 'string')
|
||||
data.parentFingerPrint = utils.toArray(data.parentFingerPrint, 'hex');
|
||||
else if (typeof data.parentFingerPrint === 'number')
|
||||
data.parentFingerPrint = array32(data.parentFingerPrint);
|
||||
|
||||
// child index = uint_32be
|
||||
if (typeof data.childIndex === 'string')
|
||||
data.childIndex = utils.toArray(data.childIndex, 'hex');
|
||||
else if (typeof data.childIndex === 'number')
|
||||
data.childIndex = array32(data.childIndex);
|
||||
|
||||
// chain code = 32 bytes
|
||||
if (typeof data.chainCode === 'string')
|
||||
data.chainCode = utils.toArray(data.chainCode, 'hex');
|
||||
|
||||
data.privateKey = data.privateKey || data.priv;
|
||||
// private key = 32 bytes
|
||||
if (data.privateKey) {
|
||||
if (data.privateKey.getPrivate)
|
||||
data.privateKey = data.privateKey.getPrivate().toArray();
|
||||
@ -190,7 +206,7 @@ HDPriv.prototype._normalize = function(data, version) {
|
||||
data.privateKey = utils.toKeyArray(data.privateKey);
|
||||
}
|
||||
|
||||
data.publicKey = data.publicKey || data.pub;
|
||||
// public key = 33 bytes
|
||||
if (data.publicKey) {
|
||||
if (data.publicKey.getPublic)
|
||||
data.publicKey = data.privateKey.getPublic(true, 'array');
|
||||
@ -198,29 +214,31 @@ HDPriv.prototype._normalize = function(data, version) {
|
||||
data.publicKey = utils.toKeyArray(data.publicKey);
|
||||
}
|
||||
|
||||
if (typeof data.checksum === 'number') {
|
||||
b = [];
|
||||
utils.writeU32BE(b, data.checksum, 0);
|
||||
data.checksum = b;
|
||||
}
|
||||
// checksum = 4 bytes
|
||||
if (typeof data.checksum === 'string')
|
||||
data.checksum = utils.toArray(data.checksum, 'hex');
|
||||
else if (typeof data.checksum === 'number')
|
||||
data.checksum = array32(data.checksum);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
HDPriv.prototype._seed = function(seed) {
|
||||
if (seed instanceof HDSeed)
|
||||
HDPrivateKey.prototype._seed = function(seed) {
|
||||
if (seed instanceof bcoin.hd.seed)
|
||||
seed = seed.seed;
|
||||
|
||||
if (utils.isHex(seed))
|
||||
seed = utils.toArray(seed, 'hex');
|
||||
|
||||
if (seed.length < MIN_ENTROPY || seed.length > MAX_ENTROPY)
|
||||
if (seed.length < constants.hd.minEntropy
|
||||
|| seed.length > constants.hd.maxEntropy) {
|
||||
throw new Error('entropy not in range');
|
||||
}
|
||||
|
||||
var hash = sha512hmac(seed, 'Bitcoin seed');
|
||||
|
||||
return {
|
||||
// version: network.prefixes.xprivkey,
|
||||
version: null,
|
||||
depth: 0,
|
||||
parentFingerPrint: 0,
|
||||
childIndex: 0,
|
||||
@ -230,7 +248,7 @@ HDPriv.prototype._seed = function(seed) {
|
||||
};
|
||||
};
|
||||
|
||||
HDPriv.prototype._unbuild = function(xkey) {
|
||||
HDPrivateKey.prototype._unbuild = function(xkey) {
|
||||
var raw = utils.fromBase58(xkey);
|
||||
var data = {};
|
||||
var off = 0;
|
||||
@ -259,28 +277,28 @@ HDPriv.prototype._unbuild = function(xkey) {
|
||||
return data;
|
||||
};
|
||||
|
||||
HDPriv.prototype._build = function(data) {
|
||||
HDPrivateKey.prototype._build = function(data) {
|
||||
var sequence = [];
|
||||
var off = 0;
|
||||
var checksum, xprivkey, pair, privateKey, publicKey, size, fingerPrint;
|
||||
|
||||
utils.writeU32BE(sequence, data.version, off);
|
||||
off += 4;
|
||||
sequence[off] = data.depth;
|
||||
off += 1;
|
||||
utils.copy(data.version, sequence, off, true);
|
||||
off += data.version.length;
|
||||
utils.copy(data.depth, sequence, off, true);
|
||||
off += data.depth.length;
|
||||
utils.copy(data.parentFingerPrint, sequence, off, true);
|
||||
off += data.parentFingerPrint.length;
|
||||
utils.writeU32BE(sequence, data.childIndex, off);
|
||||
off += 4;
|
||||
utils.copy(data.childIndex, sequence, off, true);
|
||||
off += data.childIndex.length;
|
||||
utils.copy(data.chainCode, sequence, off, true);
|
||||
off += data.chainCode.length;
|
||||
sequence[off] = 0;
|
||||
off += 1;
|
||||
utils.copy([0], sequence, off, true);
|
||||
off += [0].length;
|
||||
utils.copy(data.privateKey, sequence, off, true);
|
||||
off += data.privateKey.length;
|
||||
checksum = utils.dsha256(sequence).slice(0, 4);
|
||||
utils.copy(checksum, sequence, off, true);
|
||||
off += 4;
|
||||
off += checksum.length;
|
||||
|
||||
xprivkey = utils.toBase58(sequence);
|
||||
|
||||
@ -288,7 +306,7 @@ HDPriv.prototype._build = function(data) {
|
||||
privateKey = pair.getPrivate().toArray();
|
||||
publicKey = pair.getPublic(true, 'array');
|
||||
|
||||
size = PARENT_FINGER_PRINT_SIZE;
|
||||
size = constants.hd.parentFingerPrintSize;
|
||||
fingerPrint = utils.ripesha(publicKey).slice(0, size);
|
||||
|
||||
this.version = data.version;
|
||||
@ -297,33 +315,30 @@ HDPriv.prototype._build = function(data) {
|
||||
this.childIndex = data.childIndex;
|
||||
this.chainCode = data.chainCode;
|
||||
this.privateKey = privateKey;
|
||||
// this.checksum = checksum;
|
||||
this.checksum = null;
|
||||
|
||||
this.xprivkey = xprivkey;
|
||||
this.fingerPrint = fingerPrint;
|
||||
this.publicKey = publicKey;
|
||||
|
||||
this.hdpub = new HDPub(this);
|
||||
this.hdpub = bcoin.hd.pub(this);
|
||||
this.xpubkey = this.hdpub.xpubkey;
|
||||
this.pair = bcoin.ecdsa.keyPair({ priv: this.privateKey });
|
||||
};
|
||||
|
||||
HDPriv.prototype.derive = function(index, hard) {
|
||||
HDPrivateKey.prototype.derive = function(index, hardened) {
|
||||
var data, hash, leftPart, chainCode, privateKey;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.deriveString(index);
|
||||
|
||||
var index_ = [];
|
||||
var data, hash, leftPart, chainCode, privateKey;
|
||||
hardened = index >= constants.hd.hardened ? true : hardened;
|
||||
if (index < constants.hd.hardened && hardened)
|
||||
index += constants.hd.hardened;
|
||||
|
||||
hard = index >= HARDENED ? true : hard;
|
||||
if (index < HARDENED && hard === true)
|
||||
index += HARDENED;
|
||||
|
||||
utils.writeU32BE(index_, index, 0);
|
||||
|
||||
data = hard
|
||||
? [0].concat(this.privateKey).concat(index_)
|
||||
: data = [].concat(this.publicKey).concat(index_);
|
||||
data = hardened
|
||||
? [0].concat(this.privateKey).concat(array32(index))
|
||||
: data = [].concat(this.publicKey).concat(array32(index));
|
||||
|
||||
hash = sha512hmac(data, this.chainCode);
|
||||
leftPart = new bn(hash.slice(0, 32));
|
||||
@ -331,43 +346,44 @@ HDPriv.prototype.derive = function(index, hard) {
|
||||
|
||||
privateKey = leftPart.add(new bn(this.privateKey)).mod(ec.curve.n).toArray();
|
||||
|
||||
return new HDPriv({
|
||||
return new HDPrivateKey({
|
||||
version: null,
|
||||
master: this.master,
|
||||
// version: this.version,
|
||||
depth: this.depth + 1,
|
||||
depth: new bn(this.depth).toNumber() + 1,
|
||||
parentFingerPrint: this.fingerPrint,
|
||||
childIndex: index,
|
||||
chainCode: chainCode,
|
||||
privateKey: privateKey
|
||||
privateKey: privateKey,
|
||||
checksum: null
|
||||
});
|
||||
};
|
||||
|
||||
// https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
|
||||
HDPriv._getIndexes = function(path) {
|
||||
HDPrivateKey._getIndexes = function(path) {
|
||||
var steps = path.split('/');
|
||||
var root = steps.shift();
|
||||
var indexes = [];
|
||||
var i, step, hard, index;
|
||||
var i, step, hardened, index;
|
||||
|
||||
if (~PATH_ROOTS.indexOf(path))
|
||||
if (~constants.hd.pathRoots.indexOf(path))
|
||||
return indexes;
|
||||
|
||||
if (!~PATH_ROOTS.indexOf(root))
|
||||
if (!~constants.hd.pathRoots.indexOf(root))
|
||||
return null;
|
||||
|
||||
for (i = 0; i < steps.length; i++) {
|
||||
step = steps[i];
|
||||
hard = step[step.length - 1] === '\'';
|
||||
hardened = step[step.length - 1] === '\'';
|
||||
|
||||
if (hard)
|
||||
if (hardened)
|
||||
step = step.slice(0, -1);
|
||||
|
||||
if (!step || step[0] === '-')
|
||||
return null;
|
||||
|
||||
index = +step;
|
||||
if (hard)
|
||||
index += HARDENED;
|
||||
if (hardened)
|
||||
index += constants.hd.hardened;
|
||||
|
||||
indexes.push(index);
|
||||
}
|
||||
@ -375,42 +391,45 @@ HDPriv._getIndexes = function(path) {
|
||||
return indexes;
|
||||
};
|
||||
|
||||
HDPriv.isValidPath = function(path, hard) {
|
||||
HDPrivateKey.isValidPath = function(path, hardened) {
|
||||
if (typeof path === 'string') {
|
||||
var indexes = HDPriv._getIndexes(path);
|
||||
return indexes !== null && indexes.every(HDPriv.isValidPath);
|
||||
var indexes = HDPrivateKey._getIndexes(path);
|
||||
return indexes !== null && indexes.every(HDPrivateKey.isValidPath);
|
||||
}
|
||||
|
||||
if (typeof path === 'number') {
|
||||
if (path < HARDENED && hard === true) {
|
||||
path += HARDENED;
|
||||
if (path < constants.hd.hardened && hardened) {
|
||||
path += constants.hd.hardened;
|
||||
}
|
||||
return path >= 0 && path < MAX_INDEX;
|
||||
return path >= 0 && path < constants.hd.maxIndex;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
HDPriv.prototype.deriveString = function(path) {
|
||||
if (!HDPriv.isValidPath(path))
|
||||
HDPrivateKey.prototype.deriveString = function(path) {
|
||||
if (!HDPrivateKey.isValidPath(path))
|
||||
throw new Error('invalid path');
|
||||
|
||||
var indexes = HDPriv._getIndexes(path);
|
||||
var indexes = HDPrivateKey._getIndexes(path);
|
||||
|
||||
return indexes.reduce(function(prev, index) {
|
||||
return prev.derive(index);
|
||||
});
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* HD Public Key
|
||||
*/
|
||||
|
||||
function HDPub(options) {
|
||||
function HDPublicKey(options) {
|
||||
var data;
|
||||
|
||||
if (!(this instanceof HDPub))
|
||||
return new HDPub(options);
|
||||
if (!(this instanceof HDPublicKey))
|
||||
return new HDPublicKey(options);
|
||||
|
||||
if (!options)
|
||||
throw new Error('No options for HDPublicKey');
|
||||
|
||||
if (typeof options === 'string' && options.indexOf('xpub') === 0)
|
||||
options = { xkey: options };
|
||||
@ -426,9 +445,9 @@ function HDPub(options) {
|
||||
this._build(data);
|
||||
}
|
||||
|
||||
HDPub.prototype._normalize = HDPriv.prototype._normalize;
|
||||
HDPublicKey.prototype._normalize = HDPrivateKey.prototype._normalize;
|
||||
|
||||
HDPub.prototype._unbuild = function(xkey) {
|
||||
HDPublicKey.prototype._unbuild = function(xkey) {
|
||||
var raw = utils.fromBase58(xkey);
|
||||
var data = {};
|
||||
var off = 0;
|
||||
@ -456,26 +475,26 @@ HDPub.prototype._unbuild = function(xkey) {
|
||||
return data;
|
||||
};
|
||||
|
||||
HDPub.prototype._build = function(data) {
|
||||
HDPublicKey.prototype._build = function(data) {
|
||||
var sequence = [];
|
||||
var off = 0;
|
||||
var checksum, xpubkey, publicKey, size, fingerPrint;
|
||||
|
||||
utils.writeU32BE(sequence, data.version, off);
|
||||
off += 4;
|
||||
sequence[off] = data.depth;
|
||||
off += 1;
|
||||
utils.copy(data.version, sequence, off, true);
|
||||
off += data.version.length;
|
||||
utils.copy(data.depth, sequence, off, true);
|
||||
off += data.depth.length;
|
||||
utils.copy(data.parentFingerPrint, sequence, off, true);
|
||||
off += data.parentFingerPrint.length;
|
||||
utils.writeU32BE(sequence, data.childIndex, off);
|
||||
off += 4;
|
||||
utils.copy(data.childIndex, sequence, off, true);
|
||||
off += data.childIndex.length;
|
||||
utils.copy(data.chainCode, sequence, off, true);
|
||||
off += data.chainCode.length;
|
||||
utils.copy(data.publicKey, sequence, off, true);
|
||||
off += data.publicKey.length;
|
||||
checksum = utils.dsha256(sequence).slice(0, 4);
|
||||
utils.copy(checksum, sequence, off, true);
|
||||
off += 4;
|
||||
off += checksum.length;
|
||||
|
||||
if (!data.checksum || !data.checksum.length)
|
||||
data.checksum = checksum;
|
||||
@ -485,7 +504,7 @@ HDPub.prototype._build = function(data) {
|
||||
xpubkey = utils.toBase58(sequence);
|
||||
|
||||
publicKey = data.publicKey;
|
||||
size = PARENT_FINGER_PRINT_SIZE;
|
||||
size = constants.hd.parentFingerPrintSize;
|
||||
fingerPrint = utils.ripesha(publicKey).slice(0, size);
|
||||
|
||||
this.version = data.version;
|
||||
@ -494,7 +513,7 @@ HDPub.prototype._build = function(data) {
|
||||
this.childIndex = data.childIndex;
|
||||
this.chainCode = data.chainCode;
|
||||
this.publicKey = publicKey;
|
||||
// this.checksum = checksum;
|
||||
this.checksum = null;
|
||||
|
||||
this.xpubkey = xpubkey;
|
||||
this.fingerPrint = fingerPrint;
|
||||
@ -503,22 +522,19 @@ HDPub.prototype._build = function(data) {
|
||||
this.pair = bcoin.ecdsa.keyPair({ pub: this.publicKey });
|
||||
};
|
||||
|
||||
HDPub.prototype.derive = function(index, hard) {
|
||||
var index_ = [];
|
||||
HDPublicKey.prototype.derive = function(index, hardened) {
|
||||
var data, hash, leftPart, chainCode, pair, pubkeyPoint, publicKey;
|
||||
|
||||
if (typeof index === 'string')
|
||||
return this.deriveString(index);
|
||||
|
||||
if (index >= HARDENED || hard)
|
||||
if (index >= constants.hd.hardened || hardened)
|
||||
throw new Error('invalid index');
|
||||
|
||||
if (index < 0)
|
||||
throw new Error('invalid path');
|
||||
|
||||
utils.writeU32BE(index_, index, 0);
|
||||
|
||||
data = [].concat(this.publicKey).concat(index_);
|
||||
data = [].concat(this.publicKey).concat(array32(index));
|
||||
hash = sha512hmac(data, this.chainCode);
|
||||
leftPart = new bn(hash.slice(0, 32));
|
||||
chainCode = hash.slice(32, 64);
|
||||
@ -527,46 +543,47 @@ HDPub.prototype.derive = function(index, hard) {
|
||||
pubkeyPoint = ec.curve.g.mul(leftPart).add(pair.pub);
|
||||
publicKey = bcoin.ecdsa.keyFromPublic(pubkeyPoint).getPublic(true, 'array');
|
||||
|
||||
return new HDPub({
|
||||
// version: network.prefixes.xpubkey,
|
||||
depth: this.depth + 1,
|
||||
return new HDPublicKey({
|
||||
version: null,
|
||||
depth: new bn(this.depth).toNumber() + 1,
|
||||
parentFingerPrint: this.fingerPrint,
|
||||
childIndex: index,
|
||||
chainCode: chainCode,
|
||||
publicKey: publicKey
|
||||
publicKey: publicKey,
|
||||
checksum: null
|
||||
});
|
||||
};
|
||||
|
||||
HDPub.isValidPath = function(arg) {
|
||||
HDPublicKey.isValidPath = function(arg) {
|
||||
if (typeof arg === 'string') {
|
||||
var indexes = HDPriv._getIndexes(arg);
|
||||
return indexes !== null && indexes.every(HDPub.isValidPath);
|
||||
var indexes = HDPrivateKey._getIndexes(arg);
|
||||
return indexes !== null && indexes.every(HDPublicKey.isValidPath);
|
||||
}
|
||||
|
||||
if (typeof arg === 'number')
|
||||
return arg >= 0 && arg < HARDENED;
|
||||
return arg >= 0 && arg < constants.hd.hardened;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
HDPub.prototype.deriveString = function(path) {
|
||||
HDPublicKey.prototype.deriveString = function(path) {
|
||||
if (~path.indexOf('\''))
|
||||
throw new Error('cannot derive hardened');
|
||||
else if (!HDPub.isValidPath(path))
|
||||
else if (!HDPublicKey.isValidPath(path))
|
||||
throw new Error('invalid path');
|
||||
|
||||
var indexes = HDPriv._getIndexes(path);
|
||||
var indexes = HDPrivateKey._getIndexes(path);
|
||||
|
||||
return indexes.reduce(function(prev, index) {
|
||||
return prev.derive(index);
|
||||
});
|
||||
}, this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Make HD keys behave like elliptic KeyPairs
|
||||
*/
|
||||
|
||||
[HDPriv, HDPub].forEach(function(HD) {
|
||||
[HDPrivateKey, HDPublicKey].forEach(function(HD) {
|
||||
HD.prototype.validate = function validate() {
|
||||
return this.pair.validate.apply(this.pair, arguments);
|
||||
};
|
||||
@ -689,11 +706,17 @@ function pbkdf2(key, salt, iterations, dkLen) {
|
||||
return DK;
|
||||
}
|
||||
|
||||
function array32(data) {
|
||||
var b = [];
|
||||
utils.writeU32BE(b, data, 0);
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
||||
hd.seed = HDSeed;
|
||||
hd.priv = HDPriv;
|
||||
hd.pub = HDPub;
|
||||
hd.priv = HDPrivateKey;
|
||||
hd.pub = HDPublicKey;
|
||||
hd.pbkdf2 = pbkdf2;
|
||||
|
||||
@ -192,3 +192,12 @@ exports.zeroHash = utils.toArray(
|
||||
'0000000000000000000000000000000000000000000000000000000000000000',
|
||||
'hex'
|
||||
);
|
||||
|
||||
exports.hd = {
|
||||
hardened: 0x80000000,
|
||||
maxIndex: 2 * 0x80000000,
|
||||
minEntropy: 128 / 8,
|
||||
maxEntropy: 512 / 8,
|
||||
parentFingerPrintSize: 4,
|
||||
pathRoots: ['m', 'M', 'm\'', 'M\'']
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user