diff options
author | Ian Coleman <coleman.ian@gmail.com> | 2014-09-29 16:11:09 +1000 |
---|---|---|
committer | Ian Coleman <coleman.ian@gmail.com> | 2014-09-29 16:11:09 +1000 |
commit | e66c8a9b5aade1c6b19c58e5366f777fde3f373f (patch) | |
tree | c525a3e6cfeb004df3c2d16ff6a526951b13d9c7 /src/js/jsbip39.js | |
parent | 3af2954aeee7e849fcfa3c61b016793a59ab585e (diff) | |
download | BIP39-e66c8a9b5aade1c6b19c58e5366f777fde3f373f.tar.gz BIP39-e66c8a9b5aade1c6b19c58e5366f777fde3f373f.tar.zst BIP39-e66c8a9b5aade1c6b19c58e5366f777fde3f373f.zip |
jsbip39 updated and asmcrypto replaced with sjcl
Diffstat (limited to 'src/js/jsbip39.js')
-rw-r--r-- | src/js/jsbip39.js | 79 |
1 files changed, 56 insertions, 23 deletions
diff --git a/src/js/jsbip39.js b/src/js/jsbip39.js index 0b88fef..257d8d7 100644 --- a/src/js/jsbip39.js +++ b/src/js/jsbip39.js | |||
@@ -22,8 +22,8 @@ | |||
22 | /* | 22 | /* |
23 | * Javascript port from python by Ian Coleman | 23 | * Javascript port from python by Ian Coleman |
24 | * | 24 | * |
25 | * Includes code from asmCrypto | 25 | * Requires code from sjcl |
26 | * https://github.com/tresorit/asmcrypto.js | 26 | * https://github.com/bitwiseshiftleft/sjcl |
27 | */ | 27 | */ |
28 | 28 | ||
29 | var Mnemonic = function(language) { | 29 | var Mnemonic = function(language) { |
@@ -34,6 +34,13 @@ var Mnemonic = function(language) { | |||
34 | var self = this; | 34 | var self = this; |
35 | var wordlist = []; | 35 | var wordlist = []; |
36 | 36 | ||
37 | var hmacSHA512 = function(key) { | ||
38 | var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512); | ||
39 | this.encrypt = function() { | ||
40 | return hasher.encrypt.apply(hasher, arguments); | ||
41 | }; | ||
42 | }; | ||
43 | |||
37 | function init() { | 44 | function init() { |
38 | wordlist = WORDLISTS[language]; | 45 | wordlist = WORDLISTS[language]; |
39 | if (wordlist.length != RADIX) { | 46 | if (wordlist.length != RADIX) { |
@@ -57,14 +64,15 @@ var Mnemonic = function(language) { | |||
57 | return self.toMnemonic(data); | 64 | return self.toMnemonic(data); |
58 | } | 65 | } |
59 | 66 | ||
60 | self.toMnemonic = function(data) { | 67 | self.toMnemonic = function(byteArray) { |
61 | if (data.length % 4 > 0) { | 68 | if (byteArray.length % 4 > 0) { |
62 | throw 'Data length in bits should be divisible by 32, but it is not (' + data.length + ' bytes = ' + data.length*8 + ' bits).' | 69 | throw 'Data length in bits should be divisible by 32, but it is not (' + byteArray.length + ' bytes = ' + byteArray.length*8 + ' bits).' |
63 | } | 70 | } |
64 | 71 | ||
65 | //h = hashlib.sha256(data).hexdigest() | 72 | //h = hashlib.sha256(data).hexdigest() |
66 | var uintArray = new Uint8Array(data); | 73 | var data = byteArrayToWordArray(byteArray); |
67 | var h = asmCrypto.SHA256.bytes(uintArray); | 74 | var hash = sjcl.hash.sha256.hash(data); |
75 | var h = sjcl.codec.hex.fromBits(hash); | ||
68 | 76 | ||
69 | // b is a binary string, eg '00111010101100...' | 77 | // b is a binary string, eg '00111010101100...' |
70 | //b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \ | 78 | //b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \ |
@@ -73,9 +81,9 @@ var Mnemonic = function(language) { | |||
73 | // a = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) | 81 | // a = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) |
74 | // c = bin(int(h, 16))[2:].zfill(256) | 82 | // c = bin(int(h, 16))[2:].zfill(256) |
75 | // d = c[:len(data) * 8 / 32] | 83 | // d = c[:len(data) * 8 / 32] |
76 | var a = byteArrayToBinaryString(data); | 84 | var a = byteArrayToBinaryString(byteArray); |
77 | var c = byteArrayToBinaryString(h); | 85 | var c = zfill(hexStringToBinaryString(h), 256); |
78 | var d = c.substring(0, data.length * 8 / 32); | 86 | var d = c.substring(0, byteArray.length * 8 / 32); |
79 | // b = line1 + line2 | 87 | // b = line1 + line2 |
80 | var b = a + d; | 88 | var b = a + d; |
81 | 89 | ||
@@ -111,10 +119,11 @@ var Mnemonic = function(language) { | |||
111 | var d = b.substring(0, l / 33 * 32); | 119 | var d = b.substring(0, l / 33 * 32); |
112 | var h = b.substring(l - l / 33, l); | 120 | var h = b.substring(l - l / 33, l); |
113 | //nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip('L').zfill(l / 33 * 8)) | 121 | //nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip('L').zfill(l / 33 * 8)) |
122 | var nd = binaryStringToWordArray(d); | ||
114 | //nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l / 33] | 123 | //nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l / 33] |
115 | var nd = binaryStringToByteArray(d); | 124 | var ndHash = sjcl.hash.sha256.hash(nd); |
116 | var ndHash = asmCrypto.SHA256.bytes(nd); | 125 | var ndHex = sjcl.codec.hex.fromBits(ndHash); |
117 | var ndBstr = zfill(byteArrayToBinaryString(ndHash), 256); | 126 | var ndBstr = zfill(hexStringToBinaryString(ndHex), 256); |
118 | var nh = ndBstr.substring(0,l/33); | 127 | var nh = ndBstr.substring(0,l/33); |
119 | return h == nh; | 128 | return h == nh; |
120 | } | 129 | } |
@@ -124,8 +133,11 @@ var Mnemonic = function(language) { | |||
124 | mnemonic = self.normalizeString(mnemonic) | 133 | mnemonic = self.normalizeString(mnemonic) |
125 | passphrase = self.normalizeString(passphrase) | 134 | passphrase = self.normalizeString(passphrase) |
126 | passphrase = "mnemonic" + passphrase; | 135 | passphrase = "mnemonic" + passphrase; |
127 | //return PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations=PBKDF2_ROUNDS, macmodule=hmac, digestmodule=hashlib.sha512).read(64) | 136 | var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonic); |
128 | return asmCrypto.PBKDF2_HMAC_SHA512.hex(mnemonic, passphrase, PBKDF2_ROUNDS, 512/8); | 137 | var passphraseBits = sjcl.codec.utf8String.toBits(passphrase); |
138 | var result = sjcl.misc.pbkdf2(mnemonicBits, passphraseBits, PBKDF2_ROUNDS, 512, hmacSHA512); | ||
139 | var hashHex = sjcl.codec.hex.fromBits(result); | ||
140 | return hashHex; | ||
129 | } | 141 | } |
130 | 142 | ||
131 | self.normalizeString = function(str) { | 143 | self.normalizeString = function(str) { |
@@ -139,6 +151,19 @@ var Mnemonic = function(language) { | |||
139 | } | 151 | } |
140 | } | 152 | } |
141 | 153 | ||
154 | function byteArrayToWordArray(data) { | ||
155 | var a = []; | ||
156 | for (var i=0; i<data.length/4; i++) { | ||
157 | v = 0; | ||
158 | v += data[i*4 + 0] << 8 * 3; | ||
159 | v += data[i*4 + 1] << 8 * 2; | ||
160 | v += data[i*4 + 2] << 8 * 1; | ||
161 | v += data[i*4 + 3] << 8 * 0; | ||
162 | a.push(v); | ||
163 | } | ||
164 | return a; | ||
165 | } | ||
166 | |||
142 | function byteArrayToBinaryString(data) { | 167 | function byteArrayToBinaryString(data) { |
143 | var bin = ""; | 168 | var bin = ""; |
144 | for (var i=0; i<data.length; i++) { | 169 | for (var i=0; i<data.length; i++) { |
@@ -147,16 +172,24 @@ var Mnemonic = function(language) { | |||
147 | return bin; | 172 | return bin; |
148 | } | 173 | } |
149 | 174 | ||
150 | function binaryStringToByteArray(str) { | 175 | function hexStringToBinaryString(hexString) { |
151 | var arrayLen = str.length / 8; | 176 | binaryString = ""; |
152 | var array = new Uint8Array(arrayLen); | 177 | for (var i=0; i<hexString.length; i++) { |
153 | for (var i=0; i<arrayLen; i++) { | 178 | binaryString += zfill(parseInt(hexString[i], 16).toString(2),4); |
154 | var valueStr = str.substring(0,8); | 179 | } |
180 | return binaryString; | ||
181 | } | ||
182 | |||
183 | function binaryStringToWordArray(binary) { | ||
184 | var aLen = binary.length / 32; | ||
185 | var a = []; | ||
186 | for (var i=0; i<aLen; i++) { | ||
187 | var valueStr = binary.substring(0,32); | ||
155 | var value = parseInt(valueStr, 2); | 188 | var value = parseInt(valueStr, 2); |
156 | array[i] = value; | 189 | a.push(value); |
157 | str = str.slice(8); | 190 | binary = binary.slice(32); |
158 | } | 191 | } |
159 | return array; | 192 | return a; |
160 | } | 193 | } |
161 | 194 | ||
162 | // Pad a numeric string on the left with zero digits until the given width | 195 | // Pad a numeric string on the left with zero digits until the given width |