From bf109f32a92e32a3ad55993e37facc486a32a818 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 16 May 2014 13:42:37 +1000 Subject: [PATCH 1/2] ECPubKey: improve tests and extract test data to fixtures The use of fixtures allows for more behavioural driven tests and simpler addition of more test cases in future. However, as ECPubKey is just a wrapper around other strenuously tested modules, the test data is currently limited to testing a subset of the total wrapper. This should probably be done better by using mocked out modules instead. --- test/ecpubkey.js | 155 ++++++++++++++++++++------------------ test/fixtures/ecpubkey.js | 19 +++++ 2 files changed, 101 insertions(+), 73 deletions(-) create mode 100644 test/fixtures/ecpubkey.js diff --git a/test/ecpubkey.js b/test/ecpubkey.js index faf338d..c7aefd8 100644 --- a/test/ecpubkey.js +++ b/test/ecpubkey.js @@ -1,95 +1,104 @@ var assert = require('assert') +var crypto = require('../src/crypto') +var sec = require('../src/sec') +var ecparams = sec('secp256k1') +var BigInteger = require('bigi') +var ECPointFp = require('../src/ec').ECPointFp var ECPubKey = require('../src/ecpubkey') +var fixtures = require('./fixtures/ecpubkey') + describe('ECPubKey', function() { - describe('toBuffer/toHex', function() { - var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' - var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' + var Q + + beforeEach(function() { + var curve = ecparams.getCurve() + + Q = new ECPointFp( + curve, + curve.fromBigInteger(new BigInteger(fixtures.Q.x)), + curve.fromBigInteger(new BigInteger(fixtures.Q.y)) + ) + }) - it('using toHex should support compression', function() { - var pub = ECPubKey.fromHex(hcpub) + describe('constructor', function() { + it('defaults to compressed', function() { + var pubKey = new ECPubKey(Q) - assert.equal(pub.toHex(), hcpub) - assert.equal(pub.compressed, true) + assert.equal(pubKey.compressed, true) }) - it('using toHex should support uncompressed', function() { - var pub = ECPubKey.fromHex(hpub) + it('supports the uncompressed flag', function() { + var pubKey = new ECPubKey(Q, false) - assert.equal(pub.toHex(), hpub) - assert.equal(pub.compressed, false) + assert.equal(pubKey.compressed, false) + }) + }) + + describe('fromHex/toHex', function() { + it('supports compressed points', function() { + var pubKey = ECPubKey.fromHex(fixtures.compressed.hex) + + assert(pubKey.Q.equals(Q)) + assert.equal(pubKey.toHex(), fixtures.compressed.hex) + assert.equal(pubKey.compressed, true) + }) + + it('supports uncompressed points', function() { + var pubKey = ECPubKey.fromHex(fixtures.uncompressed.hex) + + assert(pubKey.Q.equals(Q)) + assert.equal(pubKey.toHex(), fixtures.uncompressed.hex) + assert.equal(pubKey.compressed, false) }) }) describe('getAddress', function() { - var privkeys = [ - 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458', - '1111111111111111111111111111111111111111111111111111111111111111', - '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' - ] - - // compressed pubkeys - var cpubkeys = [ - '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992', - '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa', - '0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352' - ] - - var pubkeys = cpubkeys.map(function(x) { - var pk = ECPubKey.fromHex(x) - pk.compressed = false - return pk.toHex() + it('calculates the expected hash (compressed)', function() { + var pubKey = new ECPubKey(Q, true) + var address = pubKey.getAddress() + + assert.equal(address.hash.toString('hex'), fixtures.compressed.hash160) }) - it('bitcoin', function() { - var addresses = [ - '19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', - '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', - '16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' - ] - var compressedAddresses = [ - '1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', - '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', - '1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', - ] - - for (var i = 0; i < addresses.length; ++i) { - var pub = ECPubKey.fromHex(pubkeys[i]) - var cpub = ECPubKey.fromHex(cpubkeys[i]) - cpub.compressed = true - - var addr = addresses[i] - var caddr = compressedAddresses[i] - - assert.equal(pub.getAddress().toString(), addr) - assert.equal(cpub.getAddress().toString(), caddr) - } + it('calculates the expected hash (uncompressed)', function() { + var pubKey = new ECPubKey(Q, false) + var address = pubKey.getAddress() + + assert.equal(address.hash.toString('hex'), fixtures.uncompressed.hash160) + }) + + it('supports alternative networks', function() { + var pubKey = new ECPubKey(Q) + var address = pubKey.getAddress(0x09) + + assert.equal(address.version, 0x09) + assert.equal(address.hash.toString('hex'), fixtures.compressed.hash160) }) + }) + + describe('verify', function() { + var pubKey, signature + beforeEach(function() { + pubKey = new ECPubKey(Q) - it('testnet', function() { - var addresses = [ - '19SgmoUj4xowEjwtXvNAtYTAgbvR9iBCui', - '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a', - '16UwLL9Risc3QfPqBUvKofHmBQ7wMtjvM' - ] - var compressedAddresses = [ - '1AA4sjKW2aUmbtN3MtegdvhYtDBbDEke1q', - '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9', - '1PMycacnJaSqwwJqjawXBErnLsZ7RkXUAs', - ] - - for (var i = 0; i < addresses.length; ++i) { - var pub = ECPubKey.fromHex(pubkeys[i]) - var cpub = ECPubKey.fromHex(cpubkeys[i]) - cpub.compressed = true - - var addr = addresses[i] - var caddr = compressedAddresses[i] - - assert.equal(pub.getAddress().toString(), addr) - assert.equal(cpub.getAddress().toString(), caddr) + signature = { + r: new BigInteger(fixtures.signature.r), + s: new BigInteger(fixtures.signature.s) } }) + + it('verifies a valid signature', function() { + var hash = crypto.sha256(fixtures.message) + + assert.ok(pubKey.verify(hash, signature)) + }) + + it('doesn\'t verify the wrong signature', function() { + var hash = crypto.sha256('mushrooms') + + assert.ok(!pubKey.verify(hash, signature)) + }) }) }) diff --git a/test/fixtures/ecpubkey.js b/test/fixtures/ecpubkey.js new file mode 100644 index 0000000..77b9b42 --- /dev/null +++ b/test/fixtures/ecpubkey.js @@ -0,0 +1,19 @@ +module.exports = { + "Q": { + "x": "55066263022277343669578718895168534326250603453777594175500187360389116729240", + "y": "32670510020758816978083085130507043184471273380659243275938904335757337482424" + }, + "compressed": { + "hex": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "hash160": "751e76e8199196d454941c45d1b3a323f1433bd6" + }, + "uncompressed": { + "hex": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", + "hash160": "91b24bf9f5288532960ac687abb035127b1d28a5" + }, + "message": "vires in numeris", + "signature": { + "r": "68972263025625296948424563184904289678530916807200550828762374724416876919710", + "s": "43478152510424186005054433052302509227777805602212468112169549534899266476898" + } +} \ No newline at end of file From 10fe4474d1b04bdc79094a08f3baaac50a20f513 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Fri, 16 May 2014 13:46:06 +1000 Subject: [PATCH 2/2] ECKey: remove *Buffer/*Hex functions An ECKey is a composition of a private key (D), a public key (Q) and its compression flag. These functions gave the impression of serialization of this composition, when really they only serialized `D`. They have therefore been removed in favour of always using a sane serialization format (WIF) that matches the needed behaviour. If a user needs the previous functionality, simply use `privKey.D.*` instead of `privKey.*`, as BigInteger supports `*Buffer/*Hex` functions as expected. --- src/eckey.js | 43 +++++----------- src/hdwallet.js | 11 ++-- test/ecdsa.js | 10 ++-- test/eckey.js | 114 ++++++++++++++++++++++------------------- test/fixtures/ecdsa.js | 16 +++--- test/fixtures/eckey.js | 98 +++++++++++++++++++++++++++++++++++ test/hdwallet.js | 16 +----- 7 files changed, 197 insertions(+), 111 deletions(-) create mode 100644 test/fixtures/eckey.js diff --git a/src/eckey.js b/src/eckey.js index 66982e3..e59e140 100644 --- a/src/eckey.js +++ b/src/eckey.js @@ -21,29 +21,22 @@ function ECKey(D, compressed) { } // Static constructors -ECKey.fromBuffer = function(buffer, compressed) { - assert(Buffer.isBuffer(buffer), 'First argument must be a Buffer') - assert.strictEqual(buffer.length, 32, 'Invalid buffer length') - - var D = BigInteger.fromBuffer(buffer) - return new ECKey(D, compressed) -} - -ECKey.fromHex = function(hex, compressed) { - return ECKey.fromBuffer(new Buffer(hex, 'hex'), compressed) -} - ECKey.fromWIF = function(string) { var decode = base58check.decode(string) - var payload = decode.payload + var compressed = false + if (payload.length === 33) { assert.strictEqual(payload[32], 0x01, 'Invalid WIF string') - return ECKey.fromBuffer(payload.slice(0, 32), true) + payload = payload.slice(0, -1) + compressed = true } - return ECKey.fromBuffer(payload, false) + assert.equal(payload.length, 32, 'Invalid WIF payload length') + + var D = BigInteger.fromBuffer(payload.slice(0, 32)) + return new ECKey(D, compressed) } ECKey.makeRandom = function(compressed, rng) { @@ -56,24 +49,11 @@ ECKey.makeRandom = function(compressed, rng) { return new ECKey(D, compressed) } -// Operations -ECKey.prototype.sign = function(hash) { - return ecdsa.sign(hash, this.D) -} - // Export functions -ECKey.prototype.toBuffer = function() { - return this.D.toBuffer(32) -} - -ECKey.prototype.toHex = function() { - return this.toBuffer().toString('hex') -} - ECKey.prototype.toWIF = function(version) { version = version || networks.bitcoin.wif - var buffer = this.toBuffer() + var buffer = this.D.toBuffer(32) if (this.pub.compressed) { buffer = Buffer.concat([buffer, new Buffer([0x01])]) } @@ -81,4 +61,9 @@ ECKey.prototype.toWIF = function(version) { return base58check.encode(buffer, version) } +// Operations +ECKey.prototype.sign = function(hash) { + return ecdsa.sign(hash, this.D) +} + module.exports = ECKey diff --git a/src/hdwallet.js b/src/hdwallet.js index 8e8f747..cd0787d 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -26,7 +26,9 @@ function HDWallet(seed, networkString) { var IR = I.slice(32) // In case IL is 0 or >= n, the master key is invalid (handled by ECKey.fromBuffer) - this.priv = ECKey.fromBuffer(IL, true) + var pIL = BigInteger.fromBuffer(IL) + + this.priv = new ECKey(pIL, true) this.pub = this.priv.pub this.chaincode = IR @@ -103,7 +105,10 @@ HDWallet.fromBuffer = function(input) { // 33 bytes: the public key or private key data (0x02 + X or 0x03 + X for // public keys, 0x00 + k for private keys) if (type == 'priv') { - hd.priv = ECKey.fromBuffer(input.slice(46, 78), true) + assert.equal(input.readUInt8(45), 0, 'Invalid private key') + var D = BigInteger.fromBuffer(input.slice(46, 78)) + + hd.priv = new ECKey(D, true) hd.pub = hd.priv.pub } else { hd.pub = ECPubKey.fromBuffer(input.slice(45, 78), true) @@ -153,7 +158,7 @@ HDWallet.prototype.toBuffer = function(priv) { // 0x00 + k for private keys buffer.writeUInt8(0, 45) - this.priv.toBuffer().copy(buffer, 46) + this.priv.D.toBuffer(32).copy(buffer, 46) } else { // X9.62 encoding for public keys diff --git a/test/ecdsa.js b/test/ecdsa.js index 2e9a028..b4014a7 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -16,7 +16,7 @@ describe('ecdsa', function() { describe('deterministicGenerateK', function() { it('matches the test vectors', function() { fixtures.forEach(function(f) { - var priv = BigInteger.fromHex(f.privateKey) + var priv = BigInteger.fromHex(f.D) var h1 = crypto.sha256(f.message) var k = ecdsa.deterministicGenerateK(h1, priv) @@ -39,7 +39,8 @@ describe('ecdsa', function() { describe('sign', function() { it('matches the test vectors', function() { fixtures.forEach(function(f) { - var priv = ECKey.fromHex(f.privateKey) + var D = BigInteger.fromHex(f.D) + var priv = new ECKey(D) var hash = crypto.sha256(f.message) var sig = ecdsa.parseSig(priv.sign(hash)) @@ -49,7 +50,7 @@ describe('ecdsa', function() { }) it('should sign with low S value', function() { - var priv = ECKey.fromHex('ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458') + var priv = ECKey.makeRandom() var hash = crypto.sha256('Vires in numeris') var signature = priv.sign(hash) var psig = ecdsa.parseSig(signature) @@ -62,7 +63,8 @@ describe('ecdsa', function() { describe('verifyRaw', function() { it('matches the test vectors', function() { fixtures.forEach(function(f) { - var priv = ECKey.fromHex(f.privateKey) + var D = BigInteger.fromHex(f.D) + var priv = new ECKey(D) var r = BigInteger.fromHex(f.signature.slice(0, 64)) var s = BigInteger.fromHex(f.signature.slice(64)) diff --git a/test/eckey.js b/test/eckey.js index 2ef218b..9b4a696 100644 --- a/test/eckey.js +++ b/test/eckey.js @@ -1,81 +1,89 @@ var assert = require('assert') var crypto = require('../src/crypto') +var BigInteger = require('bigi') var ECKey = require('../src/eckey') -var ECPubKey = require('../src/ecpubkey') + +var fixtures = require('./fixtures/eckey') +var networks = require('../src/networks') describe('ECKey', function() { describe('constructor', function() { - it('parses hex', function() { - var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' - var pub = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b235' + - '22cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6' - var key = ECKey.fromHex(priv, false) - - assert.equal(key.pub.toHex(), pub) - assert.equal(key.pub.compressed, false) + it('defaults to compressed', function() { + var privKey = new ECKey(BigInteger.ONE) + + assert.equal(privKey.pub.compressed, true) }) - it('parses WIF', function() { - var priv = '5HwoXVkHoRM8sL2KmNRS217n1g8mPPBomrY7yehCuXC1115WWsh' - var pub = '044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0' + - 'f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1' - var addr = '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a' - var key = ECKey.fromWIF(priv) + it('supports the uncompressed flag', function() { + var privKey = new ECKey(BigInteger.ONE, false) - assert.equal(key.pub.compressed, false) - assert.equal(key.pub.toHex(), pub) - assert.equal(key.pub.getAddress().toString(), addr) + assert.equal(privKey.pub.compressed, false) }) - it('parses compressed WIF', function() { - var priv = 'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp' - var pub = '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa' - var addr = '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9' - var key = ECKey.fromWIF(priv) + it('calculates the matching pubKey', function() { + fixtures.valid.forEach(function(f) { + var privKey = new ECKey(new BigInteger(f.D)) - assert.equal(key.pub.compressed, true) - assert.equal(key.pub.toHex(), pub) - assert.equal(key.pub.getAddress().toString(), addr) + assert.equal(privKey.pub.Q.toString(), f.Q.toString()) + }) }) - it('alternative constructor syntax', function() { - var priv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' - var pub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199' + - '283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' - var key = ECKey.fromHex(priv, false) - - assert.equal(key.pub.toHex(), pub) - assert.equal(key.pub.compressed, false) - assert.equal(key.toHex(), priv) + fixtures.invalid.constructor.forEach(function(f) { + it('throws on ' + f.description, function() { + assert.throws(function() { + new ECKey(new BigInteger(f.D)) + }) + }) }) }) - describe('signing', function() { - var hpriv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' - var hcpub = '024b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea811992' - var hash = crypto.sha256('Vires in numeris') + describe('fromWIF', function() { + it('matches the test vectors', function() { + fixtures.valid.forEach(function(f) { + f.WIFs.forEach(function(wif) { + var privKey = ECKey.fromWIF(wif.string) - it('should verify against the private key', function() { - var priv = ECKey.fromHex(hpriv) - var signature = priv.sign(hash) - - assert(priv.pub.verify(hash, signature)) + assert.equal(privKey.D.toString(), f.D) + assert.equal(privKey.pub.compressed, wif.compressed) + }) + }) }) - it('should verify against the public key', function() { - var priv = ECKey.fromHex(hpriv) - var pub = ECPubKey.fromHex(hcpub, true) - var signature = priv.sign(hash) + fixtures.invalid.WIF.forEach(function(f) { + it('throws on ' + f.description, function() { + assert.throws(function() { + ECKey.fromWIF(f.string) + }) + }) + }) + }) - assert(pub.verify(hash, signature)) + describe('toWIF', function() { + it('matches the test vectors', function() { + fixtures.valid.forEach(function(f) { + f.WIFs.forEach(function(wif) { + var privKey = ECKey.fromWIF(wif.string) + var version = networks[wif.network].wif + var result = privKey.toWIF(version) + + assert.equal(result, wif.string) + }) + }) }) + }) + + describe('signing', function() { + var hash = crypto.sha256('Vires in numeris') + var priv = ECKey.makeRandom() + var signature = priv.sign(hash) - it('should not verify against the wrong private key', function() { - var priv1 = ECKey.fromHex(hpriv) - var priv2 = ECKey.fromHex('1111111111111111111111111111111111111111111111111111111111111111') + it('should verify against the public key', function() { + assert(priv.pub.verify(hash, signature)) + }) - var signature = priv1.sign(hash) + it('should not verify against the wrong public key', function() { + var priv2 = ECKey.makeRandom() assert(!priv2.pub.verify(hash, signature)) }) diff --git a/test/fixtures/ecdsa.js b/test/fixtures/ecdsa.js index 94e278a..631475e 100644 --- a/test/fixtures/ecdsa.js +++ b/test/fixtures/ecdsa.js @@ -1,49 +1,49 @@ // Test Vectors for RFC 6979 ECDSA, secp256k1, SHA-256 module.exports = [ { - "privateKey": "0000000000000000000000000000000000000000000000000000000000000001", + "D": "0000000000000000000000000000000000000000000000000000000000000001", "k": "8f8a276c19f4149656b280621e358cce24f5f52542772691ee69063b74f15d15", "message": "Satoshi Nakamoto", "signature": "934b1ea10a4b3c1757e2b0c017d0b6143ce3c9a7e6a4a49860d7a6ab210ee3d82442ce9d2b916064108014783e923ec36b49743e2ffa1c4496f01a512aafd9e5" }, { - "privateKey": "0000000000000000000000000000000000000000000000000000000000000001", + "D": "0000000000000000000000000000000000000000000000000000000000000001", "k": "38aa22d72376b4dbc472e06c3ba403ee0a394da63fc58d88686c611aba98d6b3", "message": "All those moments will be lost in time, like tears in rain. Time to die...", "signature": "8600dbd41e348fe5c9465ab92d23e3db8b98b873beecd930736488696438cb6b547fe64427496db33bf66019dacbf0039c04199abb0122918601db38a72cfc21" }, { - "privateKey": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364140", + "D": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "k": "33a19b60e25fb6f4435af53a3d42d493644827367e6453928554f43e49aa6f90", "message": "Satoshi Nakamoto", "signature": "fd567d121db66e382991534ada77a6bd3106f0a1098c231e47993447cd6af2d06b39cd0eb1bc8603e159ef5c20a5c8ad685a45b06ce9bebed3f153d10d93bed5" }, { - "privateKey": "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", + "D": "f8b8af8ce3c7cca5e300d33939540c10d45ce001b8f252bfbc57ba0342904181", "k": "525a82b70e67874398067543fd84c83d30c175fdc45fdeee082fe13b1d7cfdf1", "message": "Alan Turing", "signature": "7063ae83e7f62bbb171798131b4a0564b956930092b33b07b395615d9ec7e15c58dfcc1e00a35e1572f366ffe34ba0fc47db1e7189759b9fb233c5b05ab388ea" }, { - "privateKey": "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", + "D": "e91671c46231f833a6406ccbea0e3e392c76c167bac1cb013f6f1013980455c2", "k": "1f4b84c23a86a221d233f2521be018d9318639d5b8bbd6374a8a59232d16ad3d", "message": "There is a computer disease that anybody who works with computers knows about. It's a very serious disease and it interferes completely with the work. The trouble with computers is that you 'play' with them!", "signature": "b552edd27580141f3b2a5463048cb7cd3e047b97c9f98076c32dbdf85a68718b279fa72dd19bfae05577e06c7c0c1900c371fcd5893f7e1d56a37d30174671f6" }, { - "privateKey": "0000000000000000000000000000000000000000000000000000000000000001", + "D": "0000000000000000000000000000000000000000000000000000000000000001", "k": "ec633bd56a5774a0940cb97e27a9e4e51dc94af737596a0c5cbb3d30332d92a5", "message": "Everything should be made as simple as possible, but not simpler.", "signature": "33a69cd2065432a30f3d1ce4eb0d59b8ab58c74f27c41a7fdb5696ad4e6108c96f807982866f785d3f6418d24163ddae117b7db4d5fdf0071de069fa54342262" }, { - "privateKey": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "D": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "k": "9dc74cbfd383980fb4ae5d2680acddac9dac956dca65a28c80ac9c847c2374e4", "message": "Equations are more important to me, because politics is for the present, but an equation is something for eternity.", "signature": "54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5" }, { - "privateKey": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", + "D": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", "k": "fd27071f01648ebbdd3e1cfbae48facc9fa97edc43bbbc9a7fdc28eae13296f5", "message": "Not only is the Universe stranger than we think, it is stranger than we can think.", "signature": "ff466a9f1b7b273e2f4c3ffe032eb2e814121ed18ef84665d0f515360dab3dd06fc95f5132e5ecfdc8e5e6e616cc77151455d46ed48f5589b7db7771a332b283" diff --git a/test/fixtures/eckey.js b/test/fixtures/eckey.js new file mode 100644 index 0000000..1751ae8 --- /dev/null +++ b/test/fixtures/eckey.js @@ -0,0 +1,98 @@ +module.exports = { + "valid": [ + { + "D": "1", + "Q": "(55066263022277343669578718895168534326250603453777594175500187360389116729240,32670510020758816978083085130507043184471273380659243275938904335757337482424)", + "WIFs": [ + { + "network": "bitcoin", + "string": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", + "compressed": true + }, + { + "network": "bitcoin", + "string": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", + "compressed": false + } + ] + }, + { + "D": "19898843618908353587043383062236220484949425084007183071220218307100305431102", + "Q": "(83225686012142088543596389522774768397204444195709443235253141114409346958144,23739058578904784236915560265041168694780215705543362357495033621678991351768)", + "WIFs": [ + { + "network": "bitcoin", + "string": "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o", + "compressed": true + } + ] + }, + { + "D": "48968302285117906840285529799176770990048954789747953886390402978935544927851", + "Q": "(30095590000961171681152428142595206241714764354580127609094760797518133922356,93521207164355458151597931319591130635754976513751247168472016818884561919702)", + "WIFs": [ + { + "network": "bitcoin", + "string": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", + "compressed": true + }, + { + "network": "bitcoin", + "string": "5JdxzLtFPHNe7CAL8EBC6krdFv9pwPoRo4e3syMZEQT9srmK8hh", + "compressed": false + }, + { + "network": "testnet", + "string": "cRD9b1m3vQxmwmjSoJy7Mj56f4uNFXjcWMCzpQCEmHASS4edEwXv", + "compressed": true + }, + { + "network": "testnet", + "string": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj", + "compressed": false + } + ] + }, + { + "D": "115792089237316195423570985008687907852837564279074904382605163141518161494336", + "Q": "(55066263022277343669578718895168534326250603453777594175500187360389116729240,83121579216557378445487899878180864668798711284981320763518679672151497189239)", + "WIFs": [ + { + "network": "bitcoin", + "string": "L5oLkpV3aqBjhki6LmvChTCV6odsp4SXM6FfU2Gppt5kFLaHLuZ9", + "compressed": true + } + ] + } + ], + "invalid": { + "constructor": [ + { + "description": "Private key ZERO", + "D": "0" + }, + { + "description": "Private key equal to the curve order", + "D": "115792089237316195423570985008687907852837564279074904382605163141518161494337" + }, + { + "description": "Private key greater than the curve order", + "D": "115792089237316195423570985008687907853269984665640564039457584007913129639935" + } + ], + "WIF": [ + { + "description": "Invalid compression flag", + "string": "ju9rooVsmagsb4qmNyTysUSFB1GB6MdpD7eoGjUTPmZRAApJxRz" + }, + { + "description": "Payload too short", + "string": "7ZEtRQLhCsDQrd6ZKfmcESdXgas8ggZPN24ByEi5ey6VJW" + }, + { + "description": "Payload too long", + "string": "5qibUKwsnMo1qDiNp3prGaQkD2JfVJa8F8Na87H2CkMHvuVg6uKhw67Rh" + } + ] + } +} \ No newline at end of file diff --git a/test/hdwallet.js b/test/hdwallet.js index 1207f76..b0284f7 100644 --- a/test/hdwallet.js +++ b/test/hdwallet.js @@ -41,7 +41,7 @@ describe('HDWallet', function() { it('creates from binary seed', function() { var hd = new HDWallet(seed) - assert.equal(hd.priv.toHex(), expectedPrivateKey) + assert.equal(hd.priv.D.toHex(), expectedPrivateKey) assert(hd.pub) }) @@ -49,7 +49,7 @@ describe('HDWallet', function() { it('creates from hex seed', function() { var hd = HDWallet.fromSeedHex(seed.toString('hex')) - assert.equal(hd.priv.toHex(), expectedPrivateKey) + assert.equal(hd.priv.D.toHex(), expectedPrivateKey) assert(hd.pub) }) }) @@ -63,7 +63,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '3442193e1bb70916e914552172cd4e2dbc9df811') assert.equal(b2h(hd.getFingerprint()), '3442193e') assert.equal(hd.getAddress().toString(), '15mKKb2eos1hWa6tisdPwwDC1a5J1y9nma') - assert.equal(hd.priv.toHex(), 'e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35') assert.equal(hd.priv.toWIF(), 'L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW') assert.equal(hd.pub.toHex(), '0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2') assert.equal(b2h(hd.chaincode), '873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508') @@ -77,7 +76,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '5c1bd648ed23aa5fd50ba52b2457c11e9e80a6a7') assert.equal(b2h(hd.getFingerprint()), '5c1bd648') assert.equal(hd.getAddress().toString(), '19Q2WoS5hSS6T8GjhK8KZLMgmWaq4neXrh') - assert.equal(hd.priv.toHex().slice(0, 64), 'edb2e14f9ee77d26dd93b4ecede8d16ed408ce149b6cd80b0715a2d911a0afea') assert.equal(hd.priv.toWIF(), 'L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT') assert.equal(hd.pub.toHex(), '035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56') assert.equal(b2h(hd.chaincode), '47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141') @@ -91,7 +89,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'bef5a2f9a56a94aab12459f72ad9cf8cf19c7bbe') assert.equal(b2h(hd.getFingerprint()), 'bef5a2f9') assert.equal(hd.getAddress().toString(), '1JQheacLPdM5ySCkrZkV66G2ApAXe1mqLj') - assert.equal(hd.priv.toHex().slice(0, 64), '3c6cb8d0f6a264c91ea8b5030fadaa8e538b020f0a387421a12de9319dc93368') assert.equal(hd.priv.toWIF(), 'KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM') assert.equal(hd.pub.toHex(), '03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c') assert.equal(b2h(hd.chaincode), '2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19') @@ -105,7 +102,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'ee7ab90cde56a8c0e2bb086ac49748b8db9dce72') assert.equal(b2h(hd.getFingerprint()), 'ee7ab90c') assert.equal(hd.getAddress().toString(), '1NjxqbA9aZWnh17q1UW3rB4EPu79wDXj7x') - assert.equal(hd.priv.toHex().slice(0, 64), 'cbce0d719ecf7431d88e6a89fa1483e02e35092af60c042b1df2ff59fa424dca') assert.equal(hd.priv.toWIF(), 'L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU') assert.equal(hd.pub.toHex(), '0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2') assert.equal(b2h(hd.chaincode), '04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f') @@ -119,7 +115,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'd880d7d893848509a62d8fb74e32148dac68412f') assert.equal(b2h(hd.getFingerprint()), 'd880d7d8') assert.equal(hd.getAddress().toString(), '1LjmJcdPnDHhNTUgrWyhLGnRDKxQjoxAgt') - assert.equal(hd.priv.toHex().slice(0, 64), '0f479245fb19a38a1954c5c7c0ebab2f9bdfd96a17563ef28a6a4b1a2a764ef4') assert.equal(hd.priv.toWIF(), 'KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR') assert.equal(hd.pub.toHex(), '02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29') assert.equal(b2h(hd.chaincode), 'cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd') @@ -133,7 +128,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'd69aa102255fed74378278c7812701ea641fdf32') assert.equal(b2h(hd.getFingerprint()), 'd69aa102') assert.equal(hd.getAddress().toString(), '1LZiqrop2HGR4qrH1ULZPyBpU6AUP49Uam') - assert.equal(hd.priv.toHex().slice(0, 64), '471b76e389e528d6de6d816857e012c5455051cad6660850e58372a6c3e6e7c8') assert.equal(hd.priv.toWIF(), 'Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs') assert.equal(hd.pub.toHex(), '022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011') assert.equal(b2h(hd.chaincode), 'c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e') @@ -150,7 +144,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'bd16bee53961a47d6ad888e29545434a89bdfe95') assert.equal(b2h(hd.getFingerprint()), 'bd16bee5') assert.equal(hd.getAddress().toString(), '1JEoxevbLLG8cVqeoGKQiAwoWbNYSUyYjg') - assert.equal(hd.priv.toHex().slice(0, 64), '4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e') assert.equal(hd.priv.toWIF(), 'KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy') assert.equal(hd.pub.toHex(), '03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7') assert.equal(b2h(hd.chaincode), '60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689') @@ -164,7 +157,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '5a61ff8eb7aaca3010db97ebda76121610b78096') assert.equal(b2h(hd.getFingerprint()), '5a61ff8e') assert.equal(hd.getAddress().toString(), '19EuDJdgfRkwCmRzbzVBHZWQG9QNWhftbZ') - assert.equal(hd.priv.toHex().slice(0, 64), 'abe74a98f6c7eabee0428f53798f0ab8aa1bd37873999041703c742f15ac7e1e') assert.equal(hd.priv.toWIF(), 'L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj') assert.equal(hd.pub.toHex(), '02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea') assert.equal(b2h(hd.chaincode), 'f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c') @@ -178,7 +170,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), 'd8ab493736da02f11ed682f88339e720fb0379d1') assert.equal(b2h(hd.getFingerprint()), 'd8ab4937') assert.equal(hd.getAddress().toString(), '1Lke9bXGhn5VPrBuXgN12uGUphrttUErmk') - assert.equal(hd.priv.toHex().slice(0, 64), '877c779ad9687164e9c2f4f0f4ff0340814392330693ce95a58fe18fd52e6e93') assert.equal(hd.priv.toWIF(), 'L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr') assert.equal(hd.pub.toHex(), '03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b') assert.equal(b2h(hd.chaincode), 'be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9') @@ -192,7 +183,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '78412e3a2296a40de124307b6485bd19833e2e34') assert.equal(b2h(hd.getFingerprint()), '78412e3a') assert.equal(hd.getAddress().toString(), '1BxrAr2pHpeBheusmd6fHDP2tSLAUa3qsW') - assert.equal(hd.priv.toHex().slice(0, 64), '704addf544a06e5ee4bea37098463c23613da32020d604506da8c0518e1da4b7') assert.equal(hd.priv.toWIF(), 'KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2') assert.equal(hd.pub.toHex(), '03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9') assert.equal(b2h(hd.chaincode), 'f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb') @@ -206,7 +196,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '31a507b815593dfc51ffc7245ae7e5aee304246e') assert.equal(b2h(hd.getFingerprint()), '31a507b8') assert.equal(hd.getAddress().toString(), '15XVotxCAV7sRx1PSCkQNsGw3W9jT9A94R') - assert.equal(hd.priv.toHex().slice(0, 64), 'f1c7c871a54a804afe328b4c83a1c33b8e5ff48f5087273f04efa83b247d6a2d') assert.equal(hd.priv.toWIF(), 'L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF') assert.equal(hd.pub.toHex(), '02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0') assert.equal(b2h(hd.chaincode), '637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29') @@ -220,7 +209,6 @@ describe('HDWallet', function() { assert.equal(b2h(hd.getIdentifier()), '26132fdbe7bf89cbc64cf8dafa3f9f88b8666220') assert.equal(b2h(hd.getFingerprint()), '26132fdb') assert.equal(hd.getAddress().toString(), '14UKfRV9ZPUp6ZC9PLhqbRtxdihW9em3xt') - assert.equal(hd.priv.toHex().slice(0, 64), 'bb7d39bdb83ecf58f2fd82b6d918341cbef428661ef01ab97c28a4842125ac23') assert.equal(hd.priv.toWIF(), 'L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK') assert.equal(hd.pub.toHex(), '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c') assert.equal(b2h(hd.chaincode), '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271')