hd and ec refactor.

This commit is contained in:
Christopher Jeffrey 2016-05-14 10:54:00 -07:00
parent 6690991acb
commit 3cea8323b0
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
3 changed files with 38 additions and 44 deletions

View File

@ -119,15 +119,16 @@ ec.rand = function rand(min, max) {
*/
ec.verify = function verify(msg, sig, key, historical, high) {
if (!Buffer.isBuffer(sig))
return false;
if (key.getPublicKey)
key = key.getPublicKey();
assert(Buffer.isBuffer(msg));
assert(Buffer.isBuffer(sig));
assert(Buffer.isBuffer(key));
if (sig.length === 0)
return false;
if (key.getPublicKey)
key = key.getPublicKey();
if (key.length === 0)
return false;
@ -150,14 +151,14 @@ ec.verify = function verify(msg, sig, key, historical, high) {
return secp256k1.verify(msg, sig, key);
}
// Make elliptic mimic secp256k1's
// failure with high S values.
if (!high && !ec.isLowS(sig))
return false;
return ec.elliptic.verify(msg, sig, key);
} catch (e) {
// if (!ec.publicKeyVerify(key))
// bcoin.debug('Public key is invalid.');
return false;
}
};
@ -294,9 +295,6 @@ ec.isLowS = function isLowS(sig) {
}
}
// Technically a negative S value is low,
// but we don't want to ever use negative
// S values in bitcoin.
if (sig.s.cmpn(0) <= 0)
return false;

View File

@ -359,14 +359,14 @@ HD.isExtended = function isExtended(data) {
HD.parsePath = function parsePath(path, max) {
var parts = path.split('/');
var root = parts.shift();
var indexes = [];
var result = [];
var i, hardened, index;
if (max == null)
max = constants.hd.MAX_INDEX;
if (constants.hd.PATH_ROOTS.indexOf(path) !== -1)
return indexes;
return result;
if (constants.hd.PATH_ROOTS.indexOf(root) === -1)
throw new Error('Bad path root.');
@ -378,21 +378,21 @@ HD.parsePath = function parsePath(path, max) {
if (hardened)
index = index.slice(0, -1);
index = +index;
if (!(index >= 0))
if (!/^\d+$/.test(index))
throw new Error('Non-number path index.');
index = +index;
if (hardened)
index += constants.hd.HARDENED;
if (!(index >= 0 && index < max))
throw new Error('Index out of range.');
indexes.push(index);
result.push(index);
}
return indexes;
return result;
};
/**
@ -496,15 +496,16 @@ HDPrivateKey.prototype.__defineGetter__('xpubkey', function() {
*/
HDPrivateKey.prototype.derive = function derive(index, hardened) {
var cached, p, data, hash, leftPart, chainCode, privateKey, child;
var p, id, data, hash, left, chainCode, privateKey, child;
if (typeof index === 'string')
return this.derivePath(index);
cached = HD.cache.get(this.xprivkey + '/' + index);
id = this.xprivkey + '/' + index;
child = HD.cache.get(id);
if (cached)
return cached;
if (child)
return child;
hardened = index >= constants.hd.HARDENED ? true : hardened;
if (index < constants.hd.HARDENED && hardened)
@ -527,18 +528,16 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
data = p.render();
hash = utils.hmac('sha512', data, this.chainCode);
leftPart = new bn(hash.slice(0, 32));
left = new bn(hash.slice(0, 32));
chainCode = hash.slice(32, 64);
privateKey = leftPart
privateKey = left
.add(new bn(this.privateKey))
.mod(ec.elliptic.curve.n)
.toBuffer('be', 32);
if (!this.fingerPrint) {
this.fingerPrint = utils.ripesha(this.publicKey)
.slice(0, constants.hd.PARENT_FINGERPRINT_SIZE);
}
if (!this.fingerPrint)
this.fingerPrint = utils.ripesha(this.publicKey).slice(0, 4);
child = new HDPrivateKey({
network: this.network,
@ -549,7 +548,7 @@ HDPrivateKey.prototype.derive = function derive(index, hardened) {
privateKey: privateKey
});
HD.cache.set(this.xprivkey + '/' + index, child);
HD.cache.set(id, child);
return child;
};
@ -702,9 +701,6 @@ HDPrivateKey.prototype.derivePath = function derivePath(path) {
HDPrivateKey.parseSeed = function parseSeed(seed, network) {
var hash, chainCode, privateKey;
if (!seed)
seed = {};
assert(Buffer.isBuffer(seed));
if (seed.length < constants.hd.MIN_ENTROPY
@ -759,6 +755,8 @@ HDPrivateKey.fromMnemonic = function fromMnemonic(mnemonic, network) {
if (mnemonic.seed || mnemonic.phrase || mnemonic.entropy)
return HDPrivateKey.fromSeed(mnemonic.toSeed(), network);
// Very unlikely, but not impossible
// to get an invalid private key.
for (;;) {
try {
key = HDPrivateKey.fromSeed(mnemonic.toSeed(), network);
@ -1083,16 +1081,17 @@ HDPublicKey.prototype.__defineGetter__('xpubkey', function() {
*/
HDPublicKey.prototype.derive = function derive(index, hardened) {
var cached, p, data, hash, leftPart, chainCode;
var p, id, data, hash, left, chainCode;
var publicPoint, point, publicKey, child;
if (typeof index === 'string')
return this.derivePath(index);
cached = HD.cache.get(this.xpubkey + '/' + index);
id = this.xpubkey + '/' + index;
child = HD.cache.get(id);
if (cached)
return cached;
if (child)
return child;
if (index >= constants.hd.HARDENED || hardened)
throw new Error('Index out of range.');
@ -1106,18 +1105,16 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
data = p.render();
hash = utils.hmac('sha512', data, this.chainCode);
leftPart = new bn(hash.slice(0, 32));
left = new bn(hash.slice(0, 32));
chainCode = hash.slice(32, 64);
publicPoint = ec.elliptic.curve.decodePoint(this.publicKey);
point = ec.elliptic.curve.g.mul(leftPart).add(publicPoint);
point = ec.elliptic.curve.g.mul(left).add(publicPoint);
publicKey = new Buffer(point.encode('array', true));
assert(publicKey.length === 33);
if (!this.fingerPrint) {
this.fingerPrint = utils.ripesha(this.publicKey)
.slice(0, constants.hd.PARENT_FINGERPRINT_SIZE);
}
if (!this.fingerPrint)
this.fingerPrint = utils.ripesha(this.publicKey).slice(0, 4);
child = new HDPublicKey({
network: this.network,
@ -1128,7 +1125,7 @@ HDPublicKey.prototype.derive = function derive(index, hardened) {
publicKey: publicKey
});
HD.cache.set(this.xpubkey + '/' + index, child);
HD.cache.set(id, child);
return child;
};

View File

@ -515,10 +515,9 @@ exports.rejectByVal = utils.revMap(exports.reject);
exports.hd = {
HARDENED: 0x80000000,
MAX_INDEX: 2 * 0x80000000,
MAX_INDEX: 0x100000000,
MIN_ENTROPY: 128 / 8,
MAX_ENTROPY: 512 / 8,
PARENT_FINGERPRINT_SIZE: 4,
PATH_ROOTS: ['m', 'M', 'm\'', 'M\'']
};