From e66c8a9b5aade1c6b19c58e5366f777fde3f373f Mon Sep 17 00:00:00 2001 From: Ian Coleman Date: Mon, 29 Sep 2014 16:11:09 +1000 Subject: jsbip39 updated and asmcrypto replaced with sjcl --- src/js/jsbip39.js | 79 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 23 deletions(-) (limited to 'src/js/jsbip39.js') 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 @@ /* * Javascript port from python by Ian Coleman * - * Includes code from asmCrypto - * https://github.com/tresorit/asmcrypto.js + * Requires code from sjcl + * https://github.com/bitwiseshiftleft/sjcl */ var Mnemonic = function(language) { @@ -34,6 +34,13 @@ var Mnemonic = function(language) { var self = this; var wordlist = []; + var hmacSHA512 = function(key) { + var hasher = new sjcl.misc.hmac(key, sjcl.hash.sha512); + this.encrypt = function() { + return hasher.encrypt.apply(hasher, arguments); + }; + }; + function init() { wordlist = WORDLISTS[language]; if (wordlist.length != RADIX) { @@ -57,14 +64,15 @@ var Mnemonic = function(language) { return self.toMnemonic(data); } - self.toMnemonic = function(data) { - if (data.length % 4 > 0) { - throw 'Data length in bits should be divisible by 32, but it is not (' + data.length + ' bytes = ' + data.length*8 + ' bits).' + self.toMnemonic = function(byteArray) { + if (byteArray.length % 4 > 0) { + throw 'Data length in bits should be divisible by 32, but it is not (' + byteArray.length + ' bytes = ' + byteArray.length*8 + ' bits).' } //h = hashlib.sha256(data).hexdigest() - var uintArray = new Uint8Array(data); - var h = asmCrypto.SHA256.bytes(uintArray); + var data = byteArrayToWordArray(byteArray); + var hash = sjcl.hash.sha256.hash(data); + var h = sjcl.codec.hex.fromBits(hash); // b is a binary string, eg '00111010101100...' //b = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) + \ @@ -73,9 +81,9 @@ var Mnemonic = function(language) { // a = bin(int(binascii.hexlify(data), 16))[2:].zfill(len(data) * 8) // c = bin(int(h, 16))[2:].zfill(256) // d = c[:len(data) * 8 / 32] - var a = byteArrayToBinaryString(data); - var c = byteArrayToBinaryString(h); - var d = c.substring(0, data.length * 8 / 32); + var a = byteArrayToBinaryString(byteArray); + var c = zfill(hexStringToBinaryString(h), 256); + var d = c.substring(0, byteArray.length * 8 / 32); // b = line1 + line2 var b = a + d; @@ -111,10 +119,11 @@ var Mnemonic = function(language) { var d = b.substring(0, l / 33 * 32); var h = b.substring(l - l / 33, l); //nd = binascii.unhexlify(hex(int(d, 2))[2:].rstrip('L').zfill(l / 33 * 8)) + var nd = binaryStringToWordArray(d); //nh = bin(int(hashlib.sha256(nd).hexdigest(), 16))[2:].zfill(256)[:l / 33] - var nd = binaryStringToByteArray(d); - var ndHash = asmCrypto.SHA256.bytes(nd); - var ndBstr = zfill(byteArrayToBinaryString(ndHash), 256); + var ndHash = sjcl.hash.sha256.hash(nd); + var ndHex = sjcl.codec.hex.fromBits(ndHash); + var ndBstr = zfill(hexStringToBinaryString(ndHex), 256); var nh = ndBstr.substring(0,l/33); return h == nh; } @@ -124,8 +133,11 @@ var Mnemonic = function(language) { mnemonic = self.normalizeString(mnemonic) passphrase = self.normalizeString(passphrase) passphrase = "mnemonic" + passphrase; - //return PBKDF2(mnemonic, 'mnemonic' + passphrase, iterations=PBKDF2_ROUNDS, macmodule=hmac, digestmodule=hashlib.sha512).read(64) - return asmCrypto.PBKDF2_HMAC_SHA512.hex(mnemonic, passphrase, PBKDF2_ROUNDS, 512/8); + var mnemonicBits = sjcl.codec.utf8String.toBits(mnemonic); + var passphraseBits = sjcl.codec.utf8String.toBits(passphrase); + var result = sjcl.misc.pbkdf2(mnemonicBits, passphraseBits, PBKDF2_ROUNDS, 512, hmacSHA512); + var hashHex = sjcl.codec.hex.fromBits(result); + return hashHex; } self.normalizeString = function(str) { @@ -139,6 +151,19 @@ var Mnemonic = function(language) { } } + function byteArrayToWordArray(data) { + var a = []; + for (var i=0; i