From efacd387beedf1e415f51b7319435466bf4304c7 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 20 Aug 2015 20:16:57 +1000 Subject: [PATCH] ECPair: extract WIF to 3rd party module --- package.json | 3 +- src/ecpair.js | 64 +++++++++++---------------------------- test/bitcoin.core.js | 2 +- test/ecpair.js | 4 +-- test/fixtures/ecpair.json | 14 ++++++--- 5 files changed, 31 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index d74bd03..e863c89 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "create-hmac": "^1.1.3", "ecurve": "^1.0.0", "randombytes": "^2.0.1", - "typeforce": "^1.3.0" + "typeforce": "^1.3.0", + "wif": "^1.1.0" }, "devDependencies": { "async": "^0.9.0", diff --git a/src/ecpair.js b/src/ecpair.js index 4599039..13f2b05 100644 --- a/src/ecpair.js +++ b/src/ecpair.js @@ -5,6 +5,7 @@ var ecurve = require('ecurve') var randomBytes = require('randombytes') var typeforce = require('typeforce') var types = require('./types') +var wif = require('wif') var NETWORKS = require('./networks') var BigInteger = require('bigi') @@ -57,46 +58,25 @@ ECPair.fromPublicKeyBuffer = function (buffer, network) { }) } -ECPair.fromWIF = function (string, networks) { - var payload = bs58check.decode(string) - var version = payload.readUInt8(0) - var compressed +ECPair.fromWIF = function (string, network) { + network = network || NETWORKS.bitcoin + var buffer = bs58check.decode(string) - if (payload.length === 34) { - if (payload[33] !== 0x01) throw new Error('Invalid compression flag') + if (types.Array(network)) { + var version = buffer[0] - // truncate the version/compression bytes - payload = payload.slice(1, -1) - compressed = true - - // no compression flag - } else { - if (payload.length !== 33) throw new Error('Invalid WIF payload length') - - // Truncate the version byte - payload = payload.slice(1) - compressed = false - } - - var network - - // list of networks? - if (Array.isArray(networks)) { - network = networks.filter(function (network) { + network = network.filter(function (network) { return version === network.wif }).pop() || {} - // otherwise, assume a network object (or default to bitcoin) - } else { - network = networks || NETWORKS.bitcoin + if (version !== network.wif) throw new Error('Invalid network version') } - if (version !== network.wif) throw new Error('Invalid network') - - var d = BigInteger.fromBuffer(payload) + var decoded = wif.decodeRaw(network.wif, buffer) + var d = BigInteger.fromBuffer(decoded.d) return new ECPair(d, null, { - compressed: compressed, + compressed: decoded.compressed, network: network }) } @@ -114,22 +94,6 @@ ECPair.makeRandom = function (options) { return new ECPair(d, null, options) } -ECPair.prototype.toWIF = function () { - if (!this.d) throw new Error('Missing private key') - - var bufferLen = this.compressed ? 34 : 33 - var buffer = new Buffer(bufferLen) - - buffer.writeUInt8(this.network.wif, 0) - this.d.toBuffer(32).copy(buffer, 1) - - if (this.compressed) { - buffer.writeUInt8(0x01, 33) - } - - return bs58check.encode(buffer) -} - ECPair.prototype.getAddress = function () { var pubKey = this.getPublicKeyBuffer() var pubKeyHash = bcrypto.hash160(pubKey) @@ -151,6 +115,12 @@ ECPair.prototype.sign = function (hash) { return ecdsa.sign(secp256k1, hash, this.d) } +ECPair.prototype.toWIF = function () { + if (!this.d) throw new Error('Missing private key') + + return wif.encode(this.network.wif, this.d.toBuffer(32), this.compressed) +} + ECPair.prototype.verify = function (hash, signature) { return ecdsa.verify(secp256k1, hash, signature, this.Q) } diff --git a/test/bitcoin.core.js b/test/bitcoin.core.js index cdc3b8e..e30d366 100644 --- a/test/bitcoin.core.js +++ b/test/bitcoin.core.js @@ -117,7 +117,7 @@ describe('Bitcoin-core', function () { it('throws on ' + string, function () { assert.throws(function () { bitcoin.ECPair.fromWIF(string, allowedNetworks) - }, /(Invalid|Unknown) (checksum|compression flag|network|WIF payload)/) + }, /(Invalid|Unknown) (checksum|compression flag|network version|WIF length)/) }) }) }) diff --git a/test/ecpair.js b/test/ecpair.js index b64f1d2..db378a9 100644 --- a/test/ecpair.js +++ b/test/ecpair.js @@ -129,9 +129,9 @@ describe('ECPair', function () { }) fixtures.invalid.fromWIF.forEach(function (f) { - it('throws on ' + f.string, function () { + it('throws on ' + f.WIF, function () { assert.throws(function () { - ECPair.fromWIF(f.string) + ECPair.fromWIF(f.WIF) }, new RegExp(f.exception)) }) }) diff --git a/test/fixtures/ecpair.json b/test/fixtures/ecpair.json index bc117e6..662f354 100644 --- a/test/fixtures/ecpair.json +++ b/test/fixtures/ecpair.json @@ -85,17 +85,21 @@ } ], "fromWIF": [ + { + "exception": "Invalid network version", + "WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj" + }, { "exception": "Invalid compression flag", - "string": "ju9rooVsmagsb4qmNyTysUSFB1GB6MdpD7eoGjUTPmZRAApJxRz" + "WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sfZr2ym" }, { - "exception": "Invalid WIF payload length", - "string": "7ZEtRQLhCsDQrd6ZKfmcESdXgas8ggZPN24ByEi5ey6VJW" + "exception": "Invalid WIF length", + "WIF": "3tq8Vmhh9SN5XhjTGSWgx8iKk59XbKG6UH4oqpejRuJhfYD" }, { - "exception": "Invalid WIF payload length", - "string": "5qibUKwsnMo1qDiNp3prGaQkD2JfVJa8F8Na87H2CkMHvuVg6uKhw67Rh" + "exception": "Invalid WIF length", + "WIF": "38uMpGARR2BJy5p4dNFKYg9UsWNoBtkpbdrXDjmfvz8krCtw3T1W92ZDSR" } ] }