From 9fd46c22fee6540321752ccee18a595abb7ea79d Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 12 Dec 2013 11:13:35 +0100 Subject: [PATCH 1/5] missing modulo operation. --- src/bip32.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bip32.js b/src/bip32.js index 36a0d2f..55818b1 100644 --- a/src/bip32.js +++ b/src/bip32.js @@ -83,7 +83,7 @@ BIP32key.prototype.ckd = function(i) { if (this.type == 'priv') { Ikey = Bitcoin.BigInteger.fromByteArrayUnsigned(I.slice(0,32)) - newkey = new key(this.key.priv.add(Ikey)) + newkey = new key(this.key.priv.add(Ikey).mod(ecparams.getN())) newkey.compressed = true fingerprint = util.sha256ripe160(this.key.getPub()).slice(0,4) } From 740a0fcb7d5dd0e592a531f24394ef3e38c63354 Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 12 Dec 2013 11:14:27 +0100 Subject: [PATCH 2/5] test vectors for bip32. --- test/bip32.js | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 test/bip32.js diff --git a/test/bip32.js b/test/bip32.js new file mode 100644 index 0000000..0c0f82a --- /dev/null +++ b/test/bip32.js @@ -0,0 +1,96 @@ +// Tests from https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Test_Vectors + +var assert = require('assert'); +var BIP32key = require('..').BIP32key; + +var hexToBytes = require('../').convert.hexToBytes; +var bytesToString = require('../').convert.bytesToString; + +function checkKey(key, extPriv, extPub) { + assert.equal(key.serialize(), extPriv); + assert.equal(key.getPub().serialize(), extPub); +} + +test("BIP32 Test vector 1", function () { + var seed_str = '000102030405060708090a0b0c0d0e0f'; + var seed = bytesToString(hexToBytes(seed_str)); + + var key = new BIP32key(seed); + + checkKey(key, + "xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi", + "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"); + + var branch = key.ckd(0+BIP32_PRIME); + + checkKey(branch, + "xprv9uHRZZhk6KAJC1avXpDAp4MDc3sQKNxDiPvvkX8Br5ngLNv1TxvUxt4cV1rGL5hj6KCesnDYUhd7oWgT11eZG7XnxHrnYeSvkzY7d2bhkJ7", + "xpub68Gmy5EdvgibQVfPdqkBBCHxA5htiqg55crXYuXoQRKfDBFA1WEjWgP6LHhwBZeNK1VTsfTFUHCdrfp1bgwQ9xv5ski8PX9rL2dZXvgGDnw"); + + var branch2 = branch.ckd(1); + + checkKey(branch2, + "xprv9wTYmMFdV23N2TdNG573QoEsfRrWKQgWeibmLntzniatZvR9BmLnvSxqu53Kw1UmYPxLgboyZQaXwTCg8MSY3H2EU4pWcQDnRnrVA1xe8fs", + "xpub6ASuArnXKPbfEwhqN6e3mwBcDTgzisQN1wXN9BJcM47sSikHjJf3UFHKkNAWbWMiGj7Wf5uMash7SyYq527Hqck2AxYysAA7xmALppuCkwQ"); + + var branch3 = branch2.ckd(2+BIP32_PRIME); + + checkKey(branch3, + "xprv9z4pot5VBttmtdRTWfWQmoH1taj2axGVzFqSb8C9xaxKymcFzXBDptWmT7FwuEzG3ryjH4ktypQSAewRiNMjANTtpgP4mLTj34bhnZX7UiM", + "xpub6D4BDPcP2GT577Vvch3R8wDkScZWzQzMMUm3PWbmWvVJrZwQY4VUNgqFJPMM3No2dFDFGTsxxpG5uJh7n7epu4trkrX7x7DogT5Uv6fcLW5"); + + var branch4 = branch3.ckd(2); + + checkKey(branch4, + "xprvA2JDeKCSNNZky6uBCviVfJSKyQ1mDYahRjijr5idH2WwLsEd4Hsb2Tyh8RfQMuPh7f7RtyzTtdrbdqqsunu5Mm3wDvUAKRHSC34sJ7in334", + "xpub6FHa3pjLCk84BayeJxFW2SP4XRrFd1JYnxeLeU8EqN3vDfZmbqBqaGJAyiLjTAwm6ZLRQUMv1ZACTj37sR62cfN7fe5JnJ7dh8zL4fiyLHV"); + + var branch5 = branch4.ckd(1000000000); + + checkKey(branch5, + "xprvA41z7zogVVwxVSgdKUHDy1SKmdb533PjDz7J6N6mV6uS3ze1ai8FHa8kmHScGpWmj4WggLyQjgPie1rFSruoUihUZREPSL39UNdE3BBDu76", + "xpub6H1LXWLaKsWFhvm6RVpEL9P4KfRZSW7abD2ttkWP3SSQvnyA8FSVqNTEcYFgJS2UaFcxupHiYkro49S8yGasTvXEYBVPamhGW6cFJodrTHy"); + +}); + +test("BIP32 Test vector 2", function () { + var seed_str = 'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542'; + var seed = bytesToString(hexToBytes(seed_str)); + + var key = new BIP32key(seed); + + checkKey(key, + "xprv9s21ZrQH143K31xYSDQpPDxsXRTUcvj2iNHm5NUtrGiGG5e2DtALGdso3pGz6ssrdK4PFmM8NSpSBHNqPqm55Qn3LqFtT2emdEXVYsCzC2U", + "xpub661MyMwAqRbcFW31YEwpkMuc5THy2PSt5bDMsktWQcFF8syAmRUapSCGu8ED9W6oDMSgv6Zz8idoc4a6mr8BDzTJY47LJhkJ8UB7WEGuduB"); + + var branch = key.ckd(0); + + checkKey(branch, + "xprv9vHkqa6EV4sPZHYqZznhT2NPtPCjKuDKGY38FBWLvgaDx45zo9WQRUT3dKYnjwih2yJD9mkrocEZXo1ex8G81dwSM1fwqWpWkeS3v86pgKt", + "xpub69H7F5d8KSRgmmdJg2KhpAK8SR3DjMwAdkxj3ZuxV27CprR9LgpeyGmXUbC6wb7ERfvrnKZjXoUmmDznezpbZb7ap6r1D3tgFxHmwMkQTPH"); + + var branch2 = branch.ckd(2147483647+BIP32_PRIME); + + checkKey(branch2, + "xprv9wSp6B7kry3Vj9m1zSnLvN3xH8RdsPP1Mh7fAaR7aRLcQMKTR2vidYEeEg2mUCTAwCd6vnxVrcjfy2kRgVsFawNzmjuHc2YmYRmagcEPdU9", + "xpub6ASAVgeehLbnwdqV6UKMHVzgqAG8Gr6riv3Fxxpj8ksbH9ebxaEyBLZ85ySDhKiLDBrQSARLq1uNRts8RuJiHjaDMBU4Zn9h8LZNnBC5y4a"); + + var branch3 = branch2.ckd(1); + + checkKey(branch3, + "xprv9zFnWC6h2cLgpmSA46vutJzBcfJ8yaJGg8cX1e5StJh45BBciYTRXSd25UEPVuesF9yog62tGAQtHjXajPPdbRCHuWS6T8XA2ECKADdw4Ef", + "xpub6DF8uhdarytz3FWdA8TvFSvvAh8dP3283MY7p2V4SeE2wyWmG5mg5EwVvmdMVCQcoNJxGoWaU9DCWh89LojfZ537wTfunKau47EL2dhHKon"); + + + var branch4 = branch3.ckd(2147483646+BIP32_PRIME); + + checkKey(branch4, + "xprvA1RpRA33e1JQ7ifknakTFpgNXPmW2YvmhqLQYMmrj4xJXXWYpDPS3xz7iAxn8L39njGVyuoseXzU6rcxFLJ8HFsTjSyQbLYnMpCqE2VbFWc", + "xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL"); + + var branch5 = branch4.ckd(2); + + checkKey(branch5, + "xprvA2nrNbFZABcdryreWet9Ea4LvTJcGsqrMzxHx98MMrotbir7yrKCEXw7nadnHM8Dq38EGfSh6dqA9QWTyefMLEcBYJUuekgW4BYPJcr9E7j", + "xpub6FnCn6nSzZAw5Tw7cgR9bi15UV96gLZhjDstkXXxvCLsUXBGXPdSnLFbdpq8p9HmGsApME5hQTZ3emM2rnY5agb9rXpVGyy3bdW6EEgAtqt"); +}); From 26e5914be26e0f1a3f70e8188db95706f31a6a2f Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 12 Dec 2013 17:19:31 +0100 Subject: [PATCH 3/5] fix in pubkey deserialization code. --- src/bip32.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bip32.js b/src/bip32.js index 55818b1..9ce7b7e 100644 --- a/src/bip32.js +++ b/src/bip32.js @@ -48,7 +48,7 @@ BIP32key.prototype.deserialize = function(str) { fingerprint: bytes.slice(5,9), i: util.bytesToNum(bytes.slice(9,13).reverse()), chaincode: bytes.slice(13,45), - key: new key(type == 'priv' ? bytes.slice(46,78).concat([1]) : bytes.slice(45,78)) + key: type == 'priv' ? new key(bytes.slice(46,78).concat([1])) : bytes.slice(45,78) }) } From 14803d053858bd153f5b5c21f6e8c17f95d1bf7e Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 12 Dec 2013 17:25:29 +0100 Subject: [PATCH 4/5] fix check for public key when making a private derivation. --- src/bip32.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bip32.js b/src/bip32.js index 9ce7b7e..8a4dc1c 100644 --- a/src/bip32.js +++ b/src/bip32.js @@ -74,7 +74,7 @@ BIP32key.prototype.ckd = function(i) { else pub = this.key if (i >= 2147483648) { - if (this.priv) throw new Error("Can't do private derivation on public key!") + if (!priv) throw new Error("Can't do private derivation on public key!") blob = [0].concat(priv.slice(0,32),util.numToBytes(i,4).reverse()) } else blob = pub.concat(util.numToBytes(i,4).reverse()) From f9cbcbeb2bb9c84abfbdf41817355ce640d678de Mon Sep 17 00:00:00 2001 From: Pablo Martin Date: Thu, 12 Dec 2013 17:46:39 +0100 Subject: [PATCH 5/5] missing BIP32_PRIME definition in bip32 tests. --- test/bip32.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/bip32.js b/test/bip32.js index 0c0f82a..2ccee37 100644 --- a/test/bip32.js +++ b/test/bip32.js @@ -6,6 +6,8 @@ var BIP32key = require('..').BIP32key; var hexToBytes = require('../').convert.hexToBytes; var bytesToString = require('../').convert.bytesToString; +var BIP32_PRIME = 0x80000000; + function checkKey(key, extPriv, extPub) { assert.equal(key.serialize(), extPriv); assert.equal(key.getPub().serialize(), extPub);