You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
7.3 KiB
225 lines
7.3 KiB
'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);
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|