diff options
-rw-r--r-- | src/js/entropy.js | 76 |
1 files changed, 55 insertions, 21 deletions
diff --git a/src/js/entropy.js b/src/js/entropy.js index 1e556ce..5b687d8 100644 --- a/src/js/entropy.js +++ b/src/js/entropy.js | |||
@@ -1,11 +1,41 @@ | |||
1 | /* | ||
2 | * Detects entropy from a string. | ||
3 | * | ||
4 | * Formats include: | ||
5 | * binary [0-1] | ||
6 | * base 6 [0-5] | ||
7 | * dice 6 [1-6] | ||
8 | * decimal [0-9] | ||
9 | * hexadecimal [0-9A-F] | ||
10 | * | ||
11 | * Automatically uses lowest entropy to avoid issues such as interpretting 0101 | ||
12 | * as hexadecimal which would be 16 bits when really it's only 4 bits of binary | ||
13 | * entropy. | ||
14 | */ | ||
15 | |||
1 | window.Entropy = new (function() { | 16 | window.Entropy = new (function() { |
2 | 17 | ||
18 | // matchers returns an array of the matched events for each type of entropy. | ||
19 | // eg | ||
20 | // matchers.binary("010") returns ["0", "1", "0"] | ||
21 | // matchers.binary("a10") returns ["1", "0"] | ||
22 | // matchers.hex("a10") returns ["a", "1", "0"] | ||
3 | var matchers = { | 23 | var matchers = { |
4 | binary: /[0-1]/gi, | 24 | binary: function(str) { |
5 | base6: /[0-5]/gi, | 25 | return str.match(/[0-1]/gi) || []; |
6 | dice: /[1-6]/gi, // ie dice numbers | 26 | }, |
7 | base10: /[0-9]/gi, | 27 | base6: function(str) { |
8 | hex: /[0-9A-F]/gi, | 28 | return str.match(/[0-5]/gi) || []; |
29 | }, | ||
30 | dice: function(str) { | ||
31 | return str.match(/[1-6]/gi) || []; // ie dice numbers | ||
32 | }, | ||
33 | base10: function(str) { | ||
34 | return str.match(/[0-9]/gi) || []; | ||
35 | }, | ||
36 | hex: function(str) { | ||
37 | return str.match(/[0-9A-F]/gi) || []; | ||
38 | }, | ||
9 | } | 39 | } |
10 | 40 | ||
11 | this.fromString = function(rawEntropyStr) { | 41 | this.fromString = function(rawEntropyStr) { |
@@ -25,12 +55,11 @@ window.Entropy = new (function() { | |||
25 | } | 55 | } |
26 | rawEntropyStr = newRawEntropyStr; | 56 | rawEntropyStr = newRawEntropyStr; |
27 | base.str = "base 6 (dice)"; | 57 | base.str = "base 6 (dice)"; |
58 | base.parts = matchers.base6(rawEntropyStr); | ||
28 | base.matcher = matchers.base6; | 59 | base.matcher = matchers.base6; |
29 | } | 60 | } |
30 | var entropyParts = rawEntropyStr.match(base.matcher) || []; | ||
31 | var entropyStr = entropyParts.join(""); | ||
32 | // Detect empty entropy | 61 | // Detect empty entropy |
33 | if (entropyStr.length == 0) { | 62 | if (base.parts.length == 0) { |
34 | return { | 63 | return { |
35 | binaryStr: "", | 64 | binaryStr: "", |
36 | hexStr: "", | 65 | hexStr: "", |
@@ -39,10 +68,10 @@ window.Entropy = new (function() { | |||
39 | }; | 68 | }; |
40 | } | 69 | } |
41 | // Pull leading zeros off | 70 | // Pull leading zeros off |
42 | var leadingZeros = ""; | 71 | var leadingZeros = []; |
43 | while (entropyStr[0] == "0") { | 72 | while (base.parts[0] == "0") { |
44 | leadingZeros += "0"; | 73 | leadingZeros.push("0"); |
45 | entropyStr = entropyStr.substring(1); | 74 | base.parts.shift(); |
46 | } | 75 | } |
47 | // Convert leading zeros to binary equivalent | 76 | // Convert leading zeros to binary equivalent |
48 | var numBinLeadingZeros = Math.ceil(Math.log2(base.asInt) * leadingZeros.length); | 77 | var numBinLeadingZeros = Math.ceil(Math.log2(base.asInt) * leadingZeros.length); |
@@ -57,7 +86,7 @@ window.Entropy = new (function() { | |||
57 | hexLeadingZeros += "0"; | 86 | hexLeadingZeros += "0"; |
58 | } | 87 | } |
59 | // Handle entropy of zero | 88 | // Handle entropy of zero |
60 | if (entropyStr == "") { | 89 | if (base.parts.length == 0) { |
61 | return { | 90 | return { |
62 | binaryStr: binLeadingZeros, | 91 | binaryStr: binLeadingZeros, |
63 | hexStr: hexLeadingZeros || "0", | 92 | hexStr: hexLeadingZeros || "0", |
@@ -69,7 +98,7 @@ window.Entropy = new (function() { | |||
69 | // out of sync if first number has leading 0 bits, eg 2 in hex is 0010 | 98 | // out of sync if first number has leading 0 bits, eg 2 in hex is 0010 |
70 | // which would show up as 10, thus missing 2 bits it should have. | 99 | // which would show up as 10, thus missing 2 bits it should have. |
71 | if (base.asInt == 16) { | 100 | if (base.asInt == 16) { |
72 | var firstDigit = parseInt(entropyStr[0], 16); | 101 | var firstDigit = parseInt(base.parts[0], 16); |
73 | if (firstDigit >= 4 && firstDigit < 8) { | 102 | if (firstDigit >= 4 && firstDigit < 8) { |
74 | binLeadingZeros += "0"; | 103 | binLeadingZeros += "0"; |
75 | } | 104 | } |
@@ -81,10 +110,10 @@ window.Entropy = new (function() { | |||
81 | } | 110 | } |
82 | } | 111 | } |
83 | // Convert entropy to different foramts | 112 | // Convert entropy to different foramts |
84 | var entropyInt = BigInteger.parse(entropyStr, base.asInt); | 113 | var entropyInt = BigInteger.parse(base.parts.join(""), base.asInt); |
85 | var entropyBin = binLeadingZeros + entropyInt.toString(2); | 114 | var entropyBin = binLeadingZeros + entropyInt.toString(2); |
86 | var entropyHex = hexLeadingZeros + entropyInt.toString(16); | 115 | var entropyHex = hexLeadingZeros + entropyInt.toString(16); |
87 | var entropyClean = leadingZeros + entropyStr; | 116 | var entropyClean = leadingZeros.join("") + base.parts.join(""); |
88 | var e = { | 117 | var e = { |
89 | binaryStr: entropyBin, | 118 | binaryStr: entropyBin, |
90 | hexStr: entropyHex, | 119 | hexStr: entropyHex, |
@@ -97,41 +126,46 @@ window.Entropy = new (function() { | |||
97 | function getBase(str) { | 126 | function getBase(str) { |
98 | // Need to get the lowest base for the supplied entropy. | 127 | // Need to get the lowest base for the supplied entropy. |
99 | // This prevents interpreting, say, dice rolls as hexadecimal. | 128 | // This prevents interpreting, say, dice rolls as hexadecimal. |
100 | var binaryMatches = str.match(matchers.binary) || []; | 129 | var binaryMatches = matchers.binary(str); |
101 | var base6Matches = str.match(matchers.base6) || []; | 130 | var hexMatches = matchers.hex(str); |
102 | var diceMatches = str.match(matchers.dice) || []; | ||
103 | var base10Matches = str.match(matchers.base10) || []; | ||
104 | var hexMatches = str.match(matchers.hex) || []; | ||
105 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars | 131 | // Find the lowest base that can be used, whilst ignoring any irrelevant chars |
106 | if (binaryMatches.length == hexMatches.length) { | 132 | if (binaryMatches.length == hexMatches.length) { |
107 | return { | 133 | return { |
134 | parts: binaryMatches, | ||
108 | matcher: matchers.binary, | 135 | matcher: matchers.binary, |
109 | asInt: 2, | 136 | asInt: 2, |
110 | str: "binary", | 137 | str: "binary", |
111 | } | 138 | } |
112 | } | 139 | } |
140 | var diceMatches = matchers.dice(str); | ||
113 | if (diceMatches.length == hexMatches.length) { | 141 | if (diceMatches.length == hexMatches.length) { |
114 | return { | 142 | return { |
143 | parts: diceMatches, | ||
115 | matcher: matchers.dice, | 144 | matcher: matchers.dice, |
116 | asInt: 6, | 145 | asInt: 6, |
117 | str: "dice", | 146 | str: "dice", |
118 | } | 147 | } |
119 | } | 148 | } |
149 | var base6Matches = matchers.base6(str); | ||
120 | if (base6Matches.length == hexMatches.length) { | 150 | if (base6Matches.length == hexMatches.length) { |
121 | return { | 151 | return { |
152 | parts: base6Matches, | ||
122 | matcher: matchers.base6, | 153 | matcher: matchers.base6, |
123 | asInt: 6, | 154 | asInt: 6, |
124 | str: "base 6", | 155 | str: "base 6", |
125 | } | 156 | } |
126 | } | 157 | } |
158 | var base10Matches = matchers.base10(str); | ||
127 | if (base10Matches.length == hexMatches.length) { | 159 | if (base10Matches.length == hexMatches.length) { |
128 | return { | 160 | return { |
161 | parts: base10Matches, | ||
129 | matcher: matchers.base10, | 162 | matcher: matchers.base10, |
130 | asInt: 10, | 163 | asInt: 10, |
131 | str: "base 10", | 164 | str: "base 10", |
132 | } | 165 | } |
133 | } | 166 | } |
134 | return { | 167 | return { |
168 | parts: hexMatches, | ||
135 | matcher: matchers.hex, | 169 | matcher: matchers.hex, |
136 | asInt: 16, | 170 | asInt: 16, |
137 | str: "hexadecimal", | 171 | str: "hexadecimal", |