use libsecp256k1 for hd derivation.
This commit is contained in:
parent
350c76d49b
commit
850b16fa7d
@ -134,6 +134,52 @@ ec.publicKeyConvert = function publicKeyConvert(key, compressed) {
|
|||||||
return new Buffer(point.encode('array', compressed));
|
return new Buffer(point.encode('array', compressed));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ((tweak + key) % n)
|
||||||
|
* @param {Buffer} privateKey
|
||||||
|
* @param {Buffer} tweak
|
||||||
|
* @returns {Buffer} privateKey
|
||||||
|
*/
|
||||||
|
|
||||||
|
ec.privateKeyTweakAdd = function privateKeyTweakAdd(privateKey, tweak) {
|
||||||
|
if (secp256k1)
|
||||||
|
return secp256k1.privateKeyTweakAdd(privateKey, tweak);
|
||||||
|
|
||||||
|
privateKey = new bn(tweak)
|
||||||
|
.add(new bn(privateKey))
|
||||||
|
.mod(ec.curve.n)
|
||||||
|
.toArrayLike(Buffer, 'be', 32);
|
||||||
|
|
||||||
|
// Only a 1 in 2^127 chance of happening.
|
||||||
|
if (!ec.privateKeyVerify(privateKey))
|
||||||
|
throw new Error('Private key is invalid.');
|
||||||
|
|
||||||
|
return privateKey;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ((g * tweak) + key)
|
||||||
|
* @param {Buffer} publicKey
|
||||||
|
* @param {Buffer} tweak
|
||||||
|
* @returns {Buffer} publicKey
|
||||||
|
*/
|
||||||
|
|
||||||
|
ec.publicKeyTweakAdd = function publicKeyTweakAdd(publicKey, tweak, compressed) {
|
||||||
|
var point;
|
||||||
|
|
||||||
|
if (secp256k1)
|
||||||
|
return secp256k1.publicKeyTweakAdd(publicKey, tweak, compressed);
|
||||||
|
|
||||||
|
point = ec.decodePoint(publicKey);
|
||||||
|
point = ec.curve.g.mul(new bn(tweak)).add(point);
|
||||||
|
publicKey = new Buffer(point.encode('array', compressed));
|
||||||
|
|
||||||
|
if (!ec.publicKeyVerify(publicKey))
|
||||||
|
throw new Error('Public key is invalid.');
|
||||||
|
|
||||||
|
return publicKey;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an ecdh.
|
* Create an ecdh.
|
||||||
* @param {Buffer} pub
|
* @param {Buffer} pub
|
||||||
|
|||||||
@ -945,7 +945,7 @@ HDPrivateKey.prototype.__defineGetter__('xpubkey', function() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
||||||
var p, id, data, hash, left, chainCode, privateKey, child;
|
var p, id, data, hash, left, right, privateKey, child;
|
||||||
|
|
||||||
if (typeof index === 'string')
|
if (typeof index === 'string')
|
||||||
return this.derivePath(index);
|
return this.derivePath(index);
|
||||||
@ -981,17 +981,14 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||||||
data = p.render();
|
data = p.render();
|
||||||
|
|
||||||
hash = utils.hmac('sha512', data, this.chainCode);
|
hash = utils.hmac('sha512', data, this.chainCode);
|
||||||
left = new bn(hash.slice(0, 32));
|
left = hash.slice(0, 32);
|
||||||
chainCode = hash.slice(32, 64);
|
right = hash.slice(32, 64);
|
||||||
|
|
||||||
privateKey = left
|
try {
|
||||||
.add(new bn(this.privateKey))
|
privateKey = ec.privateKeyTweakAdd(this.privateKey, left);
|
||||||
.mod(ec.curve.n)
|
} catch (e) {
|
||||||
.toArrayLike(Buffer, 'be', 32);
|
return this.derive(index + 1);
|
||||||
|
}
|
||||||
// Only a 1 in 2^127 chance of happening.
|
|
||||||
if (!ec.privateKeyVerify(privateKey))
|
|
||||||
throw new Error('Private key is invalid.');
|
|
||||||
|
|
||||||
if (!this.fingerPrint)
|
if (!this.fingerPrint)
|
||||||
this.fingerPrint = utils.hash160(this.publicKey).slice(0, 4);
|
this.fingerPrint = utils.hash160(this.publicKey).slice(0, 4);
|
||||||
@ -1001,7 +998,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
|
|||||||
child.depth = this.depth + 1;
|
child.depth = this.depth + 1;
|
||||||
child.parentFingerPrint = this.fingerPrint;
|
child.parentFingerPrint = this.fingerPrint;
|
||||||
child.childIndex = index;
|
child.childIndex = index;
|
||||||
child.chainCode = chainCode;
|
child.chainCode = right;
|
||||||
child.privateKey = privateKey;
|
child.privateKey = privateKey;
|
||||||
child.publicKey = ec.publicKeyCreate(privateKey, true);
|
child.publicKey = ec.publicKeyCreate(privateKey, true);
|
||||||
|
|
||||||
@ -1179,7 +1176,7 @@ HDPrivateKey.prototype.equal = function equal(obj) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
||||||
var hash, chainCode, privateKey;
|
var hash, left, right;
|
||||||
|
|
||||||
assert(Buffer.isBuffer(seed));
|
assert(Buffer.isBuffer(seed));
|
||||||
|
|
||||||
@ -1190,19 +1187,19 @@ HDPrivateKey.prototype.fromSeed = function fromSeed(seed, network) {
|
|||||||
|
|
||||||
hash = utils.hmac('sha512', seed, 'Bitcoin seed');
|
hash = utils.hmac('sha512', seed, 'Bitcoin seed');
|
||||||
|
|
||||||
privateKey = hash.slice(0, 32);
|
left = hash.slice(0, 32);
|
||||||
chainCode = hash.slice(32, 64);
|
right = hash.slice(32, 64);
|
||||||
|
|
||||||
// Only a 1 in 2^127 chance of happening.
|
// Only a 1 in 2^127 chance of happening.
|
||||||
if (!ec.privateKeyVerify(privateKey))
|
if (!ec.privateKeyVerify(left))
|
||||||
throw new Error('Master private key is invalid.');
|
throw new Error('Master private key is invalid.');
|
||||||
|
|
||||||
this.network = bcoin.network.get(network);
|
this.network = bcoin.network.get(network);
|
||||||
this.depth = 0;
|
this.depth = 0;
|
||||||
this.parentFingerPrint = new Buffer([0, 0, 0, 0]);
|
this.parentFingerPrint = new Buffer([0, 0, 0, 0]);
|
||||||
this.childIndex = 0;
|
this.childIndex = 0;
|
||||||
this.chainCode = chainCode;
|
this.chainCode = right;
|
||||||
this.privateKey = privateKey;
|
this.privateKey = left;
|
||||||
this.publicKey = ec.publicKeyCreate(this.privateKey, true);
|
this.publicKey = ec.publicKeyCreate(this.privateKey, true);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
@ -1597,7 +1594,7 @@ HDPublicKey.prototype.__defineGetter__('xpubkey', function() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
HDPublicKey.prototype.derive = function derive(index, hardened) {
|
HDPublicKey.prototype.derive = function derive(index, hardened) {
|
||||||
var p, id, data, hash, left, chainCode, point, publicKey, child;
|
var p, id, data, hash, left, right, publicKey, child;
|
||||||
|
|
||||||
if (typeof index === 'string')
|
if (typeof index === 'string')
|
||||||
return this.derivePath(index);
|
return this.derivePath(index);
|
||||||
@ -1623,16 +1620,14 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||||||
data = p.render();
|
data = p.render();
|
||||||
|
|
||||||
hash = utils.hmac('sha512', data, this.chainCode);
|
hash = utils.hmac('sha512', data, this.chainCode);
|
||||||
left = new bn(hash.slice(0, 32));
|
left = hash.slice(0, 32);
|
||||||
chainCode = hash.slice(32, 64);
|
right = hash.slice(32, 64);
|
||||||
|
|
||||||
point = ec.decodePoint(this.publicKey);
|
try {
|
||||||
point = ec.curve.g.mul(left).add(point);
|
publicKey = ec.publicKeyTweakAdd(this.publicKey, left, true);
|
||||||
publicKey = new Buffer(point.encode('array', true));
|
} catch (e) {
|
||||||
assert(publicKey.length === 33);
|
return this.derive(index + 1);
|
||||||
|
}
|
||||||
if (!ec.publicKeyVerify(publicKey))
|
|
||||||
throw new Error('Public key is invalid.');
|
|
||||||
|
|
||||||
if (!this.fingerPrint)
|
if (!this.fingerPrint)
|
||||||
this.fingerPrint = utils.hash160(this.publicKey).slice(0, 4);
|
this.fingerPrint = utils.hash160(this.publicKey).slice(0, 4);
|
||||||
@ -1642,7 +1637,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
|
|||||||
child.depth = this.depth + 1;
|
child.depth = this.depth + 1;
|
||||||
child.parentFingerPrint = this.fingerPrint;
|
child.parentFingerPrint = this.fingerPrint;
|
||||||
child.childIndex = index;
|
child.childIndex = index;
|
||||||
child.chainCode = chainCode;
|
child.chainCode = right;
|
||||||
child.publicKey = publicKey;
|
child.publicKey = publicKey;
|
||||||
|
|
||||||
HD.cache.set(id, child);
|
HD.cache.set(id, child);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user