From 3de6acc1762a4c8520aa02c8c85add3e7e491388 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Sat, 3 Jan 2015 13:20:51 -0500 Subject: [PATCH 1/3] Add tests that reveals incorrect public key calculation --- test/publickey.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/publickey.js b/test/publickey.js index de4011d..2adc78c 100644 --- a/test/publickey.js +++ b/test/publickey.js @@ -44,6 +44,7 @@ describe('PublicKey', function() { }); describe('instantiation', function() { + it('from a private key', function() { var privhex = '906977a061af29276e40bf377042ffbde414e496ae2260bbf1fa9d085637bfff'; var pubhex = '02a1633cafcc01ebfb6d78e39f687a1f0995c62fc95f51ead10a02ee0be551b5dc'; @@ -52,6 +53,18 @@ describe('PublicKey', function() { pk.toString().should.equal(pubhex); }); + it('from a known private key', function() { + var privwif = 'KzsjKq2FVqVuQv2ueHVFuB65A9uEZ6S1L6F8NuokCrE3V3kE3Ack'; + var pubhex = '03d6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01'; + var pubxhex = 'd6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01'; + var pubyhex = 'e05fb262e64b108991a29979809fcef9d3e70cafceb3248c922c17d83d66bc9d'; + var privkey = new PrivateKey(privwif); + var pubkey = privkey.toPublicKey(); + pubkey.point.x.toString('hex').should.equal(pubxhex); + pubkey.point.y.toString('hex').should.equal(pubyhex); + pubkey.toString().should.equal(pubhex); + }); + it('from a compressed public key', function() { var publicKeyHex = '031ff0fe0f7b15ffaa85ff9f4744d539139c252a49710fb053bb9f2b933173ff9a'; var publicKey = new PublicKey(publicKeyHex); From bc4e62ecd4f1aa8e3f72afc3403ae27c9e151bf3 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Sat, 3 Jan 2015 14:03:00 -0500 Subject: [PATCH 2/3] Fixed public key calculation by returning the elliptic ec.curve.g --- lib/crypto/point.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/crypto/point.js b/lib/crypto/point.js index f635b3e..85f2431 100644 --- a/lib/crypto/point.js +++ b/lib/crypto/point.js @@ -2,9 +2,8 @@ var BN = require('./bn'); var bufferUtil = require('../util/buffer'); -var ec = require('elliptic').curves.secp256k1; -var ecPoint = ec.curve.point.bind(ec.curve); -var ecPointFromX = ec.curve.pointFromX.bind(ec.curve); +var EC = require('elliptic').ec; +var ec = new EC('secp256k1'); /** * @@ -19,7 +18,7 @@ var ecPointFromX = ec.curve.pointFromX.bind(ec.curve); * @constructor */ var Point = function Point(x, y, isRed) { - var point = ecPoint(x, y, isRed); + var point = ec.curve.point(x, y, isRed); point.validate(); return point; }; @@ -36,7 +35,7 @@ Point.prototype = Object.getPrototypeOf(ec.curve.point()); * @returns {Point} An instance of Point */ Point.fromX = function fromX(odd, x){ - var point = ecPointFromX(odd, x); + var point = ec.curve.pointFromX(odd, x); point.validate(); return point; }; @@ -49,7 +48,7 @@ Point.fromX = function fromX(odd, x){ * @returns {Point} An instance of the base point. */ Point.getG = function getG() { - return Point(ec.curve.g.getX(), ec.curve.g.getY()); + return ec.curve.g; }; /** @@ -106,7 +105,7 @@ Point.prototype.validate = function validate() { throw new Error('Invalid x,y value for curve, cannot equal 0.'); } - var p2 = ecPointFromX(this.getY().isOdd(), this.getX()); + var p2 = ec.curve.pointFromX(this.getY().isOdd(), this.getX()); if (p2.y.cmp(this.y) !== 0) { throw new Error('Invalid y value for curve.'); From d2a2be7a938fa470e9330efbdfcbe32270256700 Mon Sep 17 00:00:00 2001 From: Braydon Fuller Date: Sun, 4 Jan 2015 09:19:08 -0500 Subject: [PATCH 3/3] Upgraded bn.js to fix public key calculation problem, restored crypto/point.js, and added additional tests. --- lib/crypto/point.js | 13 +++++++------ npm-shrinkwrap.json | 12 ++++++------ package.json | 2 +- test/publickey.js | 37 +++++++++++++++++++++++++++---------- 4 files changed, 41 insertions(+), 23 deletions(-) diff --git a/lib/crypto/point.js b/lib/crypto/point.js index 85f2431..f635b3e 100644 --- a/lib/crypto/point.js +++ b/lib/crypto/point.js @@ -2,8 +2,9 @@ var BN = require('./bn'); var bufferUtil = require('../util/buffer'); -var EC = require('elliptic').ec; -var ec = new EC('secp256k1'); +var ec = require('elliptic').curves.secp256k1; +var ecPoint = ec.curve.point.bind(ec.curve); +var ecPointFromX = ec.curve.pointFromX.bind(ec.curve); /** * @@ -18,7 +19,7 @@ var ec = new EC('secp256k1'); * @constructor */ var Point = function Point(x, y, isRed) { - var point = ec.curve.point(x, y, isRed); + var point = ecPoint(x, y, isRed); point.validate(); return point; }; @@ -35,7 +36,7 @@ Point.prototype = Object.getPrototypeOf(ec.curve.point()); * @returns {Point} An instance of Point */ Point.fromX = function fromX(odd, x){ - var point = ec.curve.pointFromX(odd, x); + var point = ecPointFromX(odd, x); point.validate(); return point; }; @@ -48,7 +49,7 @@ Point.fromX = function fromX(odd, x){ * @returns {Point} An instance of the base point. */ Point.getG = function getG() { - return ec.curve.g; + return Point(ec.curve.g.getX(), ec.curve.g.getY()); }; /** @@ -105,7 +106,7 @@ Point.prototype.validate = function validate() { throw new Error('Invalid x,y value for curve, cannot equal 0.'); } - var p2 = ec.curve.pointFromX(this.getY().isOdd(), this.getX()); + var p2 = ecPointFromX(this.getY().isOdd(), this.getX()); if (p2.y.cmp(this.y) !== 0) { throw new Error('Invalid y value for curve.'); diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 02adf12..becad21 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -13,9 +13,9 @@ "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-0.4.1.tgz" }, "bn.js": { - "version": "0.16.0", - "from": "bn.js@0.16.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.0.tgz" + "version": "0.16.1", + "from": "bn.js@0.16.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.1.tgz" }, "browser-request": { "version": "0.3.3", @@ -43,9 +43,9 @@ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-0.16.0.tgz", "dependencies": { "bn.js": { - "version": "0.16.0", - "from": "bn.js@0.16.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.0.tgz" + "version": "0.16.1", + "from": "bn.js@0.16.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-0.16.1.tgz" }, "brorand": { "version": "1.0.1", diff --git a/package.json b/package.json index d94b9e8..59cd473 100644 --- a/package.json +++ b/package.json @@ -74,7 +74,7 @@ }, "dependencies": { "asn1.js": "=0.4.1", - "bn.js": "=0.16.0", + "bn.js": "=0.16.1", "browser-request": "^0.3.3", "bs58": "=2.0.0", "bufferput": "^0.1.2", diff --git a/test/publickey.js b/test/publickey.js index 2adc78c..dce9707 100644 --- a/test/publickey.js +++ b/test/publickey.js @@ -53,16 +53,33 @@ describe('PublicKey', function() { pk.toString().should.equal(pubhex); }); - it('from a known private key', function() { - var privwif = 'KzsjKq2FVqVuQv2ueHVFuB65A9uEZ6S1L6F8NuokCrE3V3kE3Ack'; - var pubhex = '03d6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01'; - var pubxhex = 'd6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01'; - var pubyhex = 'e05fb262e64b108991a29979809fcef9d3e70cafceb3248c922c17d83d66bc9d'; - var privkey = new PrivateKey(privwif); - var pubkey = privkey.toPublicKey(); - pubkey.point.x.toString('hex').should.equal(pubxhex); - pubkey.point.y.toString('hex').should.equal(pubyhex); - pubkey.toString().should.equal(pubhex); + it('problematic secp256k1 public keys', function() { + + var knownKeys = [ + { + wif: 'KzsjKq2FVqVuQv2ueHVFuB65A9uEZ6S1L6F8NuokCrE3V3kE3Ack', + priv: '6d1229a6b24c2e775c062870ad26bc261051e0198c67203167273c7c62538846', + pub: '03d6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01', + pubx: 'd6106302d2698d6a41e9c9a114269e7be7c6a0081317de444bb2980bf9265a01', + puby: 'e05fb262e64b108991a29979809fcef9d3e70cafceb3248c922c17d83d66bc9d' + }, + { + wif: 'L5MgSwNB2R76xBGorofRSTuQFd1bm3hQMFVf3u2CneFom8u1Yt7G', + priv: 'f2cc9d2b008927db94b89e04e2f6e70c180e547b3e5e564b06b8215d1c264b53', + pub: '03e275faa35bd1e88f5df6e8f9f6edb93bdf1d65f4915efc79fd7a726ec0c21700', + pubx: 'e275faa35bd1e88f5df6e8f9f6edb93bdf1d65f4915efc79fd7a726ec0c21700', + puby: '367216cb35b086e6686d69dddd822a8f4d52eb82ac5d9de18fdcd9bf44fa7df7' + } + ]; + + for(var i = 0; i < knownKeys.length; i++) { + var privkey = new PrivateKey(knownKeys[i].wif); + var pubkey = privkey.toPublicKey(); + pubkey.toString().should.equal(knownKeys[i].pub); + pubkey.point.x.toString('hex').should.equal(knownKeys[i].pubx); + pubkey.point.y.toString('hex').should.equal(knownKeys[i].puby); + } + }); it('from a compressed public key', function() {