From abc799f45338cd498e64460c7afb768e732bb427 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Sat, 19 Apr 2014 20:10:05 -0300 Subject: [PATCH 1/4] split up Point into separate node and browser versions --- lib/Point.browser.js | 81 +++++++++++++++++++++++++ lib/Point.js | 141 ++----------------------------------------- lib/Point.node.js | 53 ++++++++++++++++ test/test.Point.js | 2 +- 4 files changed, 139 insertions(+), 138 deletions(-) create mode 100644 lib/Point.browser.js create mode 100644 lib/Point.node.js diff --git a/lib/Point.browser.js b/lib/Point.browser.js new file mode 100644 index 0000000..dacf965 --- /dev/null +++ b/lib/Point.browser.js @@ -0,0 +1,81 @@ +"use strict"; + +var imports = require('soop').imports(); +var Key = imports.Key || require('./Key'); +var bignum = imports.bignum || require('bignum'); +var assert = require('assert'); +var ECKey = require('../browser/vendor-bundle.js').ECKey; +var ECPointFp = require('../browser/vendor-bundle.js').ECPointFp; +var ECFieldElementFp = require('../browser/vendor-bundle.js').ECFieldElementFp; +var getSECCurveByName = require('../browser/vendor-bundle.js').getSECCurveByName; +var BigInteger = require('../browser/vendor-bundle.js').BigInteger; +var should = require('chai').should(); + +//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) { + 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 p2xhex = p2.x.toBuffer({size: 32}).toString('hex'); + var p2x = new BigInteger(p2xhex, 16); + var p2yhex = p2.y.toBuffer({size: 32}).toString('hex'); + var p2y = new BigInteger(p2yhex, 16); + var p2px = new ECFieldElementFp(ecparams.getCurve().getQ(), p2x); + var p2py = new ECFieldElementFp(ecparams.getCurve().getQ(), p2y); + var p2p = new ECPointFp(ecparams.getCurve(), p2px, p2py); + + var p = p1p.add(p2p); + + 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.fromKey = function(key) { + var point = new Point(); + var pubKeyBuf = new Buffer(key.public); + var key2 = new ECKey(); + key2.setCompressed(key.compressed); + key2.setPub(Key.bufferToArray(pubKeyBuf)); + key2.setCompressed(false); + point.x = bignum.fromBuffer((new Buffer(key2.getPub())).slice(1, 33), {size: 32}); + point.y = bignum.fromBuffer((new Buffer(key2.getPub())).slice(33, 65), {size: 32}); + return point; +}; + +//convert the Point into the Key containing a compressed public key +Point.prototype.toKey = function() { + var xbuf = this.x.toBuffer({size: 32}); + var ybuf = this.y.toBuffer({size: 32}); + var key = new ECKey(); + key.setCompressed(false); + var prefix = new Buffer([0x04]); + var pub = Buffer.concat([prefix, xbuf, ybuf]); //this might be wrong + key.setPub(Key.bufferToArray(pub)); + key.setCompressed(true); + var key2 = new Key(); + key2.public = new Buffer(key.getPub()); + return key2; +}; + +module.exports = require('soop')(Point); diff --git a/lib/Point.js b/lib/Point.js index 424529f..fc611ec 100644 --- a/lib/Point.js +++ b/lib/Point.js @@ -1,138 +1,5 @@ -"use strict"; - -var imports = require('soop').imports(); -var Key = imports.Key || require('./Key'); -var bignum = imports.bignum || require('bignum'); -var assert = require('assert'); - -//browser -if (!process.versions) { - var ECKey = require('../browser/vendor-bundle.js').ECKey; - var ECPointFp = require('../browser/vendor-bundle.js').ECPointFp; - var ECFieldElementFp = require('../browser/vendor-bundle.js').ECFieldElementFp; - var getSECCurveByName = require('../browser/vendor-bundle.js').getSECCurveByName; - var BigInteger = require('../browser/vendor-bundle.js').BigInteger; - var should = require('chai').should(); +if (process.versions) { + module.exports = require('./Point.node'); + return; } - - -//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 { - 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 p2xhex = p2.x.toBuffer({size: 32}).toString('hex'); - var p2x = new BigInteger(p2xhex, 16); - var p2yhex = p2.y.toBuffer({size: 32}).toString('hex'); - var p2y = new BigInteger(p2yhex, 16); - var p2px = new ECFieldElementFp(ecparams.getCurve().getQ(), p2x); - var p2py = new ECFieldElementFp(ecparams.getCurve().getQ(), p2y); - var p2p = new ECPointFp(ecparams.getCurve(), p2px, p2py); - - var p = p1p.add(p2p); - - 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.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 { - var point = new Point(); - var pubKeyBuf = new Buffer(key.public); - var key2 = new ECKey(); - key2.setCompressed(key.compressed); - key2.setPub(Key.bufferToArray(pubKeyBuf)); - key2.setCompressed(false); - point.x = bignum.fromBuffer((new Buffer(key2.getPub())).slice(1, 33), {size: 32}); - point.y = bignum.fromBuffer((new Buffer(key2.getPub())).slice(33, 65), {size: 32}); - return point; - } -}; - -//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 might be wrong - key.compressed = true; - return key; - } - - //browser - else { - var xbuf = this.x.toBuffer({size: 32}); - var ybuf = this.y.toBuffer({size: 32}); - var key = new ECKey(); - key.setCompressed(false); - var prefix = new Buffer([0x04]); - var pub = Buffer.concat([prefix, xbuf, ybuf]); //this might be wrong - key.setPub(Key.bufferToArray(pub)); - key.setCompressed(true); - var key2 = new Key(); - key2.public = new Buffer(key.getPub()); - return key2; - } -}; - -module.exports = require('soop')(Point); +module.exports = require('./Point.browser'); diff --git a/lib/Point.node.js b/lib/Point.node.js new file mode 100644 index 0000000..a3d2f45 --- /dev/null +++ b/lib/Point.node.js @@ -0,0 +1,53 @@ +"use strict"; + +var imports = require('soop').imports(); +var Key = imports.Key || require('./Key'); +var bignum = imports.bignum || require('bignum'); +var assert = require('assert'); + +//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) { + 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); +}; + +//convert the public key of a Key into a Point +Point.fromKey = function(key) { + 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; +}; + +//convert the Point into the Key containing a compressed public key +Point.prototype.toKey = function() { + 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 might be wrong + key.compressed = true; + return key; +}; + +module.exports = require('soop')(Point); diff --git a/test/test.Point.js b/test/test.Point.js index 251acbd..66e32c1 100644 --- a/test/test.Point.js +++ b/test/test.Point.js @@ -12,7 +12,7 @@ var assert = chai.assert; var Point = bitcore.Point; var Key = bitcore.Key; -describe('Key', function() { +describe('Point', function() { it('should initialize the main object', function() { should.exist(Point); From 05d86b64535063f6c9bf6a4309acec39489b1f2c Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Sun, 20 Apr 2014 11:19:54 -0300 Subject: [PATCH 2/4] split up Key into Key.browser and Key.node --- lib/Key.browser.js | 102 +++++++++++++++++++++++++++++++++++++++ lib/Key.js | 116 ++------------------------------------------- lib/Key.node.js | 1 + 3 files changed, 106 insertions(+), 113 deletions(-) create mode 100644 lib/Key.browser.js create mode 100644 lib/Key.node.js diff --git a/lib/Key.browser.js b/lib/Key.browser.js new file mode 100644 index 0000000..b172e64 --- /dev/null +++ b/lib/Key.browser.js @@ -0,0 +1,102 @@ +var ECKey = require('../browser/vendor-bundle.js').ECKey; +var buffertools = require('buffertools'); + +var Key = function() { + this._pub = null; + this.compressed = true; // default +}; + +var bufferToArray = Key.bufferToArray = function(buffer) { + var ret = []; + + var l = buffer.length; + for(var i =0; i Date: Sun, 20 Apr 2014 13:00:24 -0300 Subject: [PATCH 3/4] split Key node tests into separate file --- test/test.Key.js | 74 --------------------------------------- test/test.Key.node.js | 81 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 74 deletions(-) create mode 100644 test/test.Key.node.js diff --git a/test/test.Key.js b/test/test.Key.js index 3320e4f..25cdb26 100644 --- a/test/test.Key.js +++ b/test/test.Key.js @@ -1,4 +1,3 @@ - var chai = chai || require('chai'); var bitcore = bitcore || require('../bitcore'); var coinUtil = coinUtil || bitcore.util; @@ -113,77 +112,4 @@ describe('Key', function() { var ret= k.verifySignatureSync(a_hash, sig2); ret.should.equal(false); }); - - - //node tests only - //addUncompressed is a node-only interface feature - if (typeof process !== 'undefined' && process.versions) { - describe('#addUncompressed', function() { - it('should exist', function() { - should.exist(Key.addUncompressed); - }); - - it('should add two uncompressed public keys', function() { - var key1 = Key.generateSync(); - key1.compressed = false; - var key2 = Key.generateSync(); - key2.compressed = false; - var pubkey1 = key1.public; - var pubkey2 = key2.public; - var pubkey = Key.addUncompressed(pubkey1, pubkey2); - pubkey.length.should.equal(65); - }); - - it('a + b should equal b + a', function() { - var key1 = Key.generateSync(); - key1.compressed = false; - var key2 = Key.generateSync(); - key2.compressed = false; - var pubkey1 = key1.public; - var pubkey2 = key2.public; - var r1 = Key.addUncompressed(pubkey1, pubkey2); - var r2 = Key.addUncompressed(pubkey2, pubkey1); - r1.toString('hex').should.equal(r2.toString('hex')); - }); - - it('should be able to add these two public keys without error', function() { - var key1 = new Key(); - key1.private = coinUtil.sha256("first " + 3); - key1.compressed = false; - key1.regenerateSync(); - var key2 = new Key(); - key2.private = coinUtil.sha256("second " + 3); - key2.compressed = false; - key2.regenerateSync(); - var pubkey1 = key1.public; - var pubkey2 = key2.public; - var pubkey = Key.addUncompressed(pubkey1, pubkey2); - pubkey.length.should.equal(65); - var key = new Key(); - key.public = pubkey; - assert(key.public !== null); - }); - - }); - - describe('node only Key functionality', function() { - it('should not fail when called as Key() without "new"', function() { - var key = Key(); - should.exist(key); - }); - it('should not fail when called as Key() without "new" with some args', function() { - var key = Key(1, 2, 3, 4, 5); - should.exist(key); - }); - it('should have correct properties when called with Key() without "new"', function() { - var key = Key(); - key.compressed.should.equal(true); - should.not.exist(key.public); - should.not.exist(key.private); - should.exist(key); - }); - - }); - } - }); diff --git a/test/test.Key.node.js b/test/test.Key.node.js new file mode 100644 index 0000000..538572e --- /dev/null +++ b/test/test.Key.node.js @@ -0,0 +1,81 @@ +var chai = chai || require('chai'); +var bitcore = bitcore || require('../bitcore'); +var coinUtil = coinUtil || bitcore.util; +var buffertools = require('buffertools'); + +var should = chai.should(); +var assert = chai.assert; + +var Key = bitcore.Key; + +//addUncompressed is a node-only interface feature +if (typeof process !== 'undefined' && process.versions) { + describe('#Key.node', function() { + describe('#addUncompressed', function() { + it('should exist', function() { + should.exist(Key.addUncompressed); + }); + + it('should add two uncompressed public keys', function() { + var key1 = Key.generateSync(); + key1.compressed = false; + var key2 = Key.generateSync(); + key2.compressed = false; + var pubkey1 = key1.public; + var pubkey2 = key2.public; + var pubkey = Key.addUncompressed(pubkey1, pubkey2); + pubkey.length.should.equal(65); + }); + + it('a + b should equal b + a', function() { + var key1 = Key.generateSync(); + key1.compressed = false; + var key2 = Key.generateSync(); + key2.compressed = false; + var pubkey1 = key1.public; + var pubkey2 = key2.public; + var r1 = Key.addUncompressed(pubkey1, pubkey2); + var r2 = Key.addUncompressed(pubkey2, pubkey1); + r1.toString('hex').should.equal(r2.toString('hex')); + }); + + it('should be able to add these two public keys without error', function() { + var key1 = new Key(); + key1.private = coinUtil.sha256("first " + 3); + key1.compressed = false; + key1.regenerateSync(); + var key2 = new Key(); + key2.private = coinUtil.sha256("second " + 3); + key2.compressed = false; + key2.regenerateSync(); + var pubkey1 = key1.public; + var pubkey2 = key2.public; + var pubkey = Key.addUncompressed(pubkey1, pubkey2); + pubkey.length.should.equal(65); + var key = new Key(); + key.public = pubkey; + assert(key.public !== null); + }); + + }); + + describe('node only Key functionality', function() { + it('should not fail when called as Key() without "new"', function() { + var key = Key(); + should.exist(key); + }); + it('should not fail when called as Key() without "new" with some args', function() { + var key = Key(1, 2, 3, 4, 5); + should.exist(key); + }); + it('should have correct properties when called with Key() without "new"', function() { + var key = Key(); + key.compressed.should.equal(true); + should.not.exist(key.public); + should.not.exist(key.private); + should.exist(key); + }); + + }); + }); +} From f82fa5007ab87842bded55ca6779727c9422f0d5 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Tue, 22 Apr 2014 19:36:18 -0300 Subject: [PATCH 4/4] move *.browser and *.node to browser/* and node/* ...this should leave the lib folder a little bit less cluttered. --- lib/Key.js | 4 ++-- lib/Point.js | 4 ++-- lib/{Key.browser.js => browser/Key.js} | 2 +- lib/{Point.browser.js => browser/Point.js} | 10 +++++----- lib/{Key.node.js => node/Key.js} | 0 lib/{Point.node.js => node/Point.js} | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) rename lib/{Key.browser.js => browser/Key.js} (97%) rename lib/{Point.browser.js => browser/Point.js} (87%) rename lib/{Key.node.js => node/Key.js} (100%) rename lib/{Point.node.js => node/Point.js} (96%) diff --git a/lib/Key.js b/lib/Key.js index 437c856..f2c655f 100644 --- a/lib/Key.js +++ b/lib/Key.js @@ -1,5 +1,5 @@ if (process.versions) { - module.exports = require('./Key.node'); + module.exports = require('./node/Key'); return; } -module.exports = require('./Key.browser'); +module.exports = require('./browser/Key'); diff --git a/lib/Point.js b/lib/Point.js index fc611ec..0fb01ac 100644 --- a/lib/Point.js +++ b/lib/Point.js @@ -1,5 +1,5 @@ if (process.versions) { - module.exports = require('./Point.node'); + module.exports = require('./node/Point'); return; } -module.exports = require('./Point.browser'); +module.exports = require('./browser/Point'); diff --git a/lib/Key.browser.js b/lib/browser/Key.js similarity index 97% rename from lib/Key.browser.js rename to lib/browser/Key.js index b172e64..796819d 100644 --- a/lib/Key.browser.js +++ b/lib/browser/Key.js @@ -1,4 +1,4 @@ -var ECKey = require('../browser/vendor-bundle.js').ECKey; +var ECKey = require('../../browser/vendor-bundle.js').ECKey; var buffertools = require('buffertools'); var Key = function() { diff --git a/lib/Point.browser.js b/lib/browser/Point.js similarity index 87% rename from lib/Point.browser.js rename to lib/browser/Point.js index dacf965..b9f4c36 100644 --- a/lib/Point.browser.js +++ b/lib/browser/Point.js @@ -4,11 +4,11 @@ var imports = require('soop').imports(); var Key = imports.Key || require('./Key'); var bignum = imports.bignum || require('bignum'); var assert = require('assert'); -var ECKey = require('../browser/vendor-bundle.js').ECKey; -var ECPointFp = require('../browser/vendor-bundle.js').ECPointFp; -var ECFieldElementFp = require('../browser/vendor-bundle.js').ECFieldElementFp; -var getSECCurveByName = require('../browser/vendor-bundle.js').getSECCurveByName; -var BigInteger = require('../browser/vendor-bundle.js').BigInteger; +var ECKey = require('../../browser/vendor-bundle.js').ECKey; +var ECPointFp = require('../../browser/vendor-bundle.js').ECPointFp; +var ECFieldElementFp = require('../../browser/vendor-bundle.js').ECFieldElementFp; +var getSECCurveByName = require('../../browser/vendor-bundle.js').getSECCurveByName; +var BigInteger = require('../../browser/vendor-bundle.js').BigInteger; var should = require('chai').should(); //a point on the secp256k1 curve diff --git a/lib/Key.node.js b/lib/node/Key.js similarity index 100% rename from lib/Key.node.js rename to lib/node/Key.js diff --git a/lib/Point.node.js b/lib/node/Point.js similarity index 96% rename from lib/Point.node.js rename to lib/node/Point.js index a3d2f45..38a6466 100644 --- a/lib/Point.node.js +++ b/lib/node/Point.js @@ -1,7 +1,7 @@ "use strict"; var imports = require('soop').imports(); -var Key = imports.Key || require('./Key'); +var Key = imports.Key || require('../Key'); var bignum = imports.bignum || require('bignum'); var assert = require('assert');