|
|
@ -1,10 +1,7 @@ |
|
|
|
var assert = require('assert') |
|
|
|
var crypto = require('crypto') |
|
|
|
var BigInteger = require('bigi') |
|
|
|
var cs = require('coinstring') |
|
|
|
var ecurve = require('ecurve') |
|
|
|
var curve = ecurve.getCurveByName('secp256k1') |
|
|
|
var Point = ecurve.Point |
|
|
|
var secp256k1 = require('secp256k1') |
|
|
|
|
|
|
|
var MASTER_SECRET = new Buffer('Bitcoin seed') |
|
|
|
var HARDENED_OFFSET = 0x80000000 |
|
|
@ -34,9 +31,10 @@ Object.defineProperty(HDKey.prototype, 'privateKey', { |
|
|
|
}, |
|
|
|
set: function (value) { |
|
|
|
assert.equal(value.length, 32, 'Private key must be 32 bytes.') |
|
|
|
assert(secp256k1.privateKeyVerify(value) === true, 'Invalid private key') |
|
|
|
|
|
|
|
this._privateKey = value |
|
|
|
this._publicPoint = curve.G.multiply(BigInteger.fromBuffer(this._privateKey)) |
|
|
|
this._publicKey = this._publicPoint.getEncoded(true) // force compressed point
|
|
|
|
this._publicKey = secp256k1.publicKeyCreate(value, true) |
|
|
|
this._identifier = hash160(this.publicKey) |
|
|
|
this._fingerprint = this._identifier.slice(0, 4).readUInt32BE(0) |
|
|
|
} |
|
|
@ -48,8 +46,9 @@ Object.defineProperty(HDKey.prototype, 'publicKey', { |
|
|
|
}, |
|
|
|
set: function (value) { |
|
|
|
assert(value.length === 33 || value.length === 65, 'Public key must be 33 or 65 bytes.') |
|
|
|
this._publicPoint = Point.decodeFrom(curve, value) |
|
|
|
this._publicKey = this._publicPoint.getEncoded(true) // force compressed point
|
|
|
|
assert(secp256k1.publicKeyVerify(value) === true, 'Invalid public key') |
|
|
|
|
|
|
|
this._publicKey = secp256k1.publicKeyConvert(value, true) // force compressed point
|
|
|
|
this._identifier = hash160(this.publicKey) |
|
|
|
this._fingerprint = this._identifier.slice(0, 4).readUInt32BE(0) |
|
|
|
this._privateKey = null |
|
|
@ -119,33 +118,28 @@ HDKey.prototype.deriveChild = function (index) { |
|
|
|
var IR = I.slice(32) |
|
|
|
|
|
|
|
var hd = new HDKey(this.versions) |
|
|
|
var pIL = BigInteger.fromBuffer(IL) |
|
|
|
|
|
|
|
// Private parent key -> private child key
|
|
|
|
if (this.privateKey) { |
|
|
|
// ki = parse256(IL) + kpar (mod n)
|
|
|
|
var ki = pIL.add(BigInteger.fromBuffer(this.privateKey)).mod(curve.n) |
|
|
|
|
|
|
|
try { |
|
|
|
hd.privateKey = secp256k1.privateKeyTweakAdd(this.privateKey, IL) |
|
|
|
// throw if IL >= n || (privateKey + IL) === 0
|
|
|
|
} catch (err) { |
|
|
|
// In case parse256(IL) >= n or ki == 0, one should proceed with the next value for i
|
|
|
|
if (pIL.compareTo(curve.n) >= 0 || ki.signum() === 0) { |
|
|
|
return this.derive(index + 1) |
|
|
|
} |
|
|
|
|
|
|
|
// if less than 32 bytes, pad with 0's
|
|
|
|
hd.privateKey = ki.toBuffer(32) |
|
|
|
|
|
|
|
// Public parent key -> public child key
|
|
|
|
} else { |
|
|
|
// Ki = point(parse256(IL)) + Kpar
|
|
|
|
// = G*IL + Kpar
|
|
|
|
var Ki = curve.G.multiply(pIL).add(this._publicPoint) |
|
|
|
|
|
|
|
try { |
|
|
|
hd.publicKey = secp256k1.publicKeyTweakAdd(this.publicKey, IL, true) |
|
|
|
// throw if IL >= n || (g**IL + publicKey) is infinity
|
|
|
|
} catch (err) { |
|
|
|
// In case parse256(IL) >= n or Ki is the point at infinity, one should proceed with the next value for i
|
|
|
|
if (pIL.compareTo(curve.n) >= 0 || curve.isInfinity(Ki)) { |
|
|
|
return this.derive(index + 1) |
|
|
|
return this.derive(index + 1, isHardened) |
|
|
|
} |
|
|
|
|
|
|
|
hd.publicKey = Ki.getEncoded(true) |
|
|
|
} |
|
|
|
|
|
|
|
hd.chainCode = IR |
|
|
|