diff options
author | Kevin Cernekee <cernekee@gmail.com> | 2018-10-28 13:20:33 -0700 |
---|---|---|
committer | Kevin Cernekee <cernekee@gmail.com> | 2018-10-28 15:10:51 -0700 |
commit | 611f76238dedd0418c79a0d918d46d2c92b0149c (patch) | |
tree | 93ca072521fb19c304fe85764cfcb26387f918bd | |
parent | 011533e4bc1d49a6675dedf5bfaabefb7de41088 (diff) | |
download | BIP39-611f76238dedd0418c79a0d918d46d2c92b0149c.tar.gz BIP39-611f76238dedd0418c79a0d918d46d2c92b0149c.tar.zst BIP39-611f76238dedd0418c79a0d918d46d2c92b0149c.zip |
Allow converting mnemonic back to raw entropy value
Currently, this sequence produces an unexpected result:
1) Navigate to bip39-standalone.html
2) Paste a known-good mnemonic into the BIP39 Mnemonic field
3) Select "Show entropy details"
This will erase the BIP39 Mnemonic field and most of the derived
address/key information. It shows an empty Entropy field, and zeroes
for Event Count, Bits Per Event, Raw Entropy Words, Total Bits, etc.
However, it will show valid Word Indexes and BIP39 Seed.
The way to fix it is to convert the mnemonic back into a raw entropy
value and populate it in DOM.entropy, so that everything stays
consistent. This will only happen if the mnemonic is manually entered
by the user, not if phraseChanged() is triggered by hand-editing the
entropy value.
-rw-r--r-- | src/js/index.js | 9 | ||||
-rw-r--r-- | src/js/jsbip39.js | 51 |
2 files changed, 44 insertions, 16 deletions
diff --git a/src/js/index.js b/src/js/index.js index 5d031b2..0c8344f 100644 --- a/src/js/index.js +++ b/src/js/index.js | |||
@@ -232,7 +232,14 @@ | |||
232 | if (phraseChangeTimeoutEvent != null) { | 232 | if (phraseChangeTimeoutEvent != null) { |
233 | clearTimeout(phraseChangeTimeoutEvent); | 233 | clearTimeout(phraseChangeTimeoutEvent); |
234 | } | 234 | } |
235 | phraseChangeTimeoutEvent = setTimeout(phraseChanged, 400); | 235 | phraseChangeTimeoutEvent = setTimeout(function() { |
236 | phraseChanged(); | ||
237 | var entropy = mnemonic.toRawEntropyHex(DOM.phrase.val()); | ||
238 | if (entropy !== null) { | ||
239 | DOM.entropyMnemonicLength.val("raw"); | ||
240 | DOM.entropy.val(entropy); | ||
241 | } | ||
242 | }, 400); | ||
236 | } | 243 | } |
237 | 244 | ||
238 | function phraseChanged() { | 245 | function phraseChanged() { |
diff --git a/src/js/jsbip39.js b/src/js/jsbip39.js index 3230e3b..9a6e7ec 100644 --- a/src/js/jsbip39.js +++ b/src/js/jsbip39.js | |||
@@ -97,22 +97,10 @@ var Mnemonic = function(language) { | |||
97 | } | 97 | } |
98 | 98 | ||
99 | self.check = function(mnemonic) { | 99 | self.check = function(mnemonic) { |
100 | var mnemonic = self.splitWords(mnemonic); | 100 | var b = mnemonicToBinaryString(mnemonic); |
101 | if (mnemonic.length == 0 || mnemonic.length % 3 > 0) { | 101 | if (b === null) { |
102 | return false | 102 | return false; |
103 | } | ||
104 | // idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic) | ||
105 | var idx = []; | ||
106 | for (var i=0; i<mnemonic.length; i++) { | ||
107 | var word = mnemonic[i]; | ||
108 | var wordIndex = wordlist.indexOf(word); | ||
109 | if (wordIndex == -1) { | ||
110 | return false; | ||
111 | } | ||
112 | var binaryIndex = zfill(wordIndex.toString(2), 11); | ||
113 | idx.push(binaryIndex); | ||
114 | } | 103 | } |
115 | var b = idx.join(''); | ||
116 | var l = b.length; | 104 | var l = b.length; |
117 | //d = b[:l / 33 * 32] | 105 | //d = b[:l / 33 * 32] |
118 | //h = b[-l / 33:] | 106 | //h = b[-l / 33:] |
@@ -128,6 +116,20 @@ var Mnemonic = function(language) { | |||
128 | return h == nh; | 116 | return h == nh; |
129 | } | 117 | } |
130 | 118 | ||
119 | self.toRawEntropyHex = function(mnemonic) { | ||
120 | var b = mnemonicToBinaryString(mnemonic); | ||
121 | if (b === null) | ||
122 | return null; | ||
123 | var d = b.substring(0, b.length / 33 * 32); | ||
124 | var nd = binaryStringToWordArray(d); | ||
125 | |||
126 | var h = ""; | ||
127 | for (var i=0; i<nd.length; i++) { | ||
128 | h += ('0000000' + nd[i].toString(16)).slice(-8); | ||
129 | } | ||
130 | return h; | ||
131 | } | ||
132 | |||
131 | self.toSeed = function(mnemonic, passphrase) { | 133 | self.toSeed = function(mnemonic, passphrase) { |
132 | passphrase = passphrase || ''; | 134 | passphrase = passphrase || ''; |
133 | mnemonic = self.joinWords(self.splitWords(mnemonic)); // removes duplicate blanks | 135 | mnemonic = self.joinWords(self.splitWords(mnemonic)); // removes duplicate blanks |
@@ -200,6 +202,25 @@ var Mnemonic = function(language) { | |||
200 | return a; | 202 | return a; |
201 | } | 203 | } |
202 | 204 | ||
205 | function mnemonicToBinaryString(mnemonic) { | ||
206 | var mnemonic = self.splitWords(mnemonic); | ||
207 | if (mnemonic.length == 0 || mnemonic.length % 3 > 0) { | ||
208 | return null; | ||
209 | } | ||
210 | // idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic) | ||
211 | var idx = []; | ||
212 | for (var i=0; i<mnemonic.length; i++) { | ||
213 | var word = mnemonic[i]; | ||
214 | var wordIndex = wordlist.indexOf(word); | ||
215 | if (wordIndex == -1) { | ||
216 | return null; | ||
217 | } | ||
218 | var binaryIndex = zfill(wordIndex.toString(2), 11); | ||
219 | idx.push(binaryIndex); | ||
220 | } | ||
221 | return idx.join(''); | ||
222 | } | ||
223 | |||
203 | // Pad a numeric string on the left with zero digits until the given width | 224 | // Pad a numeric string on the left with zero digits until the given width |
204 | // is reached. | 225 | // is reached. |
205 | // Note this differs to the python implementation because it does not | 226 | // Note this differs to the python implementation because it does not |