diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2016-11-08 21:59:08 +1100 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2016-11-08 21:59:08 +1100 |
commit | 0d0f07f9374078ba71cf7f81cd6c2ab8df8d4693 (patch) | |
tree | 0c4c900044065e6b4838375619d881145bdd2064 | |
parent | 425b75a925717eb6f9813503569592a8160c5f34 (diff) | |
download | BIP39-0d0f07f9374078ba71cf7f81cd6c2ab8df8d4693.tar.gz BIP39-0d0f07f9374078ba71cf7f81cd6c2ab8df8d4693.tar.zst BIP39-0d0f07f9374078ba71cf7f81cd6c2ab8df8d4693.zip |
No leading zeros for first char unless hex
-rw-r--r-- | src/js/entropy.js | 28 | ||||
-rw-r--r-- | tests.js | 58 |
2 files changed, 54 insertions, 32 deletions
diff --git a/src/js/entropy.js b/src/js/entropy.js index 8e29d40..c804fda 100644 --- a/src/js/entropy.js +++ b/src/js/entropy.js | |||
@@ -71,17 +71,21 @@ window.Entropy = new (function() { | |||
71 | // This is done by changing all 6s to 0s | 71 | // This is done by changing all 6s to 0s |
72 | if (base.str == "dice") { | 72 | if (base.str == "dice") { |
73 | var newRawEntropyStr = ""; | 73 | var newRawEntropyStr = ""; |
74 | var newInts = []; | ||
74 | for (var i=0; i<rawEntropyStr.length; i++) { | 75 | for (var i=0; i<rawEntropyStr.length; i++) { |
75 | var c = rawEntropyStr[i]; | 76 | var c = rawEntropyStr[i]; |
76 | if ("12345".indexOf(c) > -1) { | 77 | if ("12345".indexOf(c) > -1) { |
77 | newRawEntropyStr += c; | 78 | newRawEntropyStr += c; |
79 | newInts[i] = base.ints[i]; | ||
78 | } | 80 | } |
79 | else { | 81 | else { |
80 | newRawEntropyStr += "0"; | 82 | newRawEntropyStr += "0"; |
83 | newInts[i] = 0; | ||
81 | } | 84 | } |
82 | } | 85 | } |
83 | rawEntropyStr = newRawEntropyStr; | 86 | rawEntropyStr = newRawEntropyStr; |
84 | base.str = "base 6 (dice)"; | 87 | base.str = "base 6 (dice)"; |
88 | base.ints = newInts; | ||
85 | base.parts = matchers.base6(rawEntropyStr); | 89 | base.parts = matchers.base6(rawEntropyStr); |
86 | base.matcher = matchers.base6; | 90 | base.matcher = matchers.base6; |
87 | } | 91 | } |
@@ -109,25 +113,23 @@ window.Entropy = new (function() { | |||
109 | if (base.ints.length == 0) { | 113 | if (base.ints.length == 0) { |
110 | return { | 114 | return { |
111 | binaryStr: binLeadingZeros, | 115 | binaryStr: binLeadingZeros, |
112 | cleanStr: leadingZeros, | 116 | cleanStr: leadingZeros.join(""), |
113 | base: base, | 117 | base: base, |
114 | } | 118 | } |
115 | } | 119 | } |
116 | // If the first integer is small, it must be padded with zeros. | 120 | // If the first integer is small, it must be padded with zeros. |
117 | // Otherwise the chance of the first bit being 1 is 100%, which is | 121 | // Otherwise the chance of the first bit being 1 is 100%, which is |
118 | // obviously incorrect. | 122 | // obviously incorrect. |
119 | // This is not perfect for unusual bases, eg base 6 has 2.6 bits, so is | 123 | // This is not perfect for unusual bases, so is only done for bases |
120 | // slightly biased toward having leading zeros, but it's still better | 124 | // of 2^n, eg octal or hexadecimal |
121 | // than ignoring it completely. | 125 | if (base.asInt == 16) { |
122 | // TODO: revise this, it seems very fishy. For example, in base 10, there are | 126 | var firstInt = base.ints[0]; |
123 | // 8 opportunities to start with 0 but only 2 to start with 1 | 127 | var firstIntBits = firstInt.toString(2).length; |
124 | var firstInt = base.ints[0]; | 128 | var maxFirstIntBits = (base.asInt-1).toString(2).length; |
125 | var firstIntBits = Math.floor(Math.log2(firstInt))+1; | 129 | var missingFirstIntBits = maxFirstIntBits - firstIntBits; |
126 | var maxFirstIntBits = Math.floor(Math.log2(base.asInt-1))+1; | 130 | for (var i=0; i<missingFirstIntBits; i++) { |
127 | var missingFirstIntBits = maxFirstIntBits - firstIntBits; | 131 | binLeadingZeros += "0"; |
128 | var firstIntLeadingZeros = ""; | 132 | } |
129 | for (var i=0; i<missingFirstIntBits; i++) { | ||
130 | binLeadingZeros += "0"; | ||
131 | } | 133 | } |
132 | // Convert base.ints to BigInteger. | 134 | // Convert base.ints to BigInteger. |
133 | // Due to using unusual bases, eg cards of base52, this is not as simple as | 135 | // Due to using unusual bases, eg cards of base52, this is not as simple as |
@@ -2130,11 +2130,31 @@ page.open(url, function(status) { | |||
2130 | catch (e) { | 2130 | catch (e) { |
2131 | return e.message; | 2131 | return e.message; |
2132 | } | 2132 | } |
2133 | // Leading zeros are correctly preserved for base 6 in binary string | 2133 | // Leading zeros are not used for base 6 as binary string |
2134 | try { | 2134 | try { |
2135 | e = Entropy.fromString("2"); | 2135 | e = Entropy.fromString("2"); |
2136 | if (e.binaryStr != "010") { | 2136 | if (e.binaryStr != "10") { |
2137 | return "Base 6 leading zeros are not correct in binary"; | 2137 | return "Base 6 as binary has leading zeros"; |
2138 | } | ||
2139 | } | ||
2140 | catch (e) { | ||
2141 | return e.message; | ||
2142 | } | ||
2143 | // Leading zeros are not used for base 10 as binary string | ||
2144 | try { | ||
2145 | e = Entropy.fromString("7"); | ||
2146 | if (e.binaryStr != "111") { | ||
2147 | return "Base 10 as binary has leading zeros"; | ||
2148 | } | ||
2149 | } | ||
2150 | catch (e) { | ||
2151 | return e.message; | ||
2152 | } | ||
2153 | // Leading zeros are not used for card entropy as binary string | ||
2154 | try { | ||
2155 | e = Entropy.fromString("2c"); | ||
2156 | if (e.binaryStr != "1") { | ||
2157 | return "Card entropy as binary has leading zeros"; | ||
2138 | } | 2158 | } |
2139 | } | 2159 | } |
2140 | catch (e) { | 2160 | catch (e) { |
@@ -2167,19 +2187,19 @@ page.open(url, function(status) { | |||
2167 | var cards = [ | 2187 | var cards = [ |
2168 | [ "ac", "00000" ], | 2188 | [ "ac", "00000" ], |
2169 | [ "acac", "00000000000" ], | 2189 | [ "acac", "00000000000" ], |
2170 | [ "acac2c", "00000000000000001" ], | 2190 | [ "acac2c", "000000000001" ], |
2171 | [ "acks", "00000110011" ], | 2191 | [ "acks", "00000110011" ], |
2172 | [ "acacks", "00000000000110011" ], | 2192 | [ "acacks", "00000000000110011" ], |
2173 | [ "2c", "000001" ], | 2193 | [ "2c", "1" ], |
2174 | [ "3d", "001111" ], | 2194 | [ "3d", "1111" ], |
2175 | [ "4h", "011101" ], | 2195 | [ "4h", "11101" ], |
2176 | [ "5s", "101011" ], | 2196 | [ "5s", "101011" ], |
2177 | [ "6c", "000101" ], | 2197 | [ "6c", "101" ], |
2178 | [ "7d", "010011" ], | 2198 | [ "7d", "10011" ], |
2179 | [ "8h", "100001" ], | 2199 | [ "8h", "100001" ], |
2180 | [ "9s", "101111" ], | 2200 | [ "9s", "101111" ], |
2181 | [ "tc", "001001" ], | 2201 | [ "tc", "1001" ], |
2182 | [ "jd", "010111" ], | 2202 | [ "jd", "10111" ], |
2183 | [ "qh", "100101" ], | 2203 | [ "qh", "100101" ], |
2184 | [ "ks", "110011" ], | 2204 | [ "ks", "110011" ], |
2185 | [ "ks2c", "101001011101" ], | 2205 | [ "ks2c", "101001011101" ], |
@@ -2465,11 +2485,11 @@ page.open(url, function(status) { | |||
2465 | [ "0000 0000 0000 0000 0000", "20" ], | 2485 | [ "0000 0000 0000 0000 0000", "20" ], |
2466 | [ "0", "1" ], | 2486 | [ "0", "1" ], |
2467 | [ "0000", "4" ], | 2487 | [ "0000", "4" ], |
2468 | [ "6", "3" ], | 2488 | [ "6", "2" ], // 6 in card is 0 in base 6, 0 in base 6 is 2.6 bits (rounded down to 2 bits) |
2469 | [ "7", "4" ], | 2489 | [ "7", "3" ], // 7 in base 10 is 111 in base 2, no leading zeros |
2470 | [ "8", "4" ], | 2490 | [ "8", "4" ], |
2471 | [ "F", "4" ], | 2491 | [ "F", "4" ], |
2472 | [ "29", "7" ], | 2492 | [ "29", "5" ], |
2473 | [ "0A", "8" ], | 2493 | [ "0A", "8" ], |
2474 | [ "1A", "8" ], // hex is always multiple of 4 bits of entropy | 2494 | [ "1A", "8" ], // hex is always multiple of 4 bits of entropy |
2475 | [ "2A", "8" ], | 2495 | [ "2A", "8" ], |
@@ -2477,9 +2497,9 @@ page.open(url, function(status) { | |||
2477 | [ "8A", "8" ], | 2497 | [ "8A", "8" ], |
2478 | [ "FA", "8" ], | 2498 | [ "FA", "8" ], |
2479 | [ "000A", "16" ], | 2499 | [ "000A", "16" ], |
2480 | [ "2220", "11" ], | 2500 | [ "5555", "11" ], |
2481 | [ "2221", "11" ], // uses dice, so entropy is actually 1110 | 2501 | [ "6666", "10" ], // uses dice, so entropy is actually 0000 in base 6, which is 4 lots of 2.58 bits, which is 10.32 bits (rounded down to 10 bits) |
2482 | [ "2227", "14" ], | 2502 | [ "2227", "12" ], |
2483 | [ "222F", "16" ], | 2503 | [ "222F", "16" ], |
2484 | [ "FFFF", "16" ], | 2504 | [ "FFFF", "16" ], |
2485 | ] | 2505 | ] |
@@ -2710,11 +2730,11 @@ page.open(url, function(status) { | |||
2710 | // base 20 | 2730 | // base 20 |
2711 | function() { | 2731 | function() { |
2712 | page.open(url, function(status) { | 2732 | page.open(url, function(status) { |
2713 | var expected = "defy trip fatal jaguar mean rack rifle survey satisfy drift twist champion steel wife state furnace night consider glove olympic oblige donor novel left"; | 2733 | var expected = "train then jungle barely whip fiber purpose puppy eagle cloud clump hospital robot brave balcony utility detect estate old green desk skill multiply virus"; |
2714 | // use entropy | 2734 | // use entropy |
2715 | page.evaluate(function() { | 2735 | page.evaluate(function() { |
2716 | $(".use-entropy").prop("checked", true).trigger("change"); | 2736 | $(".use-entropy").prop("checked", true).trigger("change"); |
2717 | var entropy = "123450123450123450123450123450123450123450123450123450123450123450123450123450123450123450123450123"; | 2737 | var entropy = "543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543210543"; |
2718 | $(".entropy").val(entropy).trigger("input"); | 2738 | $(".entropy").val(entropy).trigger("input"); |
2719 | }); | 2739 | }); |
2720 | // check the mnemonic matches the expected value from bip32jp | 2740 | // check the mnemonic matches the expected value from bip32jp |