/* * Copyright (c) 2013 Pavol Rusnak * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is furnished to do * so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* * Javascript port from python by Ian Coleman * * Requires code from sjcl * https://github.com/bitwiseshiftleft/sjcl */ var Mnemonic = function(language) { var PBKDF2_ROUNDS = 2048; var RADIX = 2048; 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) { err = 'Wordlist should contain ' + RADIX + ' words, but it contains ' + wordlist.length + ' words.'; throw err; } } self.generate = function(strength) { strength = strength || 128; var r = strength % 32; if (r > 0) { throw 'Strength should be divisible by 32, but it is not (' + r + ').'; } var hasStrongCrypto = 'crypto' in window && window['crypto'] !== null; if (!hasStrongCrypto) { throw 'Mnemonic should be generated with strong randomness, but crypto.getRandomValues is unavailable'; } var buffer = new Uint8Array(strength / 8); var data = crypto.getRandomValues(buffer); return self.toMnemonic(data); } 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 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) + \ // bin(int(h, 16))[2:].zfill(256)[:len(data) * 8 / 32] // // 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(byteArray); var c = zfill(hexStringToBinaryString(h), 256); var d = c.substring(0, byteArray.length * 8 / 32); // b = line1 + line2 var b = a + d; var result = []; var blen = b.length / 11; for (var i=0; i 0) { return false } // idx = map(lambda x: bin(self.wordlist.index(x))[2:].zfill(11), mnemonic) var idx = []; for (var i=0; i