From e2655f553d958c34bca61717c7298cd525d5fec2 Mon Sep 17 00:00:00 2001 From: olalonde Date: Mon, 5 May 2014 15:20:59 +0800 Subject: [PATCH] Added EC Point multiplication to browser/Point.js --- lib/Armory.js | 41 +++++++++++++++++++++++++++++++++++++++++ lib/browser/Point.js | 24 ++++++++++++++++++++++++ 2 files changed, 65 insertions(+) create mode 100644 lib/Armory.js diff --git a/lib/Armory.js b/lib/Armory.js new file mode 100644 index 0000000..03a7b10 --- /dev/null +++ b/lib/Armory.js @@ -0,0 +1,41 @@ +var Point = require('./browser/Point'), + twoSha256 = require('../util').twoSha256, + BigInteger = require('../browser/vendor-bundle.js').BigInteger; + +// TODO: use native modules instead of browser libraries + +/** + * For now, this class can only supports derivation from public key + * It doesn't support private key derivation (TODO). + * + * @example examples/Armory.js + */ +function Armory (chaincode, pubkey) { + this.chaincode = new Buffer(chaincode, 'hex'); + this.pubkey = new Buffer(pubkey, 'hex'); +} + +Armory.prototype.generatePubKey = function () { + var pubKey = this.pubkey; + var chainCode = this.chaincode; + var chainXor = twoSha256(pubKey); + + for (var i = 0; i < 32; i++) + chainXor[i] ^= chainCode[i]; + + var A = new BigInteger(chainXor.toString('hex'), 16); + + var pt = Point.fromUncompressedPubKey(pubKey); + pt = Point.multiply(pt, A); + + var new_pubkey = pt.toUncompressedPubKey(); + + return new_pubkey; +}; + +Armory.prototype.next = function () { + var next_pubkey = this.generatePubKey(); + return new Armory(this.chaincode, next_pubkey); +}; + +module.exports = Armory; diff --git a/lib/browser/Point.js b/lib/browser/Point.js index 1e935e0..5dd40b9 100644 --- a/lib/browser/Point.js +++ b/lib/browser/Point.js @@ -48,6 +48,30 @@ Point.add = function(p1, p2) { return point; }; +Point.multiply = function(p1, A) { + var ecparams = getSECCurveByName('secp256k1'); + + var p1xhex = p1.x.toBuffer({size: 32}).toString('hex'); + var p1x = new BigInteger(p1xhex, 16); + var p1yhex = p1.y.toBuffer({size: 32}).toString('hex'); + var p1y = new BigInteger(p1yhex, 16); + var p1px = new ECFieldElementFp(ecparams.getCurve().getQ(), p1x); + var p1py = new ECFieldElementFp(ecparams.getCurve().getQ(), p1y); + var p1p = new ECPointFp(ecparams.getCurve(), p1px, p1py); + + var p = p1p.multiply(A); + + var point = new Point(); + var pointxbuf = new Buffer(p.getX().toBigInteger().toByteArrayUnsigned()); + point.x = bignum.fromBuffer(pointxbuf, {size: pointxbuf.length}); + assert(pointxbuf.length <= 32); + var pointybuf = new Buffer(p.getY().toBigInteger().toByteArrayUnsigned()); + assert(pointybuf.length <= 32); + point.y = bignum.fromBuffer(pointybuf, {size: pointybuf.length}); + + return point; +}; + //convert the public key of a Key into a Point Point.fromUncompressedPubKey = function(pubkey) { var point = new Point();