diff options
author | Ian Coleman <ian@iancoleman.io> | 2017-11-22 15:28:58 +1100 |
---|---|---|
committer | Ian Coleman <ian@iancoleman.io> | 2017-11-22 15:37:36 +1100 |
commit | 74ab4cbe90d037604120c93230ac9b0d74a6c7f1 (patch) | |
tree | c9c71ea4c4032f46f8adcce76a720a7115643a4f | |
parent | cf6c2044973413e3cfcda03079c6a66756fb023c (diff) | |
download | BIP39-74ab4cbe90d037604120c93230ac9b0d74a6c7f1.tar.gz BIP39-74ab4cbe90d037604120c93230ac9b0d74a6c7f1.tar.zst BIP39-74ab4cbe90d037604120c93230ac9b0d74a6c7f1.zip |
Show entropy from PRNG and word indexes
see issue #132
-rw-r--r-- | src/index.html | 4 | ||||
-rw-r--r-- | src/js/index.js | 43 | ||||
-rw-r--r-- | tests/spec/tests.js | 27 |
3 files changed, 72 insertions, 2 deletions
diff --git a/src/index.html b/src/index.html index f481473..ac1ab48 100644 --- a/src/index.html +++ b/src/index.html | |||
@@ -193,6 +193,8 @@ | |||
193 | <div class="filtered col-sm-9 form-control-static"></div> | 193 | <div class="filtered col-sm-9 form-control-static"></div> |
194 | <label class="col-sm-3 control-label">Raw Binary</label> | 194 | <label class="col-sm-3 control-label">Raw Binary</label> |
195 | <div class="binary col-sm-9 form-control-static"></div> | 195 | <div class="binary col-sm-9 form-control-static"></div> |
196 | <label class="col-sm-3 control-label">Word Indexes</label> | ||
197 | <div class="word-indexes col-sm-9 form-control-static"> </div> | ||
196 | <label class="col-sm-3 control-label">Mnemonic Length</label> | 198 | <label class="col-sm-3 control-label">Mnemonic Length</label> |
197 | <div class="col-sm-9"> | 199 | <div class="col-sm-9"> |
198 | <select class="mnemonic-length form-control"> | 200 | <select class="mnemonic-length form-control"> |
@@ -223,7 +225,7 @@ | |||
223 | <div class="col-sm-10 checkbox"> | 225 | <div class="col-sm-10 checkbox"> |
224 | <label> | 226 | <label> |
225 | <input type="checkbox" class="use-entropy"> | 227 | <input type="checkbox" class="use-entropy"> |
226 | <span>Supply my own source of entropy</span> | 228 | <span>Show entropy details</span> |
227 | </label> | 229 | </label> |
228 | </div> | 230 | </div> |
229 | </div> | 231 | </div> |
diff --git a/src/js/index.js b/src/js/index.js index 261a6d1..58090c3 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -37,6 +37,7 @@ | |||
37 | DOM.entropyBitsPerEvent = DOM.entropyContainer.find(".bits-per-event"); | 37 | DOM.entropyBitsPerEvent = DOM.entropyContainer.find(".bits-per-event"); |
38 | DOM.entropyWordCount = DOM.entropyContainer.find(".word-count"); | 38 | DOM.entropyWordCount = DOM.entropyContainer.find(".word-count"); |
39 | DOM.entropyBinary = DOM.entropyContainer.find(".binary"); | 39 | DOM.entropyBinary = DOM.entropyContainer.find(".binary"); |
40 | DOM.entropyWordIndexes = DOM.entropyContainer.find(".word-indexes"); | ||
40 | DOM.entropyMnemonicLength = DOM.entropyContainer.find(".mnemonic-length"); | 41 | DOM.entropyMnemonicLength = DOM.entropyContainer.find(".mnemonic-length"); |
41 | DOM.entropyFilterWarning = DOM.entropyContainer.find(".filter-warning"); | 42 | DOM.entropyFilterWarning = DOM.entropyContainer.find(".filter-warning"); |
42 | DOM.phrase = $(".phrase"); | 43 | DOM.phrase = $(".phrase"); |
@@ -219,6 +220,8 @@ | |||
219 | var passphrase = DOM.passphrase.val(); | 220 | var passphrase = DOM.passphrase.val(); |
220 | calcBip32RootKeyFromSeed(phrase, passphrase); | 221 | calcBip32RootKeyFromSeed(phrase, passphrase); |
221 | calcForDerivationPath(); | 222 | calcForDerivationPath(); |
223 | // Show the word indexes | ||
224 | showWordIndexes(); | ||
222 | } | 225 | } |
223 | 226 | ||
224 | function tabChanged() { | 227 | function tabChanged() { |
@@ -420,10 +423,20 @@ | |||
420 | showValidationError(errorText); | 423 | showValidationError(errorText); |
421 | return; | 424 | return; |
422 | } | 425 | } |
426 | // get the amount of entropy to use | ||
423 | var numWords = parseInt(DOM.generatedStrength.val()); | 427 | var numWords = parseInt(DOM.generatedStrength.val()); |
424 | var strength = numWords / 3 * 32; | 428 | var strength = numWords / 3 * 32; |
425 | var words = mnemonic.generate(strength); | 429 | var buffer = new Uint8Array(strength / 8); |
430 | // create secure entropy | ||
431 | var data = crypto.getRandomValues(buffer); | ||
432 | // show the words | ||
433 | var words = mnemonic.toMnemonic(data); | ||
426 | DOM.phrase.val(words); | 434 | DOM.phrase.val(words); |
435 | // show the entropy | ||
436 | var entropyHex = uint8ArrayToHex(data); | ||
437 | DOM.entropy.val(entropyHex); | ||
438 | // ensure entropy fields are consistent with what is being displayed | ||
439 | DOM.entropyMnemonicLength.val("raw"); | ||
427 | return words; | 440 | return words; |
428 | } | 441 | } |
429 | 442 | ||
@@ -1103,6 +1116,8 @@ | |||
1103 | var phrase = mnemonic.toMnemonic(entropyArr); | 1116 | var phrase = mnemonic.toMnemonic(entropyArr); |
1104 | // Set the mnemonic in the UI | 1117 | // Set the mnemonic in the UI |
1105 | DOM.phrase.val(phrase); | 1118 | DOM.phrase.val(phrase); |
1119 | // Show the word indexes | ||
1120 | showWordIndexes(); | ||
1106 | } | 1121 | } |
1107 | 1122 | ||
1108 | function clearEntropyFeedback() { | 1123 | function clearEntropyFeedback() { |
@@ -1328,6 +1343,32 @@ | |||
1328 | return parseInt(lastBitClean); | 1343 | return parseInt(lastBitClean); |
1329 | } | 1344 | } |
1330 | 1345 | ||
1346 | function uint8ArrayToHex(a) { | ||
1347 | var s = "" | ||
1348 | for (var i=0; i<a.length; i++) { | ||
1349 | var h = a[i].toString(16); | ||
1350 | while (h.length < 2) { | ||
1351 | h = "0" + h; | ||
1352 | } | ||
1353 | s = s + h; | ||
1354 | } | ||
1355 | return s; | ||
1356 | } | ||
1357 | |||
1358 | function showWordIndexes() { | ||
1359 | var phrase = DOM.phrase.val(); | ||
1360 | var words = phraseToWordArray(phrase); | ||
1361 | var wordIndexes = []; | ||
1362 | var language = getLanguage(); | ||
1363 | for (var i=0; i<words.length; i++) { | ||
1364 | var word = words[i]; | ||
1365 | var wordIndex = WORDLISTS[language].indexOf(word); | ||
1366 | wordIndexes.push(wordIndex); | ||
1367 | } | ||
1368 | var wordIndexesStr = wordIndexes.join(", "); | ||
1369 | DOM.entropyWordIndexes.text(wordIndexesStr); | ||
1370 | } | ||
1371 | |||
1331 | var networks = [ | 1372 | var networks = [ |
1332 | { | 1373 | { |
1333 | name: "BCH - Bitcoin Cash", | 1374 | name: "BCH - Bitcoin Cash", |
diff --git a/tests/spec/tests.js b/tests/spec/tests.js index 2b28d73..409219b 100644 --- a/tests/spec/tests.js +++ b/tests/spec/tests.js | |||
@@ -2643,4 +2643,31 @@ it('Can generate BIP141 addresses with P2WPKH semanitcs', function(done) { | |||
2643 | }); | 2643 | }); |
2644 | }); | 2644 | }); |
2645 | 2645 | ||
2646 | it('Shows the entropy used by the PRNG when clicking generate', function(done) { | ||
2647 | driver.findElement(By.css('.generate')).click(); | ||
2648 | driver.sleep(generateDelay).then(function() { | ||
2649 | driver.findElement(By.css('.entropy')) | ||
2650 | .getAttribute("value") | ||
2651 | .then(function(entropy) { | ||
2652 | expect(entropy).not.toBe(""); | ||
2653 | done(); | ||
2654 | }); | ||
2655 | }); | ||
2656 | }); | ||
2657 | |||
2658 | it('Shows the index of each word in the mnemonic', function(done) { | ||
2659 | driver.findElement(By.css('.phrase')) | ||
2660 | .sendKeys("abandon abandon ability"); | ||
2661 | driver.sleep(generateDelay).then(function() { | ||
2662 | driver.findElement(By.css('.use-entropy')) | ||
2663 | .click(); | ||
2664 | driver.findElement(By.css('.word-indexes')) | ||
2665 | .getText() | ||
2666 | .then(function(indexes) { | ||
2667 | expect(indexes).toBe("0, 0, 1"); | ||
2668 | done(); | ||
2669 | }); | ||
2670 | }); | ||
2671 | }); | ||
2672 | |||
2646 | }); | 2673 | }); |