diff --git a/BIP32.js b/BIP32.js index 6efb73a..878a1ac 100644 --- a/BIP32.js +++ b/BIP32.js @@ -2,6 +2,7 @@ var imports = require('soop').imports(); var base58 = imports.base58 || require('base58-native').base58; var coinUtil = imports.coinUtil || require('./util/util'); var Key = imports.Key || require('./Key'); +var Point = imports.Point || require('./Point'); var bignum = imports.bignum || require('bignum'); var crypto = require('crypto'); var networks = require('./networks'); @@ -266,31 +267,20 @@ BIP32.prototype.derive_child = function(i) { var ir = hash.slice(32, 64); // Ki = (IL + kpar)*G = IL*G + Kpar - var key = new Key(); - key.private = il.toBuffer({size: 32}); - key.regenerateSync(); - key.compressed = false; + var ilGkey = new Key(); + ilGkey.private = il.toBuffer({size: 32}); + ilGkey.regenerateSync(); + var ilG = Point.fromKey(ilGkey); var oldkey = new Key(); oldkey.public = this.eckey.public; - oldkey.compressed = false; - var newpub = Key.addUncompressed(key.public, oldkey.public); - - var eckey = new Key(); - eckey.compressed = false; - eckey.public = newpub; - if (eckey.public === null) { - console.log('invalid public key'); - return this.derive_child(i+1); - } - eckey.compressed = true; + var Kpar = Point.fromKey(oldkey); + var newpub = Point.add(ilG, Kpar).toKey().public; ret = new BIP32(); ret.chain_code = new Buffer(ir); var eckey = new Key(); - eckey.compressed = false; eckey.public = newpub; - eckey.compressed = true; ret.eckey = eckey; ret.has_private_key = false; } diff --git a/Point.js b/Point.js new file mode 100644 index 0000000..b028e37 --- /dev/null +++ b/Point.js @@ -0,0 +1,75 @@ +var imports = require('soop').imports(); +var Key = imports.Key || require('./Key'); +var bignum = imports.bignum || require('bignum'); + +//a point on the secp256k1 curve +//x and y are bignums +var Point = function(x, y) { + this.x = x; + this.y = y; +}; + +Point.add = function(p1, p2) { + + //node + if (process.versions) { + var key1 = p1.toKey(); + key1.compressed = false; + var key2 = p2.toKey(); + key2.compressed = false; + var pubKey = Key.addUncompressed(key1.public, key2.public); + var key = new Key(); + key.compressed = false; + key.public = pubKey; + key.compressed = true; + return Point.fromKey(key); + } + + //browser + else { + } + +}; + +//convert the public key of a Key into a Point +Point.fromKey = function(key) { + + //node + if (process.versions) { + var point = new Point(); + var pubKeyBuf = new Buffer(key.public); + var key2 = new Key(); + key2.compressed = key.compressed; + key2.public = pubKeyBuf; + key2.compressed = false; + point.x = bignum.fromBuffer(key2.public.slice(1, 33), {size: 32}); + point.y = bignum.fromBuffer(key2.public.slice(33, 65), {size: 32}); + return point; + } + + //browser + else { + } +}; + +//convert the Point into the Key containing a compressed public key +Point.prototype.toKey = function() { + + //node + if (process.versions) { + var xbuf = this.x.toBuffer({size: 32}); + var ybuf = this.y.toBuffer({size: 32}); + var key = new Key(); + key.compressed = false; + var prefix = new Buffer([0x04]); + key.public = Buffer.concat([prefix, xbuf, ybuf]); //this is probably wrong + key.compressed = true; + return key; + } + + //browser + else { + } +}; + +module.exports = require('soop')(Point);