Skip to content

Commit

Permalink
enforce 128-256 size ENT, multiple of 4
Browse files Browse the repository at this point in the history
  • Loading branch information
dcousens committed May 12, 2017
1 parent 950ce92 commit 5bf0b64
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 19 deletions.
33 changes: 19 additions & 14 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ var JAPANESE_WORDLIST = require('./wordlists/japanese.json')
var SPANISH_WORDLIST = require('./wordlists/spanish.json')
var DEFAULT_WORDLIST = ENGLISH_WORDLIST

var INVALID_MNEMONIC = 'Invalid mnemonic'
var INVALID_ENTROPY = 'Invalid entropy'

function salt (password) {
return 'mnemonic' + (password || '')
}
Expand All @@ -36,21 +39,19 @@ function mnemonicToEntropy (mnemonic, wordlist) {
wordlist = wordlist || DEFAULT_WORDLIST

var words = unorm.nfkd(mnemonic).split(' ')
if (words.length % 3 !== 0) throw new Error('Invalid mnemonic')
if (words.length % 3 !== 0) throw new Error(INVALID_MNEMONIC)
if (words.some(function (word) {
return wordlist.indexOf(word) === -1
})) throw new Error('Invalid mnemonic')
})) throw new Error(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('')

// max entropy is 1024; (1024×8)+((1024×8)÷32) = 8448
if (bits.length > 8448) {
throw new Error('Invalid mnemonic')
}
if (bits.length < 128) throw new Error(INVALID_MNEMONIC)
if (bits.length > 264) throw new Error(INVALID_MNEMONIC)

// split the binary string into ENT/CS
var dividerIndex = Math.floor(bits.length / 33) * 32
Expand All @@ -61,25 +62,28 @@ function mnemonicToEntropy (mnemonic, wordlist) {
var entropyBytes = entropy.match(/(.{1,8})/g).map(function (bin) {
return parseInt(bin, 2)
})
if (entropy.length % 4 !== 0) throw new TypeError(INVALID_ENTROPY)
var entropyBuffer = new Buffer(entropyBytes)
var newChecksum = checksumBits(entropyBuffer)

var newChecksum = checksumBits(entropyBuffer)
if (newChecksum !== checksum) throw new Error('Invalid mnemonic checksum')

return entropyBuffer.toString('hex')
}

function entropyToMnemonic (entropy, wordlist) {
function entropyToMnemonic (entropyHex, wordlist) {
wordlist = wordlist || DEFAULT_WORDLIST

var entropyBuffer = new Buffer(entropy, 'hex')
// 128 <= ENT <= 256
if (entropyHex.length < 32) throw new Error(INVALID_ENTROPY)
if (entropyHex.length > 64) throw new Error(INVALID_ENTROPY)

if (entropyBuffer.length === 0 || entropyBuffer.length > 1024 || entropyBuffer.length % 4 !== 0) {
throw new Error('Invalid entropy')
}
// multiple of 4
if (entropyHex.length % 8 !== 0) throw new Error(INVALID_ENTROPY)

var entropyBits = bytesToBinary([].slice.call(entropyBuffer))
var checksum = checksumBits(entropyBuffer)
var entropy = new Buffer(entropyHex, 'hex')
var entropyBits = bytesToBinary([].slice.call(entropy))
var checksum = checksumBits(entropy)

var bits = entropyBits + checksum
var chunks = bits.match(/(.{1,11})/g)
Expand All @@ -95,6 +99,7 @@ function entropyToMnemonic (entropy, wordlist) {

function generateMnemonic (strength, rng, wordlist) {
strength = strength || 128
if (strength % 32 !== 0) throw new TypeError(INVALID_ENTROPY)
rng = rng || randomBytes

var hex = rng(strength / 8).toString('hex')
Expand Down
10 changes: 5 additions & 5 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,17 @@ test('UTF8 passwords', function (t) {
})

test('generateMnemonic can vary entropy length', function (t) {
var words = bip39.generateMnemonic(96).split(' ')
var words = bip39.generateMnemonic(160).split(' ')

t.plan(1)
t.equal(words.length, 9, 'can vary generated entropy bit length')
t.equal(words.length, 15, 'can vary generated entropy bit length')
})

test('generateMnemonic only requests the exact amount of data from an RNG', function (t) {
test('generateMnemonic requests the exact amount of data from an RNG', function (t) {
t.plan(1)

bip39.generateMnemonic(96, function (size) {
t.equal(size, 96 / 8)
bip39.generateMnemonic(160, function (size) {
t.equal(size, 160 / 8)
return new Buffer(size)
})
})
Expand Down

0 comments on commit 5bf0b64

Please sign in to comment.