aboutsummaryrefslogtreecommitdiff
path: root/src/js/jsbip39.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/js/jsbip39.js')
-rw-r--r--src/js/jsbip39.js79
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
29var Mnemonic = function(language) { 29var 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