diff options
author | Ian Coleman <ian@iancoleman.io> | 2019-12-17 13:42:44 +1100 |
---|---|---|
committer | Ian Coleman <ian@iancoleman.io> | 2019-12-17 14:10:45 +1100 |
commit | 516c16d721db88b4b2c39964e2d5e8f6310c7bff (patch) | |
tree | ca4d1e8742d46715892adabe5003396819d7d12b | |
parent | f7e9fdf002e7355a122a86a8407b470b56bf3f59 (diff) | |
download | BIP39-516c16d721db88b4b2c39964e2d5e8f6310c7bff.tar.gz BIP39-516c16d721db88b4b2c39964e2d5e8f6310c7bff.tar.zst BIP39-516c16d721db88b4b2c39964e2d5e8f6310c7bff.zip |
Allow manual override for entropy type
-rw-r--r-- | src/css/app.css | 3 | ||||
-rw-r--r-- | src/index.html | 42 | ||||
-rw-r--r-- | src/js/entropy.js | 17 | ||||
-rw-r--r-- | src/js/index.js | 19 | ||||
-rw-r--r-- | tests/spec/tests.js | 44 |
5 files changed, 110 insertions, 15 deletions
diff --git a/src/css/app.css b/src/css/app.css index 576b7d7..3d0ec4b 100644 --- a/src/css/app.css +++ b/src/css/app.css | |||
@@ -106,3 +106,6 @@ body { | |||
106 | .visual-privacy .private-data { | 106 | .visual-privacy .private-data { |
107 | display: none; | 107 | display: none; |
108 | } | 108 | } |
109 | .text-weight-normal { | ||
110 | font-weight: normal !important; | ||
111 | } | ||
diff --git a/src/index.html b/src/index.html index 64c25f4..fe048dc 100644 --- a/src/index.html +++ b/src/index.html | |||
@@ -123,12 +123,42 @@ | |||
123 | <div class="col-sm-3"> | 123 | <div class="col-sm-3"> |
124 | <p>Valid entropy values include:</p> | 124 | <p>Valid entropy values include:</p> |
125 | <ul> | 125 | <ul> |
126 | <li><strong>Binary</strong> [0-1]<br>101010011</li> | 126 | <li> |
127 | <li><strong>Base 6</strong> [0-5]<br>123434014</li> | 127 | <label> |
128 | <li><strong>Dice</strong> [1-6]<br>62535634</li> | 128 | <input type="radio" name="entropy-type" value="binary"> |
129 | <li><strong>Base 10</strong> [0-9]<br>90834528</li> | 129 | <strong>Binary</strong> [0-1]<br>101010011 |
130 | <li><strong>Hex</strong> [0-9A-F]<br>4187a8bfd9</li> | 130 | </label> |
131 | <li><strong>Card</strong> [A2-9TJQK][CDHS]<br>ahqs9dtc</li> | 131 | </li> |
132 | <li> | ||
133 | <label> | ||
134 | <input type="radio" name="entropy-type" value="base 6"> | ||
135 | <strong>Base 6</strong> [0-5]<br>123434014 | ||
136 | </label> | ||
137 | </li> | ||
138 | <li> | ||
139 | <label> | ||
140 | <input type="radio" name="entropy-type" value="dice"> | ||
141 | <strong>Dice</strong> [1-6]<br>62535634 | ||
142 | </label> | ||
143 | </li> | ||
144 | <li> | ||
145 | <label> | ||
146 | <input type="radio" name="entropy-type" value="base 10"> | ||
147 | <strong>Base 10</strong> [0-9]<br>90834528 | ||
148 | </label> | ||
149 | </li> | ||
150 | <li> | ||
151 | <label> | ||
152 | <input type="radio" name="entropy-type" value="hexadecimal" checked> | ||
153 | <strong>Hex</strong> [0-9A-F]<br>4187a8bfd9 | ||
154 | </label> | ||
155 | </li> | ||
156 | <li> | ||
157 | <label> | ||
158 | <input type="radio" name="entropy-type" value="card"> | ||
159 | <strong>Card</strong> [A2-9TJQK][CDHS]<br>ahqs9dtc | ||
160 | </label> | ||
161 | </li> | ||
132 | </ul> | 162 | </ul> |
133 | </div> | 163 | </div> |
134 | </div> | 164 | </div> |
diff --git a/src/js/entropy.js b/src/js/entropy.js index a709c78..a4c7622 100644 --- a/src/js/entropy.js +++ b/src/js/entropy.js | |||
@@ -67,9 +67,9 @@ window.Entropy = new (function() { | |||
67 | return ints; | 67 | return ints; |
68 | } | 68 | } |
69 | 69 | ||
70 | this.fromString = function(rawEntropyStr) { | 70 | this.fromString = function(rawEntropyStr, baseStr) { |
71 | // Find type of entropy being used (binary, hex, dice etc) | 71 | // Find type of entropy being used (binary, hex, dice etc) |
72 | var base = getBase(rawEntropyStr); | 72 | var base = getBase(rawEntropyStr, baseStr); |
73 | // Convert dice to base6 entropy (ie 1-6 to 0-5) | 73 | // Convert dice to base6 entropy (ie 1-6 to 0-5) |
74 | // This is done by changing all 6s to 0s | 74 | // This is done by changing all 6s to 0s |
75 | if (base.str == "dice") { | 75 | if (base.str == "dice") { |
@@ -166,13 +166,14 @@ window.Entropy = new (function() { | |||
166 | return s; | 166 | return s; |
167 | } | 167 | } |
168 | 168 | ||
169 | function getBase(str) { | 169 | function getBase(str, baseStr) { |
170 | // Need to get the lowest base for the supplied entropy. | 170 | // Need to get the lowest base for the supplied entropy. |
171 | // This prevents interpreting, say, dice rolls as hexadecimal. | 171 | // This prevents interpreting, say, dice rolls as hexadecimal. |
172 | var binaryMatches = matchers.binary(str); | 172 | var binaryMatches = matchers.binary(str); |
173 | var hexMatches = matchers.hex(str); | 173 | var hexMatches = matchers.hex(str); |
174 | var autodetect = baseStr === undefined; | ||
174 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars | 175 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars |
175 | if (binaryMatches.length == hexMatches.length && hexMatches.length > 0) { | 176 | if ((binaryMatches.length == hexMatches.length && hexMatches.length > 0 && autodetect) || baseStr === "binary") { |
176 | var ints = binaryMatches.map(function(i) { return parseInt(i, 2) }); | 177 | var ints = binaryMatches.map(function(i) { return parseInt(i, 2) }); |
177 | return { | 178 | return { |
178 | ints: ints, | 179 | ints: ints, |
@@ -183,7 +184,7 @@ window.Entropy = new (function() { | |||
183 | } | 184 | } |
184 | } | 185 | } |
185 | var cardMatches = matchers.card(str); | 186 | var cardMatches = matchers.card(str); |
186 | if (cardMatches.length >= hexMatches.length / 2) { | 187 | if ((cardMatches.length >= hexMatches.length / 2 && autodetect) || baseStr === "card") { |
187 | var ints = convertCardsToInts(cardMatches); | 188 | var ints = convertCardsToInts(cardMatches); |
188 | return { | 189 | return { |
189 | ints: ints, | 190 | ints: ints, |
@@ -194,7 +195,7 @@ window.Entropy = new (function() { | |||
194 | } | 195 | } |
195 | } | 196 | } |
196 | var diceMatches = matchers.dice(str); | 197 | var diceMatches = matchers.dice(str); |
197 | if (diceMatches.length == hexMatches.length && hexMatches.length > 0) { | 198 | if ((diceMatches.length == hexMatches.length && hexMatches.length > 0 && autodetect) || baseStr === "dice") { |
198 | var ints = diceMatches.map(function(i) { return parseInt(i) }); | 199 | var ints = diceMatches.map(function(i) { return parseInt(i) }); |
199 | return { | 200 | return { |
200 | ints: ints, | 201 | ints: ints, |
@@ -205,7 +206,7 @@ window.Entropy = new (function() { | |||
205 | } | 206 | } |
206 | } | 207 | } |
207 | var base6Matches = matchers.base6(str); | 208 | var base6Matches = matchers.base6(str); |
208 | if (base6Matches.length == hexMatches.length && hexMatches.length > 0) { | 209 | if ((base6Matches.length == hexMatches.length && hexMatches.length > 0 && autodetect) || baseStr === "base 6") { |
209 | var ints = base6Matches.map(function(i) { return parseInt(i) }); | 210 | var ints = base6Matches.map(function(i) { return parseInt(i) }); |
210 | return { | 211 | return { |
211 | ints: ints, | 212 | ints: ints, |
@@ -216,7 +217,7 @@ window.Entropy = new (function() { | |||
216 | } | 217 | } |
217 | } | 218 | } |
218 | var base10Matches = matchers.base10(str); | 219 | var base10Matches = matchers.base10(str); |
219 | if (base10Matches.length == hexMatches.length && hexMatches.length > 0) { | 220 | if ((base10Matches.length == hexMatches.length && hexMatches.length > 0 && autodetect) || baseStr === "base 10") { |
220 | var ints = base10Matches.map(function(i) { return parseInt(i) }); | 221 | var ints = base10Matches.map(function(i) { return parseInt(i) }); |
221 | return { | 222 | return { |
222 | ints: ints, | 223 | ints: ints, |
diff --git a/src/js/index.js b/src/js/index.js index 5fb0c47..3db0a31 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -16,6 +16,7 @@ | |||
16 | var showQr = false; | 16 | var showQr = false; |
17 | var litecoinUseLtub = true; | 17 | var litecoinUseLtub = true; |
18 | 18 | ||
19 | var entropyTypeAutoDetect = true; | ||
19 | var entropyChangeTimeoutEvent = null; | 20 | var entropyChangeTimeoutEvent = null; |
20 | var phraseChangeTimeoutEvent = null; | 21 | var phraseChangeTimeoutEvent = null; |
21 | var rootKeyChangedTimeoutEvent = null; | 22 | var rootKeyChangedTimeoutEvent = null; |
@@ -32,6 +33,7 @@ | |||
32 | DOM.entropy = $(".entropy"); | 33 | DOM.entropy = $(".entropy"); |
33 | DOM.entropyFiltered = DOM.entropyContainer.find(".filtered"); | 34 | DOM.entropyFiltered = DOM.entropyContainer.find(".filtered"); |
34 | DOM.entropyType = DOM.entropyContainer.find(".type"); | 35 | DOM.entropyType = DOM.entropyContainer.find(".type"); |
36 | DOM.entropyTypeInputs = DOM.entropyContainer.find("input[name='entropy-type']"); | ||
35 | DOM.entropyCrackTime = DOM.entropyContainer.find(".crack-time"); | 37 | DOM.entropyCrackTime = DOM.entropyContainer.find(".crack-time"); |
36 | DOM.entropyEventCount = DOM.entropyContainer.find(".event-count"); | 38 | DOM.entropyEventCount = DOM.entropyContainer.find(".event-count"); |
37 | DOM.entropyBits = DOM.entropyContainer.find(".bits"); | 39 | DOM.entropyBits = DOM.entropyContainer.find(".bits"); |
@@ -128,6 +130,7 @@ | |||
128 | DOM.useEntropy.on("change", setEntropyVisibility); | 130 | DOM.useEntropy.on("change", setEntropyVisibility); |
129 | DOM.entropy.on("input", delayedEntropyChanged); | 131 | DOM.entropy.on("input", delayedEntropyChanged); |
130 | DOM.entropyMnemonicLength.on("change", entropyChanged); | 132 | DOM.entropyMnemonicLength.on("change", entropyChanged); |
133 | DOM.entropyTypeInputs.on("change", entropyTypeChanged); | ||
131 | DOM.phrase.on("input", delayedPhraseChanged); | 134 | DOM.phrase.on("input", delayedPhraseChanged); |
132 | DOM.passphrase.on("input", delayedPhraseChanged); | 135 | DOM.passphrase.on("input", delayedPhraseChanged); |
133 | DOM.generate.on("click", generateClicked); | 136 | DOM.generate.on("click", generateClicked); |
@@ -330,6 +333,11 @@ | |||
330 | } | 333 | } |
331 | } | 334 | } |
332 | 335 | ||
336 | function entropyTypeChanged() { | ||
337 | entropyTypeAutoDetect = false; | ||
338 | entropyChanged(); | ||
339 | } | ||
340 | |||
333 | function delayedRootKeyChanged() { | 341 | function delayedRootKeyChanged() { |
334 | // Warn if there is an existing mnemonic or passphrase. | 342 | // Warn if there is an existing mnemonic or passphrase. |
335 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { | 343 | if (DOM.phrase.val().length > 0 || DOM.passphrase.val().length > 0) { |
@@ -1551,7 +1559,14 @@ | |||
1551 | // Get entropy value | 1559 | // Get entropy value |
1552 | var entropyStr = DOM.entropy.val(); | 1560 | var entropyStr = DOM.entropy.val(); |
1553 | // Work out minimum base for entropy | 1561 | // Work out minimum base for entropy |
1554 | var entropy = Entropy.fromString(entropyStr); | 1562 | var entropy = null; |
1563 | if (entropyTypeAutoDetect) { | ||
1564 | entropy = Entropy.fromString(entropyStr); | ||
1565 | } | ||
1566 | else { | ||
1567 | let base = DOM.entropyTypeInputs.filter(":checked").val(); | ||
1568 | entropy = Entropy.fromString(entropyStr, base); | ||
1569 | } | ||
1555 | if (entropy.binaryStr.length == 0) { | 1570 | if (entropy.binaryStr.length == 0) { |
1556 | return; | 1571 | return; |
1557 | } | 1572 | } |
@@ -1632,6 +1647,8 @@ | |||
1632 | console.log(e); | 1647 | console.log(e); |
1633 | } | 1648 | } |
1634 | var entropyTypeStr = getEntropyTypeStr(entropy); | 1649 | var entropyTypeStr = getEntropyTypeStr(entropy); |
1650 | DOM.entropyTypeInputs.attr("checked", false); | ||
1651 | DOM.entropyTypeInputs.filter("[value='" + entropyTypeStr + "']").attr("checked", true); | ||
1635 | var wordCount = Math.floor(numberOfBits / 32) * 3; | 1652 | var wordCount = Math.floor(numberOfBits / 32) * 3; |
1636 | var bitsPerEvent = entropy.bitsPerEvent.toFixed(2); | 1653 | var bitsPerEvent = entropy.bitsPerEvent.toFixed(2); |
1637 | var spacedBinaryStr = addSpacesEveryElevenBits(entropy.binaryStr); | 1654 | var spacedBinaryStr = addSpacesEveryElevenBits(entropy.binaryStr); |
diff --git a/tests/spec/tests.js b/tests/spec/tests.js index bbc1f57..bdc5909 100644 --- a/tests/spec/tests.js +++ b/tests/spec/tests.js | |||
@@ -4285,4 +4285,48 @@ it('Shows split prase cards', function(done) { | |||
4285 | }); | 4285 | }); |
4286 | }); | 4286 | }); |
4287 | 4287 | ||
4288 | // It allows manually specifying the entropy type | ||
4289 | it('Allows entropy type to be manually selected', function(done) { | ||
4290 | driver.findElement(By.css('.use-entropy')) | ||
4291 | .click(); | ||
4292 | // use decimal entropy | ||
4293 | driver.findElement(By.css('.entropy')) | ||
4294 | .sendKeys("91"); | ||
4295 | // manually change to binary entropy | ||
4296 | driver.executeScript(function() { | ||
4297 | $(".entropy-container input[value='binary']").click(); | ||
4298 | }); | ||
4299 | driver.sleep(entropyFeedbackDelay).then(function() { | ||
4300 | driver.findElement(By.css('.entropy-container')) | ||
4301 | .getText() | ||
4302 | .then(function(text) { | ||
4303 | // overide 91 to be just 1 | ||
4304 | var key = "Filtered Entropy"; | ||
4305 | var value = "1"; | ||
4306 | var reText = key + "\\s+" + value; | ||
4307 | var re = new RegExp(reText); | ||
4308 | expect(text).toMatch(re); | ||
4309 | // overide automatic decimal to binary | ||
4310 | var key = "Entropy Type"; | ||
4311 | var value = "binary"; | ||
4312 | var reText = key + "\\s+" + value; | ||
4313 | var re = new RegExp(reText); | ||
4314 | expect(text).toMatch(re); | ||
4315 | // overide 2 events to 1 | ||
4316 | var key = "Event Count"; | ||
4317 | var value = 1; | ||
4318 | var reText = key + "\\s+" + value; | ||
4319 | var re = new RegExp(reText); | ||
4320 | expect(text).toMatch(re); | ||
4321 | // overide log2(10)*2 bits to 1 bit | ||
4322 | var key = "Total Bits"; | ||
4323 | var value = 1; | ||
4324 | var reText = key + "\\s+" + value; | ||
4325 | var re = new RegExp(reText); | ||
4326 | expect(text).toMatch(re); | ||
4327 | done(); | ||
4328 | }); | ||
4329 | }); | ||
4330 | }); | ||
4331 | |||
4288 | }); | 4332 | }); |