Browse Source

hdkey: use the secp256k1 package for crypto

master
Alex Beregszaszi 9 years ago
parent
commit
a63bb73084
  1. 38
      lib/hdkey.js
  2. 3
      package.json

38
lib/hdkey.js

@ -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

3
package.json

@ -31,8 +31,9 @@
},
"dependencies": {
"bigi": "^1.1.0",
"coinstring": "^2.0.0",
"ecurve": "^1.0.0",
"coinstring": "^2.0.0"
"secp256k1": "^3.0.1"
},
"scripts": {
"browser-test": "mochify --wd -R spec",

Loading…
Cancel
Save