Emilio Almansi
7 years ago
36 changed files with 1434 additions and 23 deletions
File diff suppressed because one or more lines are too long
@ -0,0 +1,3 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = require('./mnemonic'); |
@ -0,0 +1,289 @@ |
|||
'use strict'; |
|||
|
|||
var _ = require('lodash'); |
|||
var $ = require('../util/preconditions'); |
|||
var BN = require('../crypto/bn'); |
|||
var errors = require('../errors'); |
|||
var Hash = require('../crypto/hash'); |
|||
var HDPrivateKey = require('../hdprivatekey'); |
|||
var Random = require('../crypto/random'); |
|||
var unorm = require('unorm'); |
|||
|
|||
/** |
|||
* This is an immutable class that represents a BIP39 Mnemonic code. |
|||
* See BIP39 specification for more info: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
|||
* A Mnemonic code is a a group of easy to remember words used for the generation |
|||
* of deterministic wallets. A Mnemonic can be used to generate a seed using |
|||
* an optional passphrase, for later generate a HDPrivateKey. |
|||
* |
|||
* @example |
|||
* // generate a random mnemonic
|
|||
* var mnemonic = new Mnemonic(); |
|||
* var phrase = mnemonic.phrase; |
|||
* |
|||
* // use a different language
|
|||
* var mnemonic = new Mnemonic(Mnemonic.Words.SPANISH); |
|||
* var xprivkey = mnemonic.toHDPrivateKey(); |
|||
* |
|||
* @param {*=} data - a seed, phrase, or entropy to initialize (can be skipped) |
|||
* @param {Array=} wordlist - the wordlist to generate mnemonics from |
|||
* @returns {Mnemonic} A new instance of Mnemonic |
|||
* @constructor |
|||
*/ |
|||
var Mnemonic = function Mnemonic(data, wordlist) { |
|||
if (!(this instanceof Mnemonic)) { |
|||
return new Mnemonic(data, wordlist); |
|||
} |
|||
|
|||
if (_.isArray(data)) { |
|||
wordlist = data; |
|||
data = null; |
|||
} |
|||
|
|||
// handle data overloading
|
|||
var ent, phrase, seed; |
|||
if (Buffer.isBuffer(data)) { |
|||
seed = data; |
|||
} else if (_.isString(data)) { |
|||
phrase = unorm.nfkd(data); |
|||
} else if (_.isNumber(data)) { |
|||
ent = data; |
|||
} else if (data) { |
|||
throw new errors.InvalidArgument('data', 'Must be a Buffer, a string or an integer'); |
|||
} |
|||
ent = ent || 128; |
|||
|
|||
// check and detect wordlist
|
|||
wordlist = wordlist || Mnemonic._getDictionary(phrase); |
|||
if (phrase && !wordlist) { |
|||
throw new errors.UnknownWordlist(phrase); |
|||
} |
|||
wordlist = wordlist || Mnemonic.Words.ENGLISH; |
|||
|
|||
if (seed) { |
|||
phrase = Mnemonic._entropy2mnemonic(seed, wordlist); |
|||
} |
|||
|
|||
// validate phrase and ent
|
|||
if (phrase && !Mnemonic.isValid(phrase, wordlist)) { |
|||
throw new errors.InvalidMnemonic(phrase); |
|||
} |
|||
if (ent % 32 !== 0 || ent < 128) { |
|||
throw new errors.InvalidArgument('ENT', 'Values must be ENT > 128 and ENT % 32 == 0'); |
|||
} |
|||
|
|||
phrase = phrase || Mnemonic._mnemonic(ent, wordlist); |
|||
|
|||
Object.defineProperty(this, 'wordlist', { |
|||
configurable: false, |
|||
value: wordlist |
|||
}); |
|||
|
|||
Object.defineProperty(this, 'phrase', { |
|||
configurable: false, |
|||
value: phrase |
|||
}); |
|||
}; |
|||
|
|||
Mnemonic.Words = require('./words'); |
|||
|
|||
/** |
|||
* Will return a boolean if the mnemonic is valid |
|||
* |
|||
* @example |
|||
* |
|||
* var valid = Mnemonic.isValid('lab rescue lunch elbow recall phrase perfect donkey biology guess moment husband'); |
|||
* // true
|
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @param {String} [wordlist] - The wordlist used |
|||
* @returns {boolean} |
|||
*/ |
|||
Mnemonic.isValid = function (mnemonic, wordlist) { |
|||
mnemonic = unorm.nfkd(mnemonic); |
|||
wordlist = wordlist || Mnemonic._getDictionary(mnemonic); |
|||
|
|||
if (!wordlist) { |
|||
return false; |
|||
} |
|||
|
|||
var words = mnemonic.split(' '); |
|||
var bin = ''; |
|||
for (var i = 0; i < words.length; i++) { |
|||
var ind = wordlist.indexOf(words[i]); |
|||
if (ind < 0) return false; |
|||
bin = bin + ('00000000000' + ind.toString(2)).slice(-11); |
|||
} |
|||
|
|||
var cs = bin.length / 33; |
|||
var hash_bits = bin.slice(-cs); |
|||
var nonhash_bits = bin.slice(0, bin.length - cs); |
|||
var buf = new Buffer(nonhash_bits.length / 8); |
|||
for (i = 0; i < nonhash_bits.length / 8; i++) { |
|||
buf.writeUInt8(parseInt(bin.slice(i * 8, (i + 1) * 8), 2), i); |
|||
} |
|||
var expected_hash_bits = Mnemonic._entropyChecksum(buf); |
|||
return expected_hash_bits === hash_bits; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to check if a mnemonic belongs to a wordlist. |
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @param {String} wordlist - The wordlist |
|||
* @returns {boolean} |
|||
*/ |
|||
Mnemonic._belongsToWordlist = function (mnemonic, wordlist) { |
|||
var words = unorm.nfkd(mnemonic).split(' '); |
|||
for (var i = 0; i < words.length; i++) { |
|||
var ind = wordlist.indexOf(words[i]); |
|||
if (ind < 0) return false; |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to detect the wordlist used to generate the mnemonic. |
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @returns {Array} the wordlist or null |
|||
*/ |
|||
Mnemonic._getDictionary = function (mnemonic) { |
|||
if (!mnemonic) return null; |
|||
|
|||
var dicts = Object.keys(Mnemonic.Words); |
|||
for (var i = 0; i < dicts.length; i++) { |
|||
var key = dicts[i]; |
|||
if (Mnemonic._belongsToWordlist(mnemonic, Mnemonic.Words[key])) { |
|||
return Mnemonic.Words[key]; |
|||
} |
|||
} |
|||
return null; |
|||
}; |
|||
|
|||
/** |
|||
* Will generate a seed based on the mnemonic and optional passphrase. |
|||
* |
|||
* @param {String} [passphrase] |
|||
* @returns {Buffer} |
|||
*/ |
|||
Mnemonic.prototype.toSeed = function (passphrase) { |
|||
passphrase = passphrase || ''; |
|||
return Mnemonic.pbkdf2(unorm.nfkd(this.phrase), unorm.nfkd('mnemonic' + passphrase), 2048, 64); |
|||
}; |
|||
|
|||
/** |
|||
* Will generate a Mnemonic object based on a seed. |
|||
* |
|||
* @param {Buffer} [seed] |
|||
* @param {string} [wordlist] |
|||
* @returns {Mnemonic} |
|||
*/ |
|||
Mnemonic.fromSeed = function (seed, wordlist) { |
|||
$.checkArgument(Buffer.isBuffer(seed), 'seed must be a Buffer.'); |
|||
$.checkArgument(_.isArray(wordlist) || _.isString(wordlist), 'wordlist must be a string or an array.'); |
|||
return new Mnemonic(seed, wordlist); |
|||
}; |
|||
|
|||
/** |
|||
* |
|||
* Generates a HD Private Key from a Mnemonic. |
|||
* Optionally receive a passphrase and bitcoin network. |
|||
* |
|||
* @param {String=} [passphrase] |
|||
* @param {Network|String|number=} [network] - The network: 'livenet' or 'testnet' |
|||
* @returns {HDPrivateKey} |
|||
*/ |
|||
Mnemonic.prototype.toHDPrivateKey = function (passphrase, network) { |
|||
var seed = this.toSeed(passphrase); |
|||
return HDPrivateKey.fromSeed(seed, network); |
|||
}; |
|||
|
|||
/** |
|||
* Will return a the string representation of the mnemonic |
|||
* |
|||
* @returns {String} Mnemonic |
|||
*/ |
|||
Mnemonic.prototype.toString = function () { |
|||
return this.phrase; |
|||
}; |
|||
|
|||
/** |
|||
* Will return a string formatted for the console |
|||
* |
|||
* @returns {String} Mnemonic |
|||
*/ |
|||
Mnemonic.prototype.inspect = function () { |
|||
return '<Mnemonic: ' + this.toString() + ' >'; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to generate a random mnemonic |
|||
* |
|||
* @param {Number} ENT - Entropy size, defaults to 128 |
|||
* @param {Array} wordlist - Array of words to generate the mnemonic |
|||
* @returns {String} Mnemonic string |
|||
*/ |
|||
Mnemonic._mnemonic = function (ENT, wordlist) { |
|||
var buf = Random.getRandomBuffer(ENT / 8); |
|||
return Mnemonic._entropy2mnemonic(buf, wordlist); |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to generate mnemonic based on entropy |
|||
* |
|||
* @param {Number} entropy - Entropy buffer |
|||
* @param {Array} wordlist - Array of words to generate the mnemonic |
|||
* @returns {String} Mnemonic string |
|||
*/ |
|||
Mnemonic._entropy2mnemonic = function (entropy, wordlist) { |
|||
var bin = ''; |
|||
for (var i = 0; i < entropy.length; i++) { |
|||
bin = bin + ('00000000' + entropy[i].toString(2)).slice(-8); |
|||
} |
|||
|
|||
bin = bin + Mnemonic._entropyChecksum(entropy); |
|||
if (bin.length % 11 !== 0) { |
|||
throw new errors.InvalidEntropy(bin); |
|||
} |
|||
var mnemonic = []; |
|||
for (i = 0; i < bin.length / 11; i++) { |
|||
var wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2); |
|||
mnemonic.push(wordlist[wi]); |
|||
} |
|||
var ret; |
|||
if (wordlist === Mnemonic.Words.JAPANESE) { |
|||
ret = mnemonic.join('\u3000'); |
|||
} else { |
|||
ret = mnemonic.join(' '); |
|||
} |
|||
return ret; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to create checksum of entropy |
|||
* |
|||
* @param entropy |
|||
* @returns {string} Checksum of entropy length / 32 |
|||
* @private |
|||
*/ |
|||
Mnemonic._entropyChecksum = function (entropy) { |
|||
var hash = Hash.sha256(entropy); |
|||
var bits = entropy.length * 8; |
|||
var cs = bits / 32; |
|||
|
|||
var hashbits = new BN(hash.toString('hex'), 16).toString(2); |
|||
|
|||
// zero pad the hash bits
|
|||
while (hashbits.length % 256 !== 0) { |
|||
hashbits = '0' + hashbits; |
|||
} |
|||
|
|||
var checksum = hashbits.slice(0, cs); |
|||
|
|||
return checksum; |
|||
}; |
|||
|
|||
Mnemonic.pbkdf2 = require('./pbkdf2'); |
|||
|
|||
module.exports = Mnemonic; |
@ -0,0 +1,71 @@ |
|||
'use strict'; |
|||
|
|||
var crypto = require('crypto'); |
|||
|
|||
/** |
|||
* PDKBF2 |
|||
* Credit to: https://github.com/stayradiated/pbkdf2-sha512
|
|||
* Copyright (c) 2014, JP Richardson Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved |
|||
*/ |
|||
function pbkdf2(key, salt, iterations, dkLen) { |
|||
/* jshint maxstatements: 31 */ |
|||
/* jshint maxcomplexity: 9 */ |
|||
|
|||
var hLen = 64; //SHA512 Mac length
|
|||
if (dkLen > (Math.pow(2, 32) - 1) * hLen) { |
|||
throw Error('Requested key length too long'); |
|||
} |
|||
|
|||
if (typeof key !== 'string' && !Buffer.isBuffer(key)) { |
|||
throw new TypeError('key must a string or Buffer'); |
|||
} |
|||
|
|||
if (typeof salt !== 'string' && !Buffer.isBuffer(salt)) { |
|||
throw new TypeError('salt must a string or Buffer'); |
|||
} |
|||
|
|||
if (typeof key === 'string') { |
|||
key = new Buffer(key); |
|||
} |
|||
|
|||
if (typeof salt === 'string') { |
|||
salt = new Buffer(salt); |
|||
} |
|||
|
|||
var DK = new Buffer(dkLen); |
|||
|
|||
var U = new Buffer(hLen); |
|||
var T = new Buffer(hLen); |
|||
var block1 = new Buffer(salt.length + 4); |
|||
|
|||
var l = Math.ceil(dkLen / hLen); |
|||
var r = dkLen - (l - 1) * hLen; |
|||
|
|||
salt.copy(block1, 0, 0, salt.length); |
|||
for (var i = 1; i <= l; i++) { |
|||
block1[salt.length + 0] = i >> 24 & 0xff; |
|||
block1[salt.length + 1] = i >> 16 & 0xff; |
|||
block1[salt.length + 2] = i >> 8 & 0xff; |
|||
block1[salt.length + 3] = i >> 0 & 0xff; |
|||
|
|||
U = crypto.createHmac('sha512', key).update(block1).digest(); |
|||
|
|||
U.copy(T, 0, 0, hLen); |
|||
|
|||
for (var j = 1; j < iterations; j++) { |
|||
U = crypto.createHmac('sha512', key).update(U).digest(); |
|||
|
|||
for (var k = 0; k < hLen; k++) { |
|||
T[k] ^= U[k]; |
|||
} |
|||
} |
|||
|
|||
var destPos = (i - 1) * hLen; |
|||
var len = i === l ? r : hLen; |
|||
T.copy(DK, destPos, 0, len); |
|||
} |
|||
|
|||
return DK; |
|||
} |
|||
|
|||
module.exports = pbkdf2; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,10 @@ |
|||
'use strict'; |
|||
|
|||
module.exports = { |
|||
'CHINESE': require('./chinese'), |
|||
'ENGLISH': require('./english'), |
|||
'FRENCH': require('./french'), |
|||
'ITALIAN': require('./italian'), |
|||
'JAPANESE': require('./japanese'), |
|||
'SPANISH': require('./spanish') |
|||
}; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@ |
|||
module.exports = require('./mnemonic'); |
@ -0,0 +1,292 @@ |
|||
'use strict'; |
|||
|
|||
var _ = require('lodash'); |
|||
var $ = require('../util/preconditions'); |
|||
var BN = require('../crypto/bn'); |
|||
var errors = require('../errors'); |
|||
var Hash = require('../crypto/hash'); |
|||
var HDPrivateKey = require('../hdprivatekey'); |
|||
var Random = require('../crypto/random'); |
|||
var unorm = require('unorm'); |
|||
|
|||
/** |
|||
* This is an immutable class that represents a BIP39 Mnemonic code. |
|||
* See BIP39 specification for more info: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
|||
* A Mnemonic code is a a group of easy to remember words used for the generation |
|||
* of deterministic wallets. A Mnemonic can be used to generate a seed using |
|||
* an optional passphrase, for later generate a HDPrivateKey. |
|||
* |
|||
* @example |
|||
* // generate a random mnemonic
|
|||
* var mnemonic = new Mnemonic(); |
|||
* var phrase = mnemonic.phrase; |
|||
* |
|||
* // use a different language
|
|||
* var mnemonic = new Mnemonic(Mnemonic.Words.SPANISH); |
|||
* var xprivkey = mnemonic.toHDPrivateKey(); |
|||
* |
|||
* @param {*=} data - a seed, phrase, or entropy to initialize (can be skipped) |
|||
* @param {Array=} wordlist - the wordlist to generate mnemonics from |
|||
* @returns {Mnemonic} A new instance of Mnemonic |
|||
* @constructor |
|||
*/ |
|||
var Mnemonic = function(data, wordlist) { |
|||
if (!(this instanceof Mnemonic)) { |
|||
return new Mnemonic(data, wordlist); |
|||
} |
|||
|
|||
if (_.isArray(data)) { |
|||
wordlist = data; |
|||
data = null; |
|||
} |
|||
|
|||
|
|||
// handle data overloading
|
|||
var ent, phrase, seed; |
|||
if (Buffer.isBuffer(data)) { |
|||
seed = data; |
|||
} else if (_.isString(data)) { |
|||
phrase = unorm.nfkd(data); |
|||
} else if (_.isNumber(data)) { |
|||
ent = data; |
|||
} else if (data) { |
|||
throw new errors.InvalidArgument('data', 'Must be a Buffer, a string or an integer'); |
|||
} |
|||
ent = ent || 128; |
|||
|
|||
|
|||
// check and detect wordlist
|
|||
wordlist = wordlist || Mnemonic._getDictionary(phrase); |
|||
if (phrase && !wordlist) { |
|||
throw new errors.UnknownWordlist(phrase); |
|||
} |
|||
wordlist = wordlist || Mnemonic.Words.ENGLISH; |
|||
|
|||
if (seed) { |
|||
phrase = Mnemonic._entropy2mnemonic(seed, wordlist); |
|||
} |
|||
|
|||
|
|||
// validate phrase and ent
|
|||
if (phrase && !Mnemonic.isValid(phrase, wordlist)) { |
|||
throw new errors.InvalidMnemonic(phrase); |
|||
} |
|||
if (ent % 32 !== 0 || ent < 128) { |
|||
throw new errors.InvalidArgument('ENT', 'Values must be ENT > 128 and ENT % 32 == 0'); |
|||
} |
|||
|
|||
phrase = phrase || Mnemonic._mnemonic(ent, wordlist); |
|||
|
|||
Object.defineProperty(this, 'wordlist', { |
|||
configurable: false, |
|||
value: wordlist |
|||
}); |
|||
|
|||
Object.defineProperty(this, 'phrase', { |
|||
configurable: false, |
|||
value: phrase |
|||
}); |
|||
}; |
|||
|
|||
Mnemonic.Words = require('./words'); |
|||
|
|||
/** |
|||
* Will return a boolean if the mnemonic is valid |
|||
* |
|||
* @example |
|||
* |
|||
* var valid = Mnemonic.isValid('lab rescue lunch elbow recall phrase perfect donkey biology guess moment husband'); |
|||
* // true
|
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @param {String} [wordlist] - The wordlist used |
|||
* @returns {boolean} |
|||
*/ |
|||
Mnemonic.isValid = function(mnemonic, wordlist) { |
|||
mnemonic = unorm.nfkd(mnemonic); |
|||
wordlist = wordlist || Mnemonic._getDictionary(mnemonic); |
|||
|
|||
if (!wordlist) { |
|||
return false; |
|||
} |
|||
|
|||
var words = mnemonic.split(' '); |
|||
var bin = ''; |
|||
for (var i = 0; i < words.length; i++) { |
|||
var ind = wordlist.indexOf(words[i]); |
|||
if (ind < 0) return false; |
|||
bin = bin + ('00000000000' + ind.toString(2)).slice(-11); |
|||
} |
|||
|
|||
var cs = bin.length / 33; |
|||
var hash_bits = bin.slice(-cs); |
|||
var nonhash_bits = bin.slice(0, bin.length - cs); |
|||
var buf = new Buffer(nonhash_bits.length / 8); |
|||
for (i = 0; i < nonhash_bits.length / 8; i++) { |
|||
buf.writeUInt8(parseInt(bin.slice(i * 8, (i + 1) * 8), 2), i); |
|||
} |
|||
var expected_hash_bits = Mnemonic._entropyChecksum(buf); |
|||
return expected_hash_bits === hash_bits; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to check if a mnemonic belongs to a wordlist. |
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @param {String} wordlist - The wordlist |
|||
* @returns {boolean} |
|||
*/ |
|||
Mnemonic._belongsToWordlist = function(mnemonic, wordlist) { |
|||
var words = unorm.nfkd(mnemonic).split(' '); |
|||
for (var i = 0; i < words.length; i++) { |
|||
var ind = wordlist.indexOf(words[i]); |
|||
if (ind < 0) return false; |
|||
} |
|||
return true; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to detect the wordlist used to generate the mnemonic. |
|||
* |
|||
* @param {String} mnemonic - The mnemonic string |
|||
* @returns {Array} the wordlist or null |
|||
*/ |
|||
Mnemonic._getDictionary = function(mnemonic) { |
|||
if (!mnemonic) return null; |
|||
|
|||
var dicts = Object.keys(Mnemonic.Words); |
|||
for (var i = 0; i < dicts.length; i++) { |
|||
var key = dicts[i]; |
|||
if (Mnemonic._belongsToWordlist(mnemonic, Mnemonic.Words[key])) { |
|||
return Mnemonic.Words[key]; |
|||
} |
|||
} |
|||
return null; |
|||
}; |
|||
|
|||
/** |
|||
* Will generate a seed based on the mnemonic and optional passphrase. |
|||
* |
|||
* @param {String} [passphrase] |
|||
* @returns {Buffer} |
|||
*/ |
|||
Mnemonic.prototype.toSeed = function(passphrase) { |
|||
passphrase = passphrase || ''; |
|||
return Mnemonic.pbkdf2(unorm.nfkd(this.phrase), unorm.nfkd('mnemonic' + passphrase), 2048, 64); |
|||
}; |
|||
|
|||
/** |
|||
* Will generate a Mnemonic object based on a seed. |
|||
* |
|||
* @param {Buffer} [seed] |
|||
* @param {string} [wordlist] |
|||
* @returns {Mnemonic} |
|||
*/ |
|||
Mnemonic.fromSeed = function(seed, wordlist) { |
|||
$.checkArgument(Buffer.isBuffer(seed), 'seed must be a Buffer.'); |
|||
$.checkArgument(_.isArray(wordlist) || _.isString(wordlist), 'wordlist must be a string or an array.'); |
|||
return new Mnemonic(seed, wordlist); |
|||
}; |
|||
|
|||
/** |
|||
* |
|||
* Generates a HD Private Key from a Mnemonic. |
|||
* Optionally receive a passphrase and bitcoin network. |
|||
* |
|||
* @param {String=} [passphrase] |
|||
* @param {Network|String|number=} [network] - The network: 'livenet' or 'testnet' |
|||
* @returns {HDPrivateKey} |
|||
*/ |
|||
Mnemonic.prototype.toHDPrivateKey = function(passphrase, network) { |
|||
var seed = this.toSeed(passphrase); |
|||
return HDPrivateKey.fromSeed(seed, network); |
|||
}; |
|||
|
|||
/** |
|||
* Will return a the string representation of the mnemonic |
|||
* |
|||
* @returns {String} Mnemonic |
|||
*/ |
|||
Mnemonic.prototype.toString = function() { |
|||
return this.phrase; |
|||
}; |
|||
|
|||
/** |
|||
* Will return a string formatted for the console |
|||
* |
|||
* @returns {String} Mnemonic |
|||
*/ |
|||
Mnemonic.prototype.inspect = function() { |
|||
return '<Mnemonic: ' + this.toString() + ' >'; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to generate a random mnemonic |
|||
* |
|||
* @param {Number} ENT - Entropy size, defaults to 128 |
|||
* @param {Array} wordlist - Array of words to generate the mnemonic |
|||
* @returns {String} Mnemonic string |
|||
*/ |
|||
Mnemonic._mnemonic = function(ENT, wordlist) { |
|||
var buf = Random.getRandomBuffer(ENT / 8); |
|||
return Mnemonic._entropy2mnemonic(buf, wordlist); |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to generate mnemonic based on entropy |
|||
* |
|||
* @param {Number} entropy - Entropy buffer |
|||
* @param {Array} wordlist - Array of words to generate the mnemonic |
|||
* @returns {String} Mnemonic string |
|||
*/ |
|||
Mnemonic._entropy2mnemonic = function(entropy, wordlist) { |
|||
var bin = ''; |
|||
for (var i = 0; i < entropy.length; i++) { |
|||
bin = bin + ('00000000' + entropy[i].toString(2)).slice(-8); |
|||
} |
|||
|
|||
bin = bin + Mnemonic._entropyChecksum(entropy); |
|||
if (bin.length % 11 !== 0) { |
|||
throw new errors.InvalidEntropy(bin); |
|||
} |
|||
var mnemonic = []; |
|||
for (i = 0; i < bin.length / 11; i++) { |
|||
var wi = parseInt(bin.slice(i * 11, (i + 1) * 11), 2); |
|||
mnemonic.push(wordlist[wi]); |
|||
} |
|||
var ret; |
|||
if (wordlist === Mnemonic.Words.JAPANESE) { |
|||
ret = mnemonic.join('\u3000'); |
|||
} else { |
|||
ret = mnemonic.join(' '); |
|||
} |
|||
return ret; |
|||
}; |
|||
|
|||
/** |
|||
* Internal function to create checksum of entropy |
|||
* |
|||
* @param entropy |
|||
* @returns {string} Checksum of entropy length / 32 |
|||
* @private |
|||
*/ |
|||
Mnemonic._entropyChecksum = function(entropy) { |
|||
var hash = Hash.sha256(entropy); |
|||
var bits = entropy.length * 8; |
|||
var cs = bits / 32; |
|||
|
|||
var hashbits = new BN(hash.toString('hex'), 16).toString(2); |
|||
|
|||
// zero pad the hash bits
|
|||
while (hashbits.length % 256 !== 0) { |
|||
hashbits = '0' + hashbits; |
|||
} |
|||
|
|||
var checksum = hashbits.slice(0, cs); |
|||
|
|||
return checksum; |
|||
}; |
|||
|
|||
Mnemonic.pbkdf2 = require('./pbkdf2'); |
|||
|
|||
module.exports = Mnemonic; |
@ -0,0 +1,71 @@ |
|||
'use strict'; |
|||
|
|||
var crypto = require('crypto'); |
|||
|
|||
/** |
|||
* PDKBF2 |
|||
* Credit to: https://github.com/stayradiated/pbkdf2-sha512
|
|||
* Copyright (c) 2014, JP Richardson Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved |
|||
*/ |
|||
function pbkdf2(key, salt, iterations, dkLen) { |
|||
/* jshint maxstatements: 31 */ |
|||
/* jshint maxcomplexity: 9 */ |
|||
|
|||
var hLen = 64; //SHA512 Mac length
|
|||
if (dkLen > (Math.pow(2, 32) - 1) * hLen) { |
|||
throw Error('Requested key length too long'); |
|||
} |
|||
|
|||
if (typeof key !== 'string' && !Buffer.isBuffer(key)) { |
|||
throw new TypeError('key must a string or Buffer'); |
|||
} |
|||
|
|||
if (typeof salt !== 'string' && !Buffer.isBuffer(salt)) { |
|||
throw new TypeError('salt must a string or Buffer'); |
|||
} |
|||
|
|||
if (typeof key === 'string') { |
|||
key = new Buffer(key); |
|||
} |
|||
|
|||
if (typeof salt === 'string') { |
|||
salt = new Buffer(salt); |
|||
} |
|||
|
|||
var DK = new Buffer(dkLen); |
|||
|
|||
var U = new Buffer(hLen); |
|||
var T = new Buffer(hLen); |
|||
var block1 = new Buffer(salt.length + 4); |
|||
|
|||
var l = Math.ceil(dkLen / hLen); |
|||
var r = dkLen - (l - 1) * hLen; |
|||
|
|||
salt.copy(block1, 0, 0, salt.length); |
|||
for (var i = 1; i <= l; i++) { |
|||
block1[salt.length + 0] = (i >> 24 & 0xff); |
|||
block1[salt.length + 1] = (i >> 16 & 0xff); |
|||
block1[salt.length + 2] = (i >> 8 & 0xff); |
|||
block1[salt.length + 3] = (i >> 0 & 0xff); |
|||
|
|||
U = crypto.createHmac('sha512', key).update(block1).digest(); |
|||
|
|||
U.copy(T, 0, 0, hLen); |
|||
|
|||
for (var j = 1; j < iterations; j++) { |
|||
U = crypto.createHmac('sha512', key).update(U).digest(); |
|||
|
|||
for (var k = 0; k < hLen; k++) { |
|||
T[k] ^= U[k]; |
|||
} |
|||
} |
|||
|
|||
var destPos = (i - 1) * hLen; |
|||
var len = (i === l ? r : hLen); |
|||
T.copy(DK, destPos, 0, len); |
|||
} |
|||
|
|||
return DK; |
|||
} |
|||
|
|||
module.exports = pbkdf2; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@ |
|||
module.exports = { |
|||
'CHINESE': require('./chinese'), |
|||
'ENGLISH': require('./english'), |
|||
'FRENCH': require('./french'), |
|||
'ITALIAN': require('./italian'), |
|||
'JAPANESE': require('./japanese'), |
|||
'SPANISH': require('./spanish') |
|||
}; |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,300 @@ |
|||
{ |
|||
"english": [ |
|||
[ |
|||
"TREZOR", |
|||
"00000000000000000000000000000000", |
|||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about", |
|||
"c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e53495531f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"legal winner thank year wave sausage worth useful legal winner thank yellow", |
|||
"2e8905819b8723fe2c1d161860e5ee1830318dbf49a83bd451cfb8440c28bd6fa457fe1296106559a3c80937a1c1069be3a3a5bd381ee6260e8d9739fce1f607" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"80808080808080808080808080808080", |
|||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage above", |
|||
"d71de856f81a8acc65e6fc851a38d4d7ec216fd0796d0a6827a3ad6ed5511a30fa280f12eb2e47ed2ac03b5c462a0358d18d69fe4f985ec81778c1b370b652a8" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"ffffffffffffffffffffffffffffffff", |
|||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo wrong", |
|||
"ac27495480225222079d7be181583751e86f571027b0497b5b5d11218e0a8a13332572917f0f8e5a589620c6f15b11c61dee327651a14c34e18231052e48c069" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"000000000000000000000000000000000000000000000000", |
|||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon agent", |
|||
"035895f2f481b1b0f01fcf8c289c794660b289981a78f8106447707fdd9666ca06da5a9a565181599b79f53b844d8a71dd9f439c52a3d7b3e8a79c906ac845fa" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal will", |
|||
"f2b94508732bcbacbcc020faefecfc89feafa6649a5491b8c952cede496c214a0c7b3c392d168748f2d4a612bada0753b52a1c7ac53c1e93abd5c6320b9e95dd" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"808080808080808080808080808080808080808080808080", |
|||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter always", |
|||
"107d7c02a5aa6f38c58083ff74f04c607c2d2c0ecc55501dadd72d025b751bc27fe913ffb796f841c49b1d33b610cf0e91d3aa239027f5e99fe4ce9e5088cd65" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffff", |
|||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo when", |
|||
"0cd6e5d827bb62eb8fc1e262254223817fd068a74b5b449cc2f667c3f1f985a76379b43348d952e2265b4cd129090758b3e3c2c49103b5051aac2eaeb890a528" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"0000000000000000000000000000000000000000000000000000000000000000", |
|||
"abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon art", |
|||
"bda85446c68413707090a52022edd26a1c9462295029f2e60cd7c4f2bbd3097170af7a4d73245cafa9c3cca8d561a7c3de6f5d4a10be8ed2a5e608d68f92fcc8" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth useful legal winner thank year wave sausage worth title", |
|||
"bc09fca1804f7e69da93c2f2028eb238c227f2e9dda30cd63699232578480a4021b146ad717fbb7e451ce9eb835f43620bf5c514db0f8add49f5d121449d3e87" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"8080808080808080808080808080808080808080808080808080808080808080", |
|||
"letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic avoid letter advice cage absurd amount doctor acoustic bless", |
|||
"c0c519bd0e91a2ed54357d9d1ebef6f5af218a153624cf4f2da911a0ed8f7a09e2ef61af0aca007096df430022f7a2b6fb91661a9589097069720d015e4e982f" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
|||
"zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo zoo vote", |
|||
"dd48c104698c30cfe2b6142103248622fb7bb0ff692eebb00089b32d22484e1613912f0a5b694407be899ffd31ed3992c456cdf60f5d4564b8ba3f05a69890ad" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"77c2b00716cec7213839159e404db50d", |
|||
"jelly better achieve collect unaware mountain thought cargo oxygen act hood bridge", |
|||
"b5b6d0127db1a9d2226af0c3346031d77af31e918dba64287a1b44b8ebf63cdd52676f672a290aae502472cf2d602c051f3e6f18055e84e4c43897fc4e51a6ff" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", |
|||
"renew stay biology evidence goat welcome casual join adapt armor shuffle fault little machine walk stumble urge swap", |
|||
"9248d83e06f4cd98debf5b6f010542760df925ce46cf38a1bdb4e4de7d21f5c39366941c69e1bdbf2966e0f6e6dbece898a0e2f0a4c2b3e640953dfe8b7bbdc5" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", |
|||
"dignity pass list indicate nasty swamp pool script soccer toe leaf photo multiply desk host tomato cradle drill spread actor shine dismiss champion exotic", |
|||
"ff7f3184df8696d8bef94b6c03114dbee0ef89ff938712301d27ed8336ca89ef9635da20af07d4175f2bf5f3de130f39c9d9e8dd0472489c19b1a020a940da67" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"0460ef47585604c5660618db2e6a7e7f", |
|||
"afford alter spike radar gate glance object seek swamp infant panel yellow", |
|||
"65f93a9f36b6c85cbe634ffc1f99f2b82cbb10b31edc7f087b4f6cb9e976e9faf76ff41f8f27c99afdf38f7a303ba1136ee48a4c1e7fcd3dba7aa876113a36e4" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", |
|||
"indicate race push merry suffer human cruise dwarf pole review arch keep canvas theme poem divorce alter left", |
|||
"3bbf9daa0dfad8229786ace5ddb4e00fa98a044ae4c4975ffd5e094dba9e0bb289349dbe2091761f30f382d4e35c4a670ee8ab50758d2c55881be69e327117ba" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", |
|||
"clutch control vehicle tonight unusual clog visa ice plunge glimpse recipe series open hour vintage deposit universe tip job dress radar refuse motion taste", |
|||
"fe908f96f46668b2d5b37d82f558c77ed0d69dd0e7e043a5b0511c48c2f1064694a956f86360c93dd04052a8899497ce9e985ebe0c8c52b955e6ae86d4ff4449" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"eaebabb2383351fd31d703840b32e9e2", |
|||
"turtle front uncle idea crush write shrug there lottery flower risk shell", |
|||
"bdfb76a0759f301b0b899a1e3985227e53b3f51e67e3f2a65363caedf3e32fde42a66c404f18d7b05818c95ef3ca1e5146646856c461c073169467511680876c" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", |
|||
"kiss carry display unusual confirm curtain upgrade antique rotate hello void custom frequent obey nut hole price segment", |
|||
"ed56ff6c833c07982eb7119a8f48fd363c4a9b1601cd2de736b01045c5eb8ab4f57b079403485d1c4924f0790dc10a971763337cb9f9c62226f64fff26397c79" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", |
|||
"exile ask congress lamp submit jacket era scheme attend cousin alcohol catch course end lucky hurt sentence oven short ball bird grab wing top", |
|||
"095ee6f817b4c2cb30a5a797360a81a40ab0f9a4e25ecd672a3f58a0b5ba0687c096a6b14d2c0deb3bdefce4f61d01ae07417d502429352e27695163f7447a8c" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"18ab19a9f54a9274f03e5209a2ac8a91", |
|||
"board flee heavy tunnel powder denial science ski answer betray cargo cat", |
|||
"6eff1bb21562918509c73cb990260db07c0ce34ff0e3cc4a8cb3276129fbcb300bddfe005831350efd633909f476c45c88253276d9fd0df6ef48609e8bb7dca8" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", |
|||
"board blade invite damage undo sun mimic interest slam gaze truly inherit resist great inject rocket museum chief", |
|||
"f84521c777a13b61564234bf8f8b62b3afce27fc4062b51bb5e62bdfecb23864ee6ecf07c1d5a97c0834307c5c852d8ceb88e7c97923c0a3b496bedd4e5f88a9" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", |
|||
"beyond stage sleep clip because twist token leaf atom beauty genius food business side grid unable middle armed observe pair crouch tonight away coconut", |
|||
"b15509eaa2d09d3efd3e006ef42151b30367dc6e3aa5e44caba3fe4d3e352e65101fbdb86a96776b91946ff06f8eac594dc6ee1d3e82a42dfe1b40fef6bcc3fd" |
|||
], |
|||
[ |
|||
"TREZOR", |
|||
"38fe1937dd2135d7ca5e472565c41ded449d8cea2e70e1c93571c21831c82f0f466c3d94f29bff1d0cce3e85a22b93364627af716ee91a477d6e2e55abf4e761", |
|||
"decline valid evil ripple battle typical city similar century comfort alter surround endorse shoe post sock tide endless fragile loud loan tomato rotate trip history uncover device dawn vault major decline spawn peasant frame snow middle kit reward roof cash electric twin merit prize satisfy inhale lyrics lucky", |
|||
"d9a9b65c54df4104349d5ce6f9275f249160ddf378deff6e540f5492e449e0378ee20b1622bef982f6dddb003568e449fee66335cb45cbe3f8a41050b251238a" |
|||
] |
|||
], |
|||
"japanese": [ |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"00000000000000000000000000000000", |
|||
"あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あおぞら", |
|||
"a262d6fb6122ecf45be09c50492b31f92e9beb7d9a845987a02cefda57a15f9c467a17872029a9e92299b5cbdf306e3a0ee620245cbd508959b6cb7ca637bd55" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"そつう れきだい ほんやく わかす りくつ ばいか ろせん やちん そつう れきだい ほんやく わかめ", |
|||
"aee025cbe6ca256862f889e48110a6a382365142f7d16f2b9545285b3af64e542143a577e9c144e101a6bdca18f8d97ec3366ebf5b088b1c1af9bc31346e60d9" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"80808080808080808080808080808080", |
|||
"そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら あまど おおう あかちゃん", |
|||
"e51736736ebdf77eda23fa17e31475fa1d9509c78f1deb6b4aacfbd760a7e2ad769c714352c95143b5c1241985bcb407df36d64e75dd5a2b78ca5d2ba82a3544" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"ffffffffffffffffffffffffffffffff", |
|||
"われる われる われる われる われる われる われる われる われる われる われる ろんぶん", |
|||
"4cd2ef49b479af5e1efbbd1e0bdc117f6a29b1010211df4f78e2ed40082865793e57949236c43b9fe591ec70e5bb4298b8b71dc4b267bb96ed4ed282c8f7761c" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"000000000000000000000000000000000000000000000000", |
|||
"あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あらいぐま", |
|||
"d99e8f1ce2d4288d30b9c815ae981edd923c01aa4ffdc5dee1ab5fe0d4a3e13966023324d119105aff266dac32e5cd11431eeca23bbd7202ff423f30d6776d69" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"そつう れきだい ほんやく わかす りくつ ばいか ろせん やちん そつう れきだい ほんやく わかす りくつ ばいか ろせん やちん そつう れいぎ", |
|||
"eaaf171efa5de4838c758a93d6c86d2677d4ccda4a064a7136344e975f91fe61340ec8a615464b461d67baaf12b62ab5e742f944c7bd4ab6c341fbafba435716" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"808080808080808080808080808080808080808080808080", |
|||
"そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら いきなり", |
|||
"aec0f8d3167a10683374c222e6e632f2940c0826587ea0a73ac5d0493b6a632590179a6538287641a9fc9df8e6f24e01bf1be548e1f74fd7407ccd72ecebe425" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffff", |
|||
"われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる りんご", |
|||
"f0f738128a65b8d1854d68de50ed97ac1831fc3a978c569e415bbcb431a6a671d4377e3b56abd518daa861676c4da75a19ccb41e00c37d086941e471a4374b95" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"0000000000000000000000000000000000000000000000000000000000000000", |
|||
"あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん あいこくしん いってい", |
|||
"23f500eec4a563bf90cfda87b3e590b211b959985c555d17e88f46f7183590cd5793458b094a4dccc8f05807ec7bd2d19ce269e20568936a751f6f1ec7c14ddd" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f", |
|||
"そつう れきだい ほんやく わかす りくつ ばいか ろせん やちん そつう れきだい ほんやく わかす りくつ ばいか ろせん やちん そつう れきだい ほんやく わかす りくつ ばいか ろせん まんきつ", |
|||
"cd354a40aa2e241e8f306b3b752781b70dfd1c69190e510bc1297a9c5738e833bcdc179e81707d57263fb7564466f73d30bf979725ff783fb3eb4baa86560b05" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"8080808080808080808080808080808080808080808080808080808080808080", |
|||
"そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら あまど おおう あこがれる いくぶん けいけん あたえる いよく そとづら あまど おおう あこがれる いくぶん けいけん あたえる うめる", |
|||
"6b7cd1b2cdfeeef8615077cadd6a0625f417f287652991c80206dbd82db17bf317d5c50a80bd9edd836b39daa1b6973359944c46d3fcc0129198dc7dc5cd0e68" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", |
|||
"われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる われる らいう", |
|||
"a44ba7054ac2f9226929d56505a51e13acdaa8a9097923ca07ea465c4c7e294c038f3f4e7e4b373726ba0057191aced6e48ac8d183f3a11569c426f0de414623" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"77c2b00716cec7213839159e404db50d", |
|||
"せまい うちがわ あずき かろう めずらしい だんち ますく おさめる ていぼう あたる すあな えしゃく", |
|||
"344cef9efc37d0cb36d89def03d09144dd51167923487eec42c487f7428908546fa31a3c26b7391a2b3afe7db81b9f8c5007336b58e269ea0bd10749a87e0193" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"b63a9c59a6e641f288ebc103017f1da9f8290b3da6bdef7b", |
|||
"ぬすむ ふっかつ うどん こうりつ しつじ りょうり おたがい せもたれ あつめる いちりゅう はんしゃ ごますり そんけい たいちょう らしんばん ぶんせき やすみ ほいく", |
|||
"b14e7d35904cb8569af0d6a016cee7066335a21c1c67891b01b83033cadb3e8a034a726e3909139ecd8b2eb9e9b05245684558f329b38480e262c1d6bc20ecc4" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"3e141609b97933b66a060dcddc71fad1d91677db872031e85f4c015c5e7e8982", |
|||
"くのう てぬぐい そんかい すろっと ちきゅう ほあん とさか はくしゅ ひびく みえる そざい てんすう たんぴん くしょう すいようび みけん きさらぎ げざん ふくざつ あつかう はやい くろう おやゆび こすう", |
|||
"32e78dce2aff5db25aa7a4a32b493b5d10b4089923f3320c8b287a77e512455443298351beb3f7eb2390c4662a2e566eec5217e1a37467af43b46668d515e41b" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"0460ef47585604c5660618db2e6a7e7f", |
|||
"あみもの いきおい ふいうち にげる ざんしょ じかん ついか はたん ほあん すんぽう てちがい わかめ", |
|||
"0acf902cd391e30f3f5cb0605d72a4c849342f62bd6a360298c7013d714d7e58ddf9c7fdf141d0949f17a2c9c37ced1d8cb2edabab97c4199b142c829850154b" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"72f60ebac5dd8add8d2a25a797102c3ce21bc029c200076f", |
|||
"すろっと にくしみ なやむ たとえる へいこう すくう きない けってい とくべつ ねっしん いたみ せんせい おくりがな まかい とくい けあな いきおい そそぐ", |
|||
"9869e220bec09b6f0c0011f46e1f9032b269f096344028f5006a6e69ea5b0b8afabbb6944a23e11ebd021f182dd056d96e4e3657df241ca40babda532d364f73" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"2c85efc7f24ee4573d2b81a6ec66cee209b2dcbd09d8eddc51e0215b0b68e416", |
|||
"かほご きうい ゆたか みすえる もらう がっこう よそう ずっと ときどき したうけ にんか はっこう つみき すうじつ よけい くげん もくてき まわり せめる げざい にげる にんたい たんそく ほそく", |
|||
"713b7e70c9fbc18c831bfd1f03302422822c3727a93a5efb9659bec6ad8d6f2c1b5c8ed8b0b77775feaf606e9d1cc0a84ac416a85514ad59f5541ff5e0382481" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"eaebabb2383351fd31d703840b32e9e2", |
|||
"めいえん さのう めだつ すてる きぬごし ろんぱ はんこ まける たいおう さかいし ねんいり はぶらし", |
|||
"06e1d5289a97bcc95cb4a6360719131a786aba057d8efd603a547bd254261c2a97fcd3e8a4e766d5416437e956b388336d36c7ad2dba4ee6796f0249b10ee961" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"7ac45cfe7722ee6c7ba84fbc2d5bd61b45cb2fe5eb65aa78", |
|||
"せんぱい おしえる ぐんかん もらう きあい きぼう やおや いせえび のいず じゅしん よゆう きみつ さといも ちんもく ちわわ しんせいじ とめる はちみつ", |
|||
"1fef28785d08cbf41d7a20a3a6891043395779ed74503a5652760ee8c24dfe60972105ee71d5168071a35ab7b5bd2f8831f75488078a90f0926c8e9171b2bc4a" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"4fa1a8bc3e6d80ee1316050e862c1812031493212b7ec3f3bb1b08f168cabeef", |
|||
"こころ いどう きあつ そうがんきょう へいあん せつりつ ごうせい はいち いびき きこく あんい おちつく きこえる けんとう たいこ すすめる はっけん ていど はんおん いんさつ うなぎ しねま れいぼう みつかる", |
|||
"43de99b502e152d4c198542624511db3007c8f8f126a30818e856b2d8a20400d29e7a7e3fdd21f909e23be5e3c8d9aee3a739b0b65041ff0b8637276703f65c2" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"18ab19a9f54a9274f03e5209a2ac8a91", |
|||
"うりきれ さいせい じゆう むろん とどける ぐうたら はいれつ ひけつ いずれ うちあわせ おさめる おたく", |
|||
"3d711f075ee44d8b535bb4561ad76d7d5350ea0b1f5d2eac054e869ff7963cdce9581097a477d697a2a9433a0c6884bea10a2193647677977c9820dd0921cbde" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"18a2e1d81b8ecfb2a333adcb0c17a5b9eb76cc5d05db91a4", |
|||
"うりきれ うねる せっさたくま きもち めんきょ へいたく たまご ぜっく びじゅつかん さんそ むせる せいじ ねくたい しはらい せおう ねんど たんまつ がいけん", |
|||
"753ec9e333e616e9471482b4b70a18d413241f1e335c65cd7996f32b66cf95546612c51dcf12ead6f805f9ee3d965846b894ae99b24204954be80810d292fcdd" |
|||
], |
|||
[ |
|||
"メートルガバヴァぱばぐゞちぢ十人十色", |
|||
"15da872c95a13dd738fbf50e427583ad61f18fd99f628c417a61cf8343c90419", |
|||
"うちゅう ふそく ひしょ がちょう うけもつ めいそう みかん そざい いばる うけとる さんま さこつ おうさま ぱんつ しひょう めした たはつ いちぶ つうじょう てさぎょう きつね みすえる いりぐち かめれおん", |
|||
"346b7321d8c04f6f37b49fdf062a2fddc8e1bf8f1d33171b65074531ec546d1d3469974beccb1a09263440fc92e1042580a557fdce314e27ee4eabb25fa5e5fe" |
|||
] |
|||
] |
|||
} |
@ -0,0 +1,225 @@ |
|||
'use strict'; |
|||
|
|||
var chai = require('chai'); |
|||
var should = chai.should(); |
|||
|
|||
var bch = require('../..'); |
|||
var Mnemonic = bch.Mnemonic; |
|||
var errors = bch.errors; |
|||
var bip39_vectors = require('../data/mnemonics.json'); |
|||
|
|||
describe('Mnemonic', function() { |
|||
this.timeout(30000); |
|||
|
|||
it('should initialize the class', function() { |
|||
should.exist(Mnemonic); |
|||
}); |
|||
|
|||
describe('# Mnemonic', function() { |
|||
|
|||
describe('Constructor', function() { |
|||
it('does not require new keyword', function() { |
|||
var mnemonic = Mnemonic(); // jshint ignore:line
|
|||
mnemonic.should.be.instanceof(Mnemonic); |
|||
}); |
|||
|
|||
it('should fail with invalid data', function() { |
|||
(function() { |
|||
return new Mnemonic({}); |
|||
}).should.throw(errors.InvalidArgument); |
|||
}); |
|||
|
|||
it('should fail with unknown word list', function() { |
|||
(function() { |
|||
return new Mnemonic('pilots foster august tomorrow kit daughter unknown awesome model town village master'); |
|||
}).should.throw(errors.UnknownWordlist); |
|||
}); |
|||
|
|||
it('should fail with invalid mnemonic', function() { |
|||
(function() { |
|||
return new Mnemonic('monster foster august tomorrow kit daughter unknown awesome model town village pilot'); |
|||
}).should.throw(errors.InvalidMnemonic); |
|||
}); |
|||
|
|||
it('should fail with invalid ENT', function() { |
|||
(function() { |
|||
return new Mnemonic(64); |
|||
}).should.throw(errors.InvalidArgument); |
|||
}); |
|||
|
|||
it('constructor defaults to english worldlist', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
mnemonic.wordlist.should.equal(Mnemonic.Words.ENGLISH); |
|||
}); |
|||
|
|||
it('allow using different worldlists', function() { |
|||
var mnemonic = new Mnemonic(Mnemonic.Words.SPANISH); |
|||
mnemonic.wordlist.should.equal(Mnemonic.Words.SPANISH); |
|||
}); |
|||
|
|||
it('constructor honor both length and wordlist', function() { |
|||
var mnemonic = new Mnemonic(32 * 7, Mnemonic.Words.SPANISH); |
|||
mnemonic.phrase.split(' ').length.should.equal(21); |
|||
mnemonic.wordlist.should.equal(Mnemonic.Words.SPANISH); |
|||
}); |
|||
|
|||
it('constructor should detect standard wordlist', function() { |
|||
var mnemonic = new Mnemonic('afirmar diseño hielo fideo etapa ogro cambio fideo toalla pomelo número buscar'); |
|||
mnemonic.wordlist.should.equal(Mnemonic.Words.SPANISH); |
|||
}); |
|||
|
|||
}); |
|||
|
|||
|
|||
it('english wordlist is complete', function() { |
|||
Mnemonic.Words.ENGLISH.length.should.equal(2048); |
|||
Mnemonic.Words.ENGLISH[0].should.equal('abandon'); |
|||
}); |
|||
|
|||
it('spanish wordlist is complete', function() { |
|||
Mnemonic.Words.SPANISH.length.should.equal(2048); |
|||
Mnemonic.Words.SPANISH[0].should.equal('ábaco'); |
|||
}); |
|||
|
|||
it('japanese wordlist is complete', function() { |
|||
Mnemonic.Words.JAPANESE.length.should.equal(2048); |
|||
Mnemonic.Words.JAPANESE[0].should.equal('あいこくしん'); |
|||
}); |
|||
|
|||
it('chinese wordlist is complete', function() { |
|||
Mnemonic.Words.CHINESE.length.should.equal(2048); |
|||
Mnemonic.Words.CHINESE[0].should.equal('的'); |
|||
}); |
|||
|
|||
it('french wordlist is complete', function() { |
|||
Mnemonic.Words.FRENCH.length.should.equal(2048); |
|||
Mnemonic.Words.FRENCH[0].should.equal('abaisser'); |
|||
}); |
|||
|
|||
it('italian wordlist is complete', function() { |
|||
Mnemonic.Words.ITALIAN.length.should.equal(2048); |
|||
Mnemonic.Words.ITALIAN[0].should.equal('abaco'); |
|||
}); |
|||
|
|||
it('allows use different phrase lengths', function() { |
|||
var mnemonic; |
|||
|
|||
mnemonic = new Mnemonic(32 * 4); |
|||
mnemonic.phrase.split(' ').length.should.equal(12); |
|||
|
|||
mnemonic = new Mnemonic(32 * 5); |
|||
mnemonic.phrase.split(' ').length.should.equal(15); |
|||
|
|||
mnemonic = new Mnemonic(32 * 6); |
|||
mnemonic.phrase.split(' ').length.should.equal(18); |
|||
|
|||
mnemonic = new Mnemonic(32 * 7); |
|||
mnemonic.phrase.split(' ').length.should.equal(21); |
|||
|
|||
mnemonic = new Mnemonic(32 * 8); |
|||
mnemonic.phrase.split(' ').length.should.equal(24); |
|||
}); |
|||
|
|||
it('validates a phrase', function() { |
|||
var valid = Mnemonic.isValid('afirmar diseño hielo fideo etapa ogro cambio fideo toalla pomelo número buscar'); |
|||
valid.should.equal(true); |
|||
|
|||
var invalid = Mnemonic.isValid('afirmar diseño hielo fideo etapa ogro cambio fideo hielo pomelo número buscar'); |
|||
invalid.should.equal(false); |
|||
|
|||
var invalid2 = Mnemonic.isValid('afirmar diseño hielo fideo etapa ogro cambio fideo hielo pomelo número oneInvalidWord'); |
|||
invalid2.should.equal(false); |
|||
|
|||
var invalid3 = Mnemonic.isValid('totally invalid phrase'); |
|||
invalid3.should.equal(false); |
|||
|
|||
var valid2 = Mnemonic.isValid('caution opprimer époque belote devenir ficeler filleul caneton apologie nectar frapper fouiller'); |
|||
valid2.should.equal(true); |
|||
}); |
|||
|
|||
it('has a toString method', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
mnemonic.toString().should.equal(mnemonic.phrase); |
|||
}); |
|||
|
|||
it('has a toString method', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
mnemonic.inspect().should.have.string('<Mnemonic:'); |
|||
}); |
|||
|
|||
it('derives a seed without a passphrase', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
var seed = mnemonic.toSeed(); |
|||
should.exist(seed); |
|||
}); |
|||
|
|||
it('derives a seed using a passphrase', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
var seed = mnemonic.toSeed('my passphrase'); |
|||
should.exist(seed); |
|||
}); |
|||
|
|||
it('derives an extended private key', function() { |
|||
var mnemonic = new Mnemonic(); |
|||
var pk = mnemonic.toHDPrivateKey(); |
|||
should.exist(pk); |
|||
}); |
|||
|
|||
it('Mnemonic.fromSeed should fail with invalid wordlist', function() { |
|||
(function() { |
|||
return Mnemonic.fromSeed(new Buffer(1)); |
|||
}).should.throw(errors.InvalidArgument); |
|||
}); |
|||
|
|||
it('Mnemonic.fromSeed should fail with invalid seed', function() { |
|||
(function() { |
|||
return Mnemonic.fromSeed(); |
|||
}).should.throw(errors.InvalidArgument); |
|||
}); |
|||
|
|||
it('Constructor should fail with invalid seed', function() { |
|||
(function() { |
|||
return new Mnemonic(new Buffer(1)); |
|||
}).should.throw(errors.InvalidEntropy); |
|||
}); |
|||
|
|||
// To add new vectors for different languages:
|
|||
// 1. Add and implement the wordlist so it appears in Mnemonic.Words
|
|||
// 2. Add the vectors and make sure the key is lowercase of the key for Mnemonic.Words
|
|||
var vector_wordlists = {}; |
|||
|
|||
for (var key in Mnemonic.Words) { |
|||
if (Mnemonic.Words.hasOwnProperty(key)) { |
|||
vector_wordlists[key.toLowerCase()] = Mnemonic.Words[key]; |
|||
} |
|||
} |
|||
|
|||
var test_vector = function(v, lang) { |
|||
it('should pass test vector for ' + lang + ' #' + v, function() { |
|||
var wordlist = vector_wordlists[lang]; |
|||
var vector = bip39_vectors[lang][v]; |
|||
var code = vector[1]; |
|||
var mnemonic = vector[2]; |
|||
var seed = vector[3]; |
|||
var mnemonic1 = Mnemonic.fromSeed(new Buffer(code, 'hex'), wordlist).phrase; |
|||
mnemonic1.should.equal(mnemonic); |
|||
|
|||
var m = new Mnemonic(mnemonic); |
|||
var seed1 = m.toSeed(vector[0]); |
|||
seed1.toString('hex').should.equal(seed); |
|||
|
|||
Mnemonic.isValid(mnemonic, wordlist).should.equal(true); |
|||
}); |
|||
}; |
|||
|
|||
for (var key in bip39_vectors) { |
|||
if (bip39_vectors.hasOwnProperty(key)) { |
|||
for (var v = 0; v < bip39_vectors[key].length; v++) { |
|||
test_vector(v, key); |
|||
} |
|||
} |
|||
} |
|||
|
|||
}); |
|||
|
|||
}); |
@ -0,0 +1,44 @@ |
|||
'use strict'; |
|||
|
|||
var chai = require('chai'); |
|||
var should = chai.should(); |
|||
|
|||
var bch = require('../..'); |
|||
var pbkdf2 = bch.Mnemonic.pbkdf2; |
|||
|
|||
describe('pbkdf2', function() { |
|||
this.timeout(10000); |
|||
|
|||
// http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors
|
|||
it('passes test vector 1', function() { |
|||
var key = 'password'; |
|||
var salt = 'salt'; |
|||
|
|||
var res = pbkdf2(key, salt, 1, 64); |
|||
res.toString('hex').should.equal('867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce'); |
|||
}); |
|||
|
|||
it('passes test vector 2', function() { |
|||
var key = 'password'; |
|||
var salt = 'salt'; |
|||
|
|||
var res = pbkdf2(key, salt, 2, 64); |
|||
res.toString('hex').should.equal('e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e'); |
|||
}); |
|||
|
|||
it('passes test vector 3', function() { |
|||
var key = 'password'; |
|||
var salt = 'salt'; |
|||
|
|||
var res = pbkdf2(key, salt, 4096, 64); |
|||
res.toString('hex').should.equal('d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5'); |
|||
}); |
|||
|
|||
it('passes test vector 4', function() { |
|||
var key = 'passwordPASSWORDpassword'; |
|||
var salt = 'saltSALTsaltSALTsaltSALTsaltSALTsalt'; |
|||
|
|||
var res = pbkdf2(key, salt, 4096, 64); |
|||
res.toString('hex').should.equal('8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8'); |
|||
}); |
|||
}); |
@ -1,2 +1,2 @@ |
|||
--recursive |
|||
--timeout 5000 |
|||
--timeout 7000 |
|||
|
Loading…
Reference in new issue