Browse Source

index: add mnemonicToEntropy backwards function

300
Daniel Cousens 10 years ago
parent
commit
40737046ab
  1. 73
      index.js
  2. 14
      test/index.js

73
index.js

@ -1,3 +1,4 @@
var assert = require('assert')
var CryptoJS = require('crypto-js')
var crypto = require('crypto')
var secureRandom = require('secure-random')
@ -9,6 +10,41 @@ function mnemonicToSeedHex(mnemonic, password) {
return CryptoJS.PBKDF2(mnemonic, salt(password), options).toString(CryptoJS.enc.Hex)
}
function mnemonicToEntropy(mnemonic, wordlist) {
wordlist = wordlist || DEFAULT_WORDLIST
var words = mnemonic.split(' ')
assert(words.length % 3 === 0, 'Invalid mnemonic')
var belongToList = words.every(function(word) {
return wordlist.indexOf(word) > -1
})
assert(belongToList, 'Invalid mnemonic')
// convert word indices to 11 bit binary strings
var bits = words.map(function(word) {
var index = wordlist.indexOf(word)
return lpad(index.toString(2), '0', 11)
}).join('')
// split the binary string into ENT/CS
var dividerIndex = Math.floor(bits.length / 33) * 32
var entropy = bits.slice(0, dividerIndex)
var checksum = bits.slice(dividerIndex)
// calculate the checksum and compare
var entropyBytes = entropy.match(/(.{1,8})/g).map(function(bin) {
return parseInt(bin, 2)
})
var entropyBuffer = new Buffer(entropyBytes)
var newChecksum = checksumBits(entropyBuffer)
assert(newChecksum === checksum, 'Invalid mnemonic checksum')
return entropyBuffer.toString('hex')
}
function entropyToMnemonic(entropy, wordlist) {
wordlist = wordlist || DEFAULT_WORDLIST
@ -37,37 +73,13 @@ function generateMnemonic(strength, rng, wordlist) {
}
function validateMnemonic(mnemonic, wordlist) {
wordlist = wordlist || DEFAULT_WORDLIST
var words = mnemonic.split(' ')
if (words.length % 3 !== 0) return false
var belongToList = words.every(function(word) {
return wordlist.indexOf(word) > -1
})
if (!belongToList) return false
// convert word indices to 11 bit binary strings
var bits = words.map(function(word) {
var index = wordlist.indexOf(word)
return lpad(index.toString(2), '0', 11)
}).join('')
// split the binary string into ENT/CS
var dividerIndex = Math.floor(bits.length / 33) * 32
var entropy = bits.slice(0, dividerIndex)
var checksum = bits.slice(dividerIndex)
// calculate the checksum and compare
var entropyBytes = entropy.match(/(.{1,8})/g).map(function(bin) {
return parseInt(bin, 2)
})
var entropyBuffer = new Buffer(entropyBytes)
var newChecksum = checksumBits(entropyBuffer)
try {
mnemonicToEntropy(mnemonic, wordlist)
} catch (e) {
return false
}
return newChecksum === checksum
return true
}
function checksumBits(entropyBuffer) {
@ -103,6 +115,7 @@ function lpad(str, padString, length) {
module.exports = {
mnemonicToSeedHex: mnemonicToSeedHex,
mnemonicToEntropy: mnemonicToEntropy,
entropyToMnemonic: entropyToMnemonic,
generateMnemonic: generateMnemonic,
validateMnemonic: validateMnemonic

14
test/index.js

@ -19,6 +19,20 @@ describe('BIP39', function() {
})
})
describe('mnemonicToEntropy', function() {
vectors.english.forEach(function(v, i) {
it('works for tests vector ' + i, function() {
assert.equal(BIP39.mnemonicToEntropy(v[1]), v[0])
})
})
vectors.custom.forEach(function(v, i) {
it('works for custom test vector ' + i, function() {
assert.equal(BIP39.mnemonicToEntropy(v[1], wordlists.custom), v[0])
})
})
})
describe('entropyToMnemonic', function() {
vectors.english.forEach(function(v, i) {
it('works for tests vector ' + i, function() {

Loading…
Cancel
Save