hd and ec refactor.
This commit is contained in:
parent
6690991acb
commit
3cea8323b0
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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\'']
|
||||
};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user