From b4f70dcddebb90776c86beacdc9016ee30b9bee3 Mon Sep 17 00:00:00 2001 From: Daniel Cousens Date: Thu, 17 Apr 2014 19:08:16 +1000 Subject: [PATCH] Migrates ECKey to stricter API --- src/eckey.js | 266 +++++++++++++++++++------------------------- src/hdwallet.js | 30 ++--- src/message.js | 7 +- src/script.js | 7 +- src/transaction.js | 10 +- test/ec.js | 2 +- test/ecdsa.js | 12 +- test/eckey.js | 87 +++++++-------- test/hdwallet.js | 28 ++--- test/message.js | 17 +-- test/transaction.js | 8 +- 11 files changed, 213 insertions(+), 261 deletions(-) diff --git a/src/eckey.js b/src/eckey.js index 0ed6180..15c5d64 100644 --- a/src/eckey.js +++ b/src/eckey.js @@ -1,191 +1,149 @@ -var Address = require('./address') var assert = require('assert') var base58check = require('./base58check') -var BigInteger = require('./jsbn/jsbn') -var convert = require('./convert') -var crypto = require('./crypto') var ecdsa = require('./ecdsa') -var ECPointFp = require('./jsbn/ec').ECPointFp +var network = require('./network') +var secureRandom = require('secure-random') + +var Address = require('./address') +var crypto = require('./crypto') + var sec = require('./jsbn/sec') -var Network = require('./network') var ecparams = sec("secp256k1") -// input can be nothing, array of bytes, hex string, or base58 string -var ECKey = function (input, compressed) { - if (!(this instanceof ECKey)) { return new ECKey(input, compressed) } - if (!input) { - // Generate new key - var n = ecparams.getN() - this.priv = ecdsa.getBigRandom(n) - this.compressed = compressed || false +var BigInteger = require('./jsbn/jsbn') +var ECPointFp = require('./jsbn/ec').ECPointFp + +function ECKey(D, compressed) { + assert(D instanceof BigInteger) + assert(D.compareTo(BigInteger.ZERO) > 0) + assert(D.compareTo(ecparams.getN()) < 0) + + var Q = ecparams.getG().multiply(D) + + this.D = D + this.pub = new ECPubKey(Q, compressed) +} + +// Static constructors +ECKey.fromBuffer = function(buffer, compressed) { + assert(Buffer.isBuffer(buffer)) + var D = BigInteger.fromByteArrayUnsigned(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 + if (payload.length === 33) { + assert(payload[32] === 0x01) + + return ECKey.fromBuffer(payload.slice(0, 32), true) } - else this.import(input,compressed) + + assert(payload.length === 32) + return ECKey.fromBuffer(payload, false) } -ECKey.prototype.import = function (input, compressed) { - function has(li, v) { return li.indexOf(v) >= 0 } - function fromBin(x) { return BigInteger.fromByteArrayUnsigned(x) } +ECKey.makeRandom = function(compressed, rng) { + rng = rng || secureRandom - this.priv = - input instanceof ECKey ? input.priv - : input instanceof BigInteger ? input.mod(ecparams.getN()) - : Array.isArray(input) ? fromBin(input.slice(0, 32)) - : Buffer.isBuffer(input) ? fromBin(input.slice(0, 32)) - : typeof input != "string" ? null - : input.length == 44 ? fromBin(convert.base64ToBytes(input)) - : input.length == 51 && input[0] == '5' ? fromBin(base58check.decode(input).payload) - : input.length == 51 && input[0] == '9' ? fromBin(base58check.decode(input).payload) - : input.length == 52 && has('LK', input[0]) ? fromBin(base58check.decode(input).payload.slice(0, 32)) - : input.length == 52 && input[0] == 'c' ? fromBin(base58check.decode(input).payload.slice(0, 32)) - : has([64,65],input.length) ? fromBin(convert.hexToBytes(input.slice(0, 64))) - : null + var buffer = new Buffer(rng(32)) + var D = BigInteger.fromByteArrayUnsigned(buffer) + D = D.mod(ecparams.getN()) - assert(this.priv !== null) - - this.compressed = - compressed !== undefined ? compressed - : input instanceof ECKey ? input.compressed - : input instanceof BigInteger ? false - : Array.isArray(input) ? false - : typeof input != "string" ? null - : input.length == 44 ? false - : input.length == 51 && input[0] == '5' ? false - : input.length == 51 && input[0] == '9' ? false - : input.length == 52 && has('LK', input[0]) ? true - : input.length == 52 && input[0] == 'c' ? true - : input.length == 64 ? false - : input.length == 65 ? true - : null - - assert(this.compressed !== null) -} - -ECKey.prototype.getPub = function(compressed) { - if (compressed === undefined) compressed = this.compressed - return ECPubKey(ecparams.getG().multiply(this.priv), compressed) -} - -ECKey.prototype.toBin = function() { - return convert.bytesToString(this.toBytes()) -} - -ECKey.version_bytes = { - 0: 128, - 111: 239 -} - -ECKey.prototype.toWif = function(version) { - version = version || Network.bitcoin.pubKeyHash - - return base58check.encode(this.toBytes(), ECKey.version_bytes[version]) -} - -ECKey.prototype.toHex = function() { - return convert.bytesToHex(this.toBytes()) -} - -ECKey.prototype.toBytes = function() { - var bytes = this.priv.toByteArrayUnsigned() - - // ensure 32 bytes - while (bytes.length < 32) bytes.unshift(0) - - if (this.compressed) bytes.push(1) - return bytes -} - -ECKey.prototype.toBase64 = function() { - return convert.bytesToBase64(this.toBytes()) -} - -ECKey.prototype.toString = ECKey.prototype.toHex - -ECKey.prototype.getAddress = function(version) { - return this.getPub().getAddress(version) -} - -ECKey.prototype.add = function(key) { - return ECKey(this.priv.add(ECKey(key).priv), this.compressed) -} - -ECKey.prototype.multiply = function(key) { - return ECKey(this.priv.multiply(ECKey(key).priv), this.compressed) + return new ECKey(D, compressed) } +// Operations ECKey.prototype.sign = function(hash) { - return ecdsa.sign(hash, this.priv) + return ecdsa.sign(hash, this.D) } -ECKey.prototype.verify = function(hash, sig) { - return this.getPub().verify(hash, sig) -} +// Export functions +ECKey.prototype.toBuffer = function() { + var buffer = new Buffer(this.D.toByteArrayUnsigned()) -var ECPubKey = function(input, compressed) { - if (!(this instanceof ECPubKey)) { - return new ECPubKey(input, compressed) + // pad out the zero bytes + if (buffer.length < 32) { + var padded = new Buffer(32) + + padded.fill(0) + buffer.copy(padded, 32 - buffer.length) + + return padded } - this.import(input, compressed) + assert(buffer.length === 32) + + return buffer +} +ECKey.prototype.toHex = function() { + return this.toBuffer().toString('hex') } -ECPubKey.prototype.import = function(input, compressed) { - var decode = function(x) { return ECPointFp.decodeFrom(ecparams.getCurve(), x) } +ECKey.prototype.toWIF = function(version) { + version = version || network.bitcoin.wif - this.pub = - input instanceof ECPointFp ? input - : input instanceof ECKey ? ecparams.getG().multiply(input.priv) - : input instanceof ECPubKey ? input.pub - : typeof input == "string" ? decode(convert.hexToBytes(input)) - : Array.isArray(input) ? decode(input) - : Buffer.isBuffer(input) ? decode(input) - : null + var buffer + if (this.pub.compressed) { + buffer = Buffer.concat([this.toBuffer(), new Buffer([0x01])]) + } else { + buffer = this.toBuffer() + } - assert(this.pub !== null) - - this.compressed = - compressed ? compressed - : input instanceof ECPointFp ? input.compressed - : input instanceof ECPubKey ? input.compressed - : (this.pub[0] < 4) + return base58check.encode(buffer, version) } -ECPubKey.prototype.add = function(key) { - return ECPubKey(this.pub.add(ECPubKey(key).pub), this.compressed) +////////////////////////////////////////////////////// + +function ECPubKey(Q, compressed) { + if (compressed == undefined) compressed = true + assert(typeof compressed === 'boolean') + assert(Q instanceof ECPointFp) + + this.compressed = compressed + this.Q = Q } -ECPubKey.prototype.multiply = function(key) { - return ECPubKey(this.pub.multiply(ECKey(key).priv), this.compressed) +// Static constructors +ECPubKey.fromBuffer = function(buffer) { + assert(Buffer.isBuffer(buffer)) + + var Q = ECPointFp.decodeFrom(ecparams.getCurve(), buffer) + + var type = buffer.readUInt8(0) + assert(type >= 0x02 || type <= 0x04) + + var compressed = (type !== 0x04) + return new ECPubKey(Q, compressed) +} +ECPubKey.fromHex = function(hex) { + return ECPubKey.fromBuffer(new Buffer(hex, 'hex')) } -ECPubKey.prototype.toBytes = function(compressed) { - if (compressed === undefined) compressed = this.compressed - return this.pub.getEncoded(compressed) +// Operations +ECPubKey.prototype.verify = function(hash, sig) { + return ecdsa.verify(hash, sig, this.Q) } -ECPubKey.prototype.toHex = function(compressed) { - return convert.bytesToHex(this.toBytes(compressed)) -} - -ECPubKey.prototype.toBin = function(compressed) { - return convert.bytesToString(this.toBytes(compressed)) -} - -ECPubKey.prototype.toWif = function(version) { - version = version || Network.bitcoin.pubKeyHash - - return base58check.encode(this.toBytes(), version) -} - -ECPubKey.prototype.toString = ECPubKey.prototype.toHex - ECPubKey.prototype.getAddress = function(version) { - version = version || Network.bitcoin.pubKeyHash - - return new Address(crypto.hash160(this.toBytes()), version) + return new Address(crypto.hash160(this.toBuffer()), version) } -ECPubKey.prototype.verify = function(hash, sig) { - return ecdsa.verify(hash, sig, this.toBytes()) +// Export functions +ECPubKey.prototype.toBuffer = function() { + var buffer = new Buffer(this.Q.getEncoded(this.compressed)) + assert(buffer.length === (this.compressed ? 33 : 65)) + + return buffer +} +ECPubKey.prototype.toHex = function() { + return this.toBuffer().toString('hex') } module.exports = { diff --git a/src/hdwallet.js b/src/hdwallet.js index 2885562..dd4fdec 100644 --- a/src/hdwallet.js +++ b/src/hdwallet.js @@ -31,8 +31,8 @@ function HDWallet(seed, networkString) { throw new Error("Unknown network: " + this.network) } - this.priv = new ECKey(I.slice(0, 32), true) - this.pub = this.priv.getPub() + this.priv = ECKey.fromBuffer(I.slice(0, 32), true) + this.pub = this.priv.pub this.index = 0 this.depth = 0 } @@ -105,17 +105,17 @@ 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 = new ECKey(input.slice(46, 78), true) - hd.pub = hd.priv.getPub() + hd.priv = ECKey.fromBuffer(input.slice(46, 78), true) + hd.pub = hd.priv.pub } else { - hd.pub = new ECPubKey(input.slice(45, 78), true) + hd.pub = ECPubKey.fromBuffer(input.slice(45, 78), true) } return hd } HDWallet.prototype.getIdentifier = function() { - return crypto.hash160(this.pub.toBytes()) + return crypto.hash160(this.pub.toBuffer()) } HDWallet.prototype.getFingerprint = function() { @@ -123,7 +123,7 @@ HDWallet.prototype.getFingerprint = function() { } HDWallet.prototype.getAddress = function() { - return new Address(crypto.hash160(this.pub.toBytes()), this.getKeyVersion()) + return this.pub.getAddress(this.getKeyVersion()) } HDWallet.prototype.toBuffer = function(priv) { @@ -155,11 +155,11 @@ HDWallet.prototype.toBuffer = function(priv) { // 0x00 + k for private keys buffer.writeUInt8(0, 45) - new Buffer(this.priv.toBytes()).copy(buffer, 46) + this.priv.toBuffer().copy(buffer, 46) } else { // X9.62 encoding for public keys - new Buffer(this.pub.toBytes()).copy(buffer, 45) + this.pub.toBuffer().copy(buffer, 45) } return buffer @@ -190,14 +190,16 @@ HDWallet.prototype.derive = function(i) { // If 1, private derivation is used: // let I = HMAC-SHA512(Key = cpar, Data = 0x00 || kpar || i) [Note:] - var kPar = this.priv.toBytes().slice(0, 32) + var kPar = this.priv.toBuffer().slice(0, 32) + kPar = Array.prototype.slice.call(kPar) // FIXME: Dislikes buffers I = HmacFromBytesToBytes(SHA512, [0].concat(kPar, iBytes), cPar) } else { // If 0, public derivation is used: // let I = HMAC-SHA512(Key = cpar, Data = χ(kpar*G) || i) - var KPar = this.pub.toBytes() + var KPar = this.pub.toBuffer() + KPar = Array.prototype.slice.call(KPar) // FIXME: Dislikes buffers I = HmacFromBytesToBytes(SHA512, KPar.concat(iBytes), cPar) @@ -217,13 +219,13 @@ HDWallet.prototype.derive = function(i) { if (this.priv) { // ki = IL + kpar (mod n). - var ki = IL.add(this.priv.priv).mod(ecparams.getN()) + var ki = IL.add(this.priv.D).mod(ecparams.getN()) hd.priv = new ECKey(ki, true) - hd.pub = hd.priv.getPub() + hd.pub = hd.priv.pub } else { // Ki = (IL + kpar)*G = IL*G + Kpar - var Ki = IL.multiply(ecparams.getG()).add(this.pub.pub) + var Ki = IL.multiply(ecparams.getG()).add(this.pub.Q) hd.pub = new ECPubKey(Ki, true) } diff --git a/src/message.js b/src/message.js index 56eee48..e3e7c63 100644 --- a/src/message.js +++ b/src/message.js @@ -27,10 +27,10 @@ function sign(key, message) { var hash = magicHash(message) var sig = key.sign(hash) var obj = ecdsa.parseSig(sig) - var i = ecdsa.calcPubKeyRecoveryParam(key.getPub().pub, obj.r, obj.s, hash) + var i = ecdsa.calcPubKeyRecoveryParam(key.pub.Q, obj.r, obj.s, hash) i += 27 - if (key.compressed) { + if (key.pub.compressed) { i += 4 } @@ -50,8 +50,7 @@ function verify(address, sig, message) { sig = ecdsa.parseSigCompact(sig) var pubKey = new ECPubKey(ecdsa.recoverPubKey(sig.r, sig.s, magicHash(message), sig.i)) - var isCompressed = !!(sig.i & 4) - pubKey.compressed = isCompressed + pubKey.compressed = !!(sig.i & 4) address = new Address(address) return pubKey.getAddress(address.version).toString() === address.toString() diff --git a/src/script.js b/src/script.js index deeea9a..08f9d11 100644 --- a/src/script.js +++ b/src/script.js @@ -1,10 +1,10 @@ -var Opcode = require('./opcode') +var Address = require('./address') var crypto = require('./crypto') var convert = require('./convert') -var Address = require('./address') var network = require('./network') +var Opcode = require('./opcode') -var Script = function(data) { +function Script(data) { this.buffer = data || [] if(!Array.isArray(this.buffer)) { throw new Error('expect Script to be initialized with Array, but got ' + data) @@ -368,6 +368,7 @@ Script.prototype.writeBytes = function(data) { */ Script.createOutputScript = function(address) { var script = new Script() + address = new Address(address) if (address.version == network.bitcoin.scriptHash || address.version == network.testnet.scriptHash) { diff --git a/src/transaction.js b/src/transaction.js index f0ebf4f..5f64d43 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -1,5 +1,6 @@ // FIXME: To all ye that enter here, be weary of Buffers, Arrays and Hex interchanging between the outpoints +var assert = require('assert') var Address = require('./address') var BigInteger = require('./jsbn/jsbn') var Script = require('./script') @@ -217,7 +218,7 @@ Transaction.prototype.getHash = function () var buffer = this.serialize() var hash = crypto.hash256(buffer) - return Array.prototype.slice.call(hash, 0).reverse() + return Array.prototype.slice.call(hash).reverse() } Transaction.prototype.clone = function () @@ -298,10 +299,10 @@ Transaction.deserialize = function(buffer) { * Signs a standard output at some index with the given key */ Transaction.prototype.sign = function(index, key, type) { + assert(key instanceof ECKey) type = type || SIGHASH_ALL - key = new ECKey(key) - var pub = key.getPub().toBytes() + var pub = key.pub.toBuffer() var hash160 = crypto.hash160(pub) var script = Script.createOutputScript(new Address(hash160)) var hash = this.hashTransactionForSignature(script, index, type) @@ -315,7 +316,8 @@ Transaction.prototype.signWithKeys = function(keys, outputs, type) { type = type || SIGHASH_ALL var addrdata = keys.map(function(key) { - key = new ECKey(key) + assert(key instanceof ECKey) + return { key: key, address: key.getAddress().toString() diff --git a/test/ec.js b/test/ec.js index 94382fa..71b5c59 100644 --- a/test/ec.js +++ b/test/ec.js @@ -27,7 +27,7 @@ describe('ec', function() { describe('decodeFrom', function() { it('decodes valid ECPoints', function() { - var p1 = ECKey().getPub().toBytes() + var p1 = ECKey.makeRandom(false).pub.toBuffer() assert.equal(p1.length, 65) var p1_q = ECPointFp.decodeFrom(ecparams.getCurve(), p1) diff --git a/test/ecdsa.js b/test/ecdsa.js index d000ab2..2d98f0d 100644 --- a/test/ecdsa.js +++ b/test/ecdsa.js @@ -25,17 +25,17 @@ describe('ecdsa', function() { describe('sign/verify', function() { it('Signing and Verifying', function () { - var s1 = new ECKey() + var s1 = ECKey.makeRandom() var sig_a = s1.sign(BigInteger.ZERO) assert.ok(sig_a, 'Sign null') - assert.ok(s1.verify(BigInteger.ZERO, sig_a)) + assert.ok(s1.pub.verify(BigInteger.ZERO, sig_a)) - var message = new BigInteger(1024, rng).toByteArrayUnsigned() + var message = new Buffer(1024) // More or less random :P var hash = crypto.sha256(message) var sig_b = s1.sign(hash) assert.ok(sig_b, 'Sign random string') - assert.ok(s1.verify(hash, sig_b)) + assert.ok(s1.pub.verify(hash, sig_b)) var message2 = new Buffer( '12dce2c169986b3346827ffb2305cf393984627f5f9722a1b1368e933c8d' + @@ -60,7 +60,7 @@ describe('ecdsa', function() { }) it('should sign with low S value', function() { - var priv = new ECKey('ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458') + var priv = ECKey.fromHex('ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458') var message = 'Vires in numeris' var signature = priv.sign(message) var parsed = ecdsa.parseSig(signature) @@ -69,7 +69,7 @@ describe('ecdsa', function() { // https://github.com/bitcoin/bips/blob/master/bip-0062.mediawiki#low-s-values-in-signatures assert.ok(parsed.s.compareTo(ecparams.getN().divide(BigInteger.valueOf(2))) <= 0) - assert.ok(priv.verify(message, signature)) + assert.ok(priv.pub.verify(message, signature)) }) }) }) diff --git a/test/eckey.js b/test/eckey.js index 4134333..f6ea526 100644 --- a/test/eckey.js +++ b/test/eckey.js @@ -1,9 +1,8 @@ var assert = require('assert') +var Address = require('../src/address.js') var ECKey = require('../src/eckey.js').ECKey var ECPubKey = require('../src/eckey.js').ECPubKey var convert = require('../src/convert.js') -var bytesToHex = convert.bytesToHex -var hexToBytes = convert.hexToBytes var Address = require('../src/address') var Network = require('../src/network') var testnet = Network.testnet.pubKeyHash @@ -14,20 +13,10 @@ describe('ECKey', function() { var priv = '18e14a7b6a307f426a94f8114701e7c8e774e7f9a47e2c2035db29a206321725' var pub = '0450863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b235' + '22cd470243453a299fa9e77237716103abc11a1df38855ed6f2ee187e9c582ba6' - var key = new ECKey(priv) + var key = ECKey.fromHex(priv, false) - assert.equal(key.getPub().toHex(), pub) - assert.equal(key.compressed, false) - }) - - it('parses base64', function() { - var priv = 'VYdB+iv47y5FaUVIPdQInkgATrABeuD1lACUoM4x7tU=' - var pub = '042f43c16c08849fed20a35bb7b1947bbf0923c52d613ee13b5c665a1e10d24b2' + - '8be909a70f5f87c1adb79fbcd1b3f17d20aa91c04fc355112dba2ce9b1cbf013b' - var key = new ECKey(priv) - - assert.equal(key.getPub().toHex(), pub) - assert.equal(key.compressed, false) + assert.equal(key.pub.toHex(), pub) + assert.equal(key.pub.compressed, false) }) it('parses WIF', function() { @@ -35,32 +24,32 @@ describe('ECKey', function() { var pub = '044f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0' + 'f0b704075871aa385b6b1b8ead809ca67454d9683fcf2ba03456d6fe2c4abe2b07f0fbdbb2f1c1' var addr = '1MsHWS1BnwMc3tLE8G35UXsS58fKipzB7a' - var key = new ECKey(priv) + var key = ECKey.fromWIF(priv) - assert.equal(key.compressed, false) - assert.equal(key.getPub().toHex(), pub) - assert.equal(key.getAddress().toString(), addr) + assert.equal(key.pub.compressed, false) + assert.equal(key.pub.toHex(), pub) + assert.equal(key.pub.getAddress().toString(), addr) }) it('parses compressed WIF', function() { var priv = 'KwntMbt59tTsj8xqpqYqRRWufyjGunvhSyeMo3NTYpFYzZbXJ5Hp' var pub = '034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa' var addr = '1Q1pE5vPGEEMqRcVRMbtBK842Y6Pzo6nK9' - var key = new ECKey(priv) + var key = ECKey.fromWIF(priv) - assert.equal(key.compressed, true) - assert.equal(key.getPub().toHex(), pub) - assert.equal(key.getAddress().toString(), addr) + assert.equal(key.pub.compressed, true) + assert.equal(key.pub.toHex(), pub) + assert.equal(key.pub.getAddress().toString(), addr) }) it('alternative constructor syntax', function() { var priv = 'ca48ec9783cf3ad0dfeff1fc254395a2e403cbbc666477b61b45e31d3b8ab458' var pub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199' + '283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' - var key = ECKey(priv, false) + var key = ECKey.fromHex(priv, false) - assert.equal(key.getPub().toHex(), pub) - assert.equal(key.compressed, false) + assert.equal(key.pub.toHex(), pub) + assert.equal(key.pub.compressed, false) assert.equal(key.toHex(), priv) }) }) @@ -80,7 +69,9 @@ describe('ECKey', function() { ] var pubkeys = cpubkeys.map(function(x) { - return ECPubKey(x).toHex(false) + var pk = ECPubKey.fromHex(x) + pk.compressed = false + return pk.toHex() }) it('bitcoin', function() { @@ -96,14 +87,13 @@ describe('ECKey', function() { ] for (var i = 0; i < addresses.length; ++i) { - var priv = new ECKey(privkeys[i], false) - var pub = new ECPubKey(pubkeys[i], false) - var cpub = new ECPubKey(cpubkeys[i], true) + 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(priv.getAddress().toString(), addr) assert.equal(pub.getAddress().toString(), addr) assert.equal(cpub.getAddress().toString(), caddr) } @@ -122,14 +112,13 @@ describe('ECKey', function() { ] for (var i = 0; i < addresses.length; ++i) { - var priv = new ECKey(privkeys[i], false) - var pub = new ECPubKey(pubkeys[i], false) - var cpub = new ECPubKey(cpubkeys[i], true) + 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(priv.getAddress().toString(), addr) assert.equal(pub.getAddress().toString(), addr) assert.equal(cpub.getAddress().toString(), caddr) } @@ -142,27 +131,27 @@ describe('ECKey', function() { var message = 'Vires in numeris' it('should verify against the private key', function() { - var priv = new ECKey(hpriv) + var priv = ECKey.fromHex(hpriv) var signature = priv.sign(message) - assert(priv.verify(message, signature)) + assert(priv.pub.verify(message, signature)) }) it('should verify against the public key', function() { - var priv = new ECKey(hpriv) - var pub = new ECPubKey(hcpub, true) + var priv = ECKey.fromHex(hpriv) + var pub = ECPubKey.fromHex(hcpub, true) var signature = priv.sign(message) assert(pub.verify(message, signature)) }) it('should not verify against the wrong private key', function() { - var priv1 = new ECKey(hpriv) - var priv2 = new ECKey('1111111111111111111111111111111111111111111111111111111111111111') + var priv1 = ECKey.fromHex(hpriv) + var priv2 = ECKey.fromHex('1111111111111111111111111111111111111111111111111111111111111111') var signature = priv1.sign(message) - assert(!priv2.verify(message, signature)) + assert(!priv2.pub.verify(message, signature)) }) }) @@ -171,17 +160,17 @@ describe('ECKey', function() { var hpub = '044b12d9d7c77db68388b6ff7c89046174c871546436806bcd80d07c28ea81199283fbec990dad6fb98f93f712d50cb874dd717de6a184158d63886dda3090f566' it('using toHex should support compression', function() { - var pub = new ECPubKey(hpub) + var pub = ECPubKey.fromHex(hcpub) - assert.equal(pub.toHex(true), hcpub) - assert.equal(pub.toHex(false), hpub) + assert.equal(pub.toHex(), hcpub) + assert.equal(pub.compressed, true) }) - it('using toBytes should support compression', function() { - var pub = new ECPubKey(hpub) + it('using toHex should support uncompressed', function() { + var pub = ECPubKey.fromHex(hpub) - assert.equal(bytesToHex(pub.toBytes(true)), hcpub) - assert.equal(bytesToHex(pub.toBytes(false)), hpub) + assert.equal(pub.toHex(), hpub) + assert.equal(pub.compressed, false) }) }) }) diff --git a/test/hdwallet.js b/test/hdwallet.js index ae28adb..2488fdd 100644 --- a/test/hdwallet.js +++ b/test/hdwallet.js @@ -32,7 +32,7 @@ describe('HDWallet', function() { }) describe('constructor & seed deserialization', function() { - var expectedPrivateKey = '0fd71c652e847ba7ea7956e3cf3fc0a0985871846b1b2c23b9c6a29a38cee86001' + var expectedPrivateKey = '0fd71c652e847ba7ea7956e3cf3fc0a0985871846b1b2c23b9c6a29a38cee860' var seed = new Buffer([ 99, 114, 97, 122, 121, 32, 104, 111, 114, 115, 101, 32, 98, 97, 116, 116, 101, 114, 121, 32, 115, 116, 97, 112, 108, 101 @@ -63,8 +63,8 @@ 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(), 'e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b3501') - assert.equal(hd.priv.toWif(), 'L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW') + assert.equal(hd.priv.toHex(), 'e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35') + assert.equal(hd.priv.toWIF(), 'L52XzL2cMkHxqxBXRyEpnPQZGUs3uKiL3R11XbAdHigRzDozKZeW') assert.equal(hd.pub.toHex(), '0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2') assert.equal(b2h(hd.chaincode), '873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508') assert.equal(hd.toHex(false), '0488b21e000000000000000000873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d5080339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2') @@ -78,7 +78,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L5BmPijJjrKbiUfG4zbiFKNqkvuJ8usooJmzuD7Z8dkRoTThYnAT') assert.equal(hd.pub.toHex(), '035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56') assert.equal(b2h(hd.chaincode), '47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141') assert.equal(hd.toHex(false), '0488b21e013442193e8000000047fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141035a784662a4a20a65bf6aab9ae98a6c068a81c52e4b032c0fb5400c706cfccc56') @@ -92,7 +92,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'KyFAjQ5rgrKvhXvNMtFB5PCSKUYD1yyPEe3xr3T34TZSUHycXtMM') assert.equal(hd.pub.toHex(), '03501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c') assert.equal(b2h(hd.chaincode), '2a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c19') assert.equal(hd.toHex(false), '0488b21e025c1bd648000000012a7857631386ba23dacac34180dd1983734e444fdbf774041578e9b6adb37c1903501e454bf00751f24b1b489aa925215d66af2234e3891c3b21a52bedb3cd711c') @@ -106,7 +106,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L43t3od1Gh7Lj55Bzjj1xDAgJDcL7YFo2nEcNaMGiyRZS1CidBVU') assert.equal(hd.pub.toHex(), '0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2') assert.equal(b2h(hd.chaincode), '04466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f') assert.equal(hd.toHex(false), '0488b21e03bef5a2f98000000204466b9cc8e161e966409ca52986c584f07e9dc81f735db683c3ff6ec7b1503f0357bfe1e341d01c69fe5654309956cbea516822fba8a601743a012a7896ee8dc2') @@ -120,7 +120,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'KwjQsVuMjbCP2Zmr3VaFaStav7NvevwjvvkqrWd5Qmh1XVnCteBR') assert.equal(hd.pub.toHex(), '02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29') assert.equal(b2h(hd.chaincode), 'cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd') assert.equal(hd.toHex(false), '0488b21e04ee7ab90c00000002cfb71883f01676f587d023cc53a35bc7f88f724b1f8c2892ac1275ac822a3edd02e8445082a72f29b75ca48748a914df60622a609cacfce8ed0e35804560741d29') @@ -134,7 +134,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'Kybw8izYevo5xMh1TK7aUr7jHFCxXS1zv8p3oqFz3o2zFbhRXHYs') assert.equal(hd.pub.toHex(), '022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011') assert.equal(b2h(hd.chaincode), 'c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e') assert.equal(hd.toHex(false), '0488b21e05d880d7d83b9aca00c783e67b921d2beb8f6b389cc646d7263b4145701dadd2161548a8b078e65e9e022a471424da5e657499d1ff51cb43c47481a03b1e77f951fe64cec9f5a48f7011') @@ -151,7 +151,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'KyjXhyHF9wTphBkfpxjL8hkDXDUSbE3tKANT94kXSyh6vn6nKaoy') assert.equal(hd.pub.toHex(), '03cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7') assert.equal(b2h(hd.chaincode), '60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689') assert.equal(hd.toHex(false), '0488b21e00000000000000000060499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd968903cbcaa9c98c877a26977d00825c956a238e8dddfbd322cce4f74b0b5bd6ace4a7') @@ -165,7 +165,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L2ysLrR6KMSAtx7uPqmYpoTeiRzydXBattRXjXz5GDFPrdfPzKbj') assert.equal(hd.pub.toHex(), '02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea') assert.equal(b2h(hd.chaincode), 'f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c') assert.equal(hd.toHex(false), '0488b21e01bd16bee500000000f0909affaa7ee7abe5dd4e100598d4dc53cd709d5a5c2cac40e7412f232f7c9c02fc9e5af0ac8d9b3cecfe2a888e2117ba3d089d8585886c9c826b6b22a98d12ea') @@ -179,7 +179,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L1m5VpbXmMp57P3knskwhoMTLdhAAaXiHvnGLMribbfwzVRpz2Sr') assert.equal(hd.pub.toHex(), '03c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b') assert.equal(b2h(hd.chaincode), 'be17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d9') assert.equal(hd.toHex(false), '0488b21e025a61ff8effffffffbe17a268474a6bb9c61e1d720cf6215e2a88c5406c4aee7b38547f585c9a37d903c01e7425647bdefa82b12d9bad5e3e6865bee0502694b94ca58b666abc0a5c3b') @@ -193,7 +193,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'KzyzXnznxSv249b4KuNkBwowaN3akiNeEHy5FWoPCJpStZbEKXN2') assert.equal(hd.pub.toHex(), '03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9') assert.equal(b2h(hd.chaincode), 'f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb') assert.equal(hd.toHex(false), '0488b21e03d8ab493700000001f366f48f1ea9f2d1d3fe958c95ca84ea18e4c4ddb9366c336c927eb246fb38cb03a7d1d856deb74c508e05031f9895dab54626251b3806e16b4bd12e781a7df5b9') @@ -207,7 +207,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L5KhaMvPYRW1ZoFmRjUtxxPypQ94m6BcDrPhqArhggdaTbbAFJEF') assert.equal(hd.pub.toHex(), '02d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0') assert.equal(b2h(hd.chaincode), '637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e29') assert.equal(hd.toHex(false), '0488b21e0478412e3afffffffe637807030d55d01f9a0cb3a7839515d796bd07706386a6eddf06cc29a65a0e2902d2b36900396c9282fa14628566582f206a5dd0bcc8d5e892611806cafb0301f0') @@ -221,7 +221,7 @@ describe('HDWallet', function() { 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.priv.toWIF(), 'L3WAYNAZPxx1fr7KCz7GN9nD5qMBnNiqEJNJMU1z9MMaannAt4aK') assert.equal(hd.pub.toHex(), '024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c') assert.equal(b2h(hd.chaincode), '9452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271') assert.equal(hd.toHex(false), '0488b21e0531a507b8000000029452b549be8cea3ecb7a84bec10dcfd94afe4d129ebfd3b3cb58eedf394ed271024d902e1a2fc7a8755ab5b694c575fce742c48d9ff192e63df5193e4c7afe1f9c') diff --git a/test/message.js b/test/message.js index 0038a3e..b66cd16 100644 --- a/test/message.js +++ b/test/message.js @@ -2,7 +2,6 @@ var assert = require('assert') var convert = require('../').convert var ECKey = require('../src/eckey').ECKey var Message = require('../').Message -var testnet = require('../').network.testnet.pubKeyHash describe('Message', function() { var msg @@ -54,14 +53,14 @@ describe('Message', function() { describe('signing', function() { describe('using the uncompressed public key', function(){ it('gives same signature as a compressed public key', function() { - var key = new ECKey(null) // uncompressed + var key = ECKey.makeRandom(false) // uncompressed var sig = Message.sign(key, msg) - var compressedKey = new ECKey(key, true) // compressed clone - var csig = Message.sign(compressedKey, msg) // FIXME: bad compression support + var compressedKey = new ECKey(key.D, true) // compressed clone + var csig = Message.sign(compressedKey, msg) - var addr = key.getPub().getAddress() - var caddr = compressedKey.getPub().getAddress() + var addr = key.pub.getAddress() + var caddr = compressedKey.pub.getAddress() assert.ok(Message.verify(addr, sig, msg)) assert.ok(Message.verify(caddr, csig, msg)) assert.notDeepEqual(sig.slice(0, 2), csig.slice(0, 2)) // unequal compression flags @@ -71,10 +70,12 @@ describe('Message', function() { describe('testnet address', function(){ it('works', function(){ - var key = new ECKey(null) + var testnet = require('../').network.testnet + + var key = ECKey.makeRandom() var sig = Message.sign(key, msg) - var addr = key.getAddress(testnet) + var addr = key.pub.getAddress(testnet.pubKeyHash) assert(Message.verify(addr, sig, msg)) }) }) diff --git a/test/transaction.js b/test/transaction.js index 8d6de6b..1a80d33 100644 --- a/test/transaction.js +++ b/test/transaction.js @@ -166,10 +166,10 @@ describe('Transaction', function() { tx.addOutput("15mMHKL96tWAUtqF3tbVf99Z8arcmnJrr3:40000") tx.addOutput("1Bu3bhwRmevHLAy1JrRB6AfcxfgDG2vXRd:50000") - var key = new ECKey('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb') + var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb') tx.sign(0, key) - var pub = key.getPub().toBytes() + var pub = key.pub.toBuffer() var script = prevTx.outs[0].script.buffer var sig = tx.ins[0].script.chunks[0] @@ -185,8 +185,8 @@ describe('Transaction', function() { }) it('returns true for valid signature', function(){ - var key = new ECKey('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb') - var pub = key.getPub().toBytes() + var key = ECKey.fromWIF('L44f7zxJ5Zw4EK9HZtyAnzCYz2vcZ5wiJf9AuwhJakiV4xVkxBeb') + var pub = key.pub.toBuffer() var script = prevTx.outs[0].script.buffer var sig = validTx.ins[0].script.chunks[0]