From 068f6d99122cd845c6dab24a2449316a1a2ce271 Mon Sep 17 00:00:00 2001 From: Wei Lu Date: Tue, 11 Mar 2014 16:01:14 +0800 Subject: [PATCH] implement entropyToMnemonic --- index.js | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/index.js | 12 +++++++++-- 2 files changed, 65 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 72085d8..46d7adf 100644 --- a/index.js +++ b/index.js @@ -13,6 +13,21 @@ BIP39.prototype.mnemonicToSeed = function(mnemonic, password){ return Crypto.PBKDF2(mnemonic, salt(password), options).toString(Crypto.enc.Hex) } +BIP39.prototype.entropyToMnemonic = function(entropy){ + var entropyBytes = hexToBytes(entropy) + var bits = bytesToBinary(entropyBytes) + + var hash = Crypto.SHA256(bytesToWordArray(entropyBytes)) + var checksumBits = bytesToBinary(wordsToBytes(hash.words)) + var checksum = checksumBits.substr(0, bits.length / 32) + + var chunks = (bits + checksum).match(/(.{1,11})/g) + return chunks.map(function(binary){ + var index = parseInt(binary, 2) + return this.wordlist[index] + }, this).join(' ') +} + function salt(password) { return encode_utf8('mnemonic' + (password || '')) } @@ -20,3 +35,43 @@ function salt(password) { function encode_utf8(s){ return unescape(encodeURIComponent(s)) } + +//=========== helper methods from bitcoinjs-lib ======== + +function hexToBytes(hex) { + return hex.match(/../g).map(function(x) { + return parseInt(x,16) + }); +} + +function bytesToBinary(bytes) { + return bytes.map(function(x) { + return lpad(x.toString(2), '0', 8) + }).join(''); +} + +function bytesToWordArray(bytes) { + return new Crypto.lib.WordArray.init(bytesToWords(bytes), bytes.length) +} + +function bytesToWords(bytes) { + var words = []; + for (var i = 0, b = 0; i < bytes.length; i++, b += 8) { + words[b >>> 5] |= bytes[i] << (24 - b % 32); + } + return words; +} + +function wordsToBytes(words) { + var bytes = []; + for (var b = 0; b < words.length * 32; b += 8) { + bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF); + } + return bytes; +} + +function lpad(str, padString, length) { + while (str.length < length) str = padString + str; + return str; +} + diff --git a/test/index.js b/test/index.js index f56020a..4046fa5 100644 --- a/test/index.js +++ b/test/index.js @@ -3,9 +3,10 @@ var BIP39 = require('../index.js') var wordlist = require('../Wordlists/en.json') var assert = require('assert') +var bip39 = new BIP39() + describe('constructor', function(){ it('defaults language to english', function(){ - var bip39 = new BIP39() assert.deepEqual(bip39.wordlist, wordlist) }) }) @@ -13,8 +14,15 @@ describe('constructor', function(){ describe('mnemonicToSeed', function(){ vectors.forEach(function(v, i){ it('works for tests vector ' + i, function(){ - var bip39 = new BIP39() assert.equal(bip39.mnemonicToSeed(v[1], 'TREZOR'), v[2]) }) }) }) + +describe('entropyToMnemonic', function(){ + vectors.forEach(function(v, i){ + it('works for tests vector ' + i, function(){ + assert.equal(bip39.entropyToMnemonic(v[0]), v[1]) + }) + }) +})