diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-12-19 13:54:51 +1100 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-12-19 13:55:21 +1100 |
commit | ba3cb9ecae2667e98af71f5b38a862ba604e8e1c (patch) | |
tree | 380d24d03b7a3e6c7e02592901a62d605b2df61e | |
parent | 52da415f0385a6a89070498d14259aed980f989b (diff) | |
download | BIP39-ba3cb9ecae2667e98af71f5b38a862ba604e8e1c.tar.gz BIP39-ba3cb9ecae2667e98af71f5b38a862ba604e8e1c.tar.zst BIP39-ba3cb9ecae2667e98af71f5b38a862ba604e8e1c.zip |
xpub key can be used as bip32 root key
-rw-r--r-- | bip39-standalone.html | 26 | ||||
-rw-r--r-- | src/js/index.js | 26 | ||||
-rw-r--r-- | tests.js | 103 |
3 files changed, 147 insertions, 8 deletions
diff --git a/bip39-standalone.html b/bip39-standalone.html index 0f7d7d0..367d9a2 100644 --- a/bip39-standalone.html +++ b/bip39-standalone.html | |||
@@ -18868,11 +18868,11 @@ window.Entropy = new (function() { | |||
18868 | // Calculate and display | 18868 | // Calculate and display |
18869 | calcBip32RootKeyFromBase58(rootKeyBase58); | 18869 | calcBip32RootKeyFromBase58(rootKeyBase58); |
18870 | calcForDerivationPath(); | 18870 | calcForDerivationPath(); |
18871 | hidePending(); | ||
18872 | } | 18871 | } |
18873 | 18872 | ||
18874 | function calcForDerivationPath() { | 18873 | function calcForDerivationPath() { |
18875 | showPending(); | 18874 | showPending(); |
18875 | clearAddressesList(); | ||
18876 | hideValidationError(); | 18876 | hideValidationError(); |
18877 | // Get the derivation path | 18877 | // Get the derivation path |
18878 | var derivationPath = getDerivationPath(); | 18878 | var derivationPath = getDerivationPath(); |
@@ -18974,7 +18974,12 @@ window.Entropy = new (function() { | |||
18974 | continue; | 18974 | continue; |
18975 | } | 18975 | } |
18976 | var hardened = bit[bit.length-1] == "'"; | 18976 | var hardened = bit[bit.length-1] == "'"; |
18977 | if (hardened) { | 18977 | var isPriv = "privKey" in extendedKey; |
18978 | var invalidDerivationPath = hardened && !isPriv; | ||
18979 | if (invalidDerivationPath) { | ||
18980 | extendedKey = null; | ||
18981 | } | ||
18982 | else if (hardened) { | ||
18978 | extendedKey = extendedKey.deriveHardened(index); | 18983 | extendedKey = extendedKey.deriveHardened(index); |
18979 | } | 18984 | } |
18980 | else { | 18985 | else { |
@@ -19093,6 +19098,12 @@ window.Entropy = new (function() { | |||
19093 | } | 19098 | } |
19094 | } | 19099 | } |
19095 | } | 19100 | } |
19101 | // Check no hardened derivation path when using xpub keys | ||
19102 | var hardened = path.indexOf("'") > -1; | ||
19103 | var isXpubkey = !("privKey" in bip32RootKey); | ||
19104 | if (hardened && isXpubkey) { | ||
19105 | return "Hardened derivation path is invalid with xpub key"; | ||
19106 | } | ||
19096 | return false; | 19107 | return false; |
19097 | } | 19108 | } |
19098 | 19109 | ||
@@ -19119,7 +19130,11 @@ window.Entropy = new (function() { | |||
19119 | DOM.seed.val(seed); | 19130 | DOM.seed.val(seed); |
19120 | var rootKey = bip32RootKey.toBase58(); | 19131 | var rootKey = bip32RootKey.toBase58(); |
19121 | DOM.rootKey.val(rootKey); | 19132 | DOM.rootKey.val(rootKey); |
19122 | var extendedPrivKey = bip32ExtendedKey.toBase58(); | 19133 | var xprvkeyB58 = "NA"; |
19134 | if (bip32ExtendedKey.privKey) { | ||
19135 | xprvkeyB58 = bip32ExtendedKey.toBase58(); | ||
19136 | } | ||
19137 | var extendedPrivKey = xprvkeyB58; | ||
19123 | DOM.extendedPrivKey.val(extendedPrivKey); | 19138 | DOM.extendedPrivKey.val(extendedPrivKey); |
19124 | var extendedPubKey = bip32ExtendedKey.toBase58(false); | 19139 | var extendedPubKey = bip32ExtendedKey.toBase58(false); |
19125 | DOM.extendedPubKey.val(extendedPubKey); | 19140 | DOM.extendedPubKey.val(extendedPubKey); |
@@ -19153,7 +19168,10 @@ window.Entropy = new (function() { | |||
19153 | key = bip32ExtendedKey.derive(index); | 19168 | key = bip32ExtendedKey.derive(index); |
19154 | } | 19169 | } |
19155 | var address = key.getAddress().toString(); | 19170 | var address = key.getAddress().toString(); |
19156 | var privkey = key.privKey.toWIF(network); | 19171 | var privkey = "NA"; |
19172 | if (key.privKey) { | ||
19173 | privkey = key.privKey.toWIF(network); | ||
19174 | } | ||
19157 | var pubkey = key.pubKey.toHex(); | 19175 | var pubkey = key.pubKey.toHex(); |
19158 | var indexText = getDerivationPath() + "/" + index; | 19176 | var indexText = getDerivationPath() + "/" + index; |
19159 | if (useHardenedAddresses) { | 19177 | if (useHardenedAddresses) { |
diff --git a/src/js/index.js b/src/js/index.js index cac420e..45edea8 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -228,11 +228,11 @@ | |||
228 | // Calculate and display | 228 | // Calculate and display |
229 | calcBip32RootKeyFromBase58(rootKeyBase58); | 229 | calcBip32RootKeyFromBase58(rootKeyBase58); |
230 | calcForDerivationPath(); | 230 | calcForDerivationPath(); |
231 | hidePending(); | ||
232 | } | 231 | } |
233 | 232 | ||
234 | function calcForDerivationPath() { | 233 | function calcForDerivationPath() { |
235 | showPending(); | 234 | showPending(); |
235 | clearAddressesList(); | ||
236 | hideValidationError(); | 236 | hideValidationError(); |
237 | // Get the derivation path | 237 | // Get the derivation path |
238 | var derivationPath = getDerivationPath(); | 238 | var derivationPath = getDerivationPath(); |
@@ -334,7 +334,12 @@ | |||
334 | continue; | 334 | continue; |
335 | } | 335 | } |
336 | var hardened = bit[bit.length-1] == "'"; | 336 | var hardened = bit[bit.length-1] == "'"; |
337 | if (hardened) { | 337 | var isPriv = "privKey" in extendedKey; |
338 | var invalidDerivationPath = hardened && !isPriv; | ||
339 | if (invalidDerivationPath) { | ||
340 | extendedKey = null; | ||
341 | } | ||
342 | else if (hardened) { | ||
338 | extendedKey = extendedKey.deriveHardened(index); | 343 | extendedKey = extendedKey.deriveHardened(index); |
339 | } | 344 | } |
340 | else { | 345 | else { |
@@ -453,6 +458,12 @@ | |||
453 | } | 458 | } |
454 | } | 459 | } |
455 | } | 460 | } |
461 | // Check no hardened derivation path when using xpub keys | ||
462 | var hardened = path.indexOf("'") > -1; | ||
463 | var isXpubkey = !("privKey" in bip32RootKey); | ||
464 | if (hardened && isXpubkey) { | ||
465 | return "Hardened derivation path is invalid with xpub key"; | ||
466 | } | ||
456 | return false; | 467 | return false; |
457 | } | 468 | } |
458 | 469 | ||
@@ -479,7 +490,11 @@ | |||
479 | DOM.seed.val(seed); | 490 | DOM.seed.val(seed); |
480 | var rootKey = bip32RootKey.toBase58(); | 491 | var rootKey = bip32RootKey.toBase58(); |
481 | DOM.rootKey.val(rootKey); | 492 | DOM.rootKey.val(rootKey); |
482 | var extendedPrivKey = bip32ExtendedKey.toBase58(); | 493 | var xprvkeyB58 = "NA"; |
494 | if (bip32ExtendedKey.privKey) { | ||
495 | xprvkeyB58 = bip32ExtendedKey.toBase58(); | ||
496 | } | ||
497 | var extendedPrivKey = xprvkeyB58; | ||
483 | DOM.extendedPrivKey.val(extendedPrivKey); | 498 | DOM.extendedPrivKey.val(extendedPrivKey); |
484 | var extendedPubKey = bip32ExtendedKey.toBase58(false); | 499 | var extendedPubKey = bip32ExtendedKey.toBase58(false); |
485 | DOM.extendedPubKey.val(extendedPubKey); | 500 | DOM.extendedPubKey.val(extendedPubKey); |
@@ -513,7 +528,10 @@ | |||
513 | key = bip32ExtendedKey.derive(index); | 528 | key = bip32ExtendedKey.derive(index); |
514 | } | 529 | } |
515 | var address = key.getAddress().toString(); | 530 | var address = key.getAddress().toString(); |
516 | var privkey = key.privKey.toWIF(network); | 531 | var privkey = "NA"; |
532 | if (key.privKey) { | ||
533 | privkey = key.privKey.toWIF(network); | ||
534 | } | ||
517 | var pubkey = key.pubKey.toHex(); | 535 | var pubkey = key.pubKey.toHex(); |
518 | var indexText = getDerivationPath() + "/" + index; | 536 | var indexText = getDerivationPath() + "/" + index; |
519 | if (useHardenedAddresses) { | 537 | if (useHardenedAddresses) { |
@@ -3138,6 +3138,109 @@ page.open(url, function(status) { | |||
3138 | }); | 3138 | }); |
3139 | }, | 3139 | }, |
3140 | 3140 | ||
3141 | // github issue 40 | ||
3142 | // BIP32 root key can be set as an xpub | ||
3143 | function() { | ||
3144 | page.open(url, function(status) { | ||
3145 | // set the phrase | ||
3146 | page.evaluate(function() { | ||
3147 | // set xpub for account 0 of bip44 for 'abandon abandon ability' | ||
3148 | var bip44AccountXpub = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf"; | ||
3149 | $("#root-key").val(bip44AccountXpub); | ||
3150 | $("#root-key").trigger("input"); | ||
3151 | }); | ||
3152 | waitForFeedback(function() { | ||
3153 | page.evaluate(function() { | ||
3154 | // Use bip32 tab | ||
3155 | $("#bip32-tab a").click(); | ||
3156 | }); | ||
3157 | waitForGenerate(function() { | ||
3158 | page.evaluate(function() { | ||
3159 | // derive external addresses for this xpub | ||
3160 | var firstAccountDerivationPath = "m/0"; | ||
3161 | $("#bip32-path").val(firstAccountDerivationPath); | ||
3162 | $("#bip32-path").trigger("input"); | ||
3163 | }); | ||
3164 | waitForGenerate(function() { | ||
3165 | // check the addresses are generated | ||
3166 | var expected = "1Di3Vp7tBWtyQaDABLAjfWtF6V7hYKJtug"; | ||
3167 | var actual = page.evaluate(function() { | ||
3168 | return $(".address:first").text(); | ||
3169 | }); | ||
3170 | if (actual != expected) { | ||
3171 | console.log("xpub key does not generate addresses in table"); | ||
3172 | console.log("Expected: " + expected); | ||
3173 | console.log("Actual: " + actual); | ||
3174 | fail(); | ||
3175 | } | ||
3176 | // check the xprv key is not set | ||
3177 | var expected = "NA"; | ||
3178 | var actual = page.evaluate(function() { | ||
3179 | return $(".extended-priv-key").val(); | ||
3180 | }); | ||
3181 | if (actual != expected) { | ||
3182 | console.log("xpub key as root shows derived bip32 xprv key"); | ||
3183 | console.log("Expected: " + expected); | ||
3184 | console.log("Actual: " + actual); | ||
3185 | fail(); | ||
3186 | } | ||
3187 | // check the private key is not set | ||
3188 | var expected = "NA"; | ||
3189 | var actual = page.evaluate(function() { | ||
3190 | return $(".privkey:first").text(); | ||
3191 | }); | ||
3192 | if (actual != expected) { | ||
3193 | console.log("xpub key generates private key in addresses table"); | ||
3194 | console.log("Expected: " + expected); | ||
3195 | console.log("Actual: " + actual); | ||
3196 | fail(); | ||
3197 | } | ||
3198 | next(); | ||
3199 | }); | ||
3200 | }); | ||
3201 | }); | ||
3202 | }); | ||
3203 | }, | ||
3204 | |||
3205 | // github issue 40 | ||
3206 | // xpub for bip32 root key will not work with hardened derivation paths | ||
3207 | function() { | ||
3208 | page.open(url, function(status) { | ||
3209 | // set the phrase | ||
3210 | page.evaluate(function() { | ||
3211 | // set xpub for account 0 of bip44 for 'abandon abandon ability' | ||
3212 | var bip44AccountXpub = "xpub6CzDCPbtLrrn4VpVbyyQLHbdSMpZoHN4iuW64VswCyEpfjM2mJGdaHJ2DyuZwtst96E16VvcERb8BBeJdHSCVmAq9RhtRQg6eAZFrTKCNqf"; | ||
3213 | $("#root-key").val(bip44AccountXpub); | ||
3214 | $("#root-key").trigger("input"); | ||
3215 | }); | ||
3216 | waitForFeedback(function() { | ||
3217 | // Check feedback is correct | ||
3218 | var expected = "Hardened derivation path is invalid with xpub key"; | ||
3219 | var actual = page.evaluate(function() { | ||
3220 | return $(".feedback").text(); | ||
3221 | }); | ||
3222 | if (actual != expected) { | ||
3223 | console.log("xpub key with hardened derivation path does not show feedback"); | ||
3224 | console.log("Expected: " + expected); | ||
3225 | console.log("Actual: " + actual); | ||
3226 | fail(); | ||
3227 | } | ||
3228 | // Check no addresses are shown | ||
3229 | var expected = 0; | ||
3230 | var actual = page.evaluate(function() { | ||
3231 | return $(".addresses tr").length; | ||
3232 | }); | ||
3233 | if (actual != expected) { | ||
3234 | console.log("addresses still show after setting xpub key with hardened derivation path"); | ||
3235 | console.log("Expected: " + expected); | ||
3236 | console.log("Actual: " + actual); | ||
3237 | fail(); | ||
3238 | } | ||
3239 | next(); | ||
3240 | }); | ||
3241 | }); | ||
3242 | }, | ||
3243 | |||
3141 | 3244 | ||
3142 | // If you wish to add more tests, do so here... | 3245 | // If you wish to add more tests, do so here... |
3143 | 3246 | ||