bip39 again.
This commit is contained in:
parent
91fd1dc60d
commit
667fa4b796
231
lib/bcoin/hd.js
231
lib/bcoin/hd.js
@ -198,118 +198,6 @@ Mnemonic.fromOptions = function fromOptions(options) {
|
|||||||
return new Mnemonic().fromOptions(options);
|
return new Mnemonic().fromOptions(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject properties from entropy.
|
|
||||||
* @private
|
|
||||||
* @param {Buffer} entropy
|
|
||||||
* @param {String?} lang
|
|
||||||
*/
|
|
||||||
|
|
||||||
Mnemonic.prototype.fromEntropy = function fromEntropy(entropy, lang) {
|
|
||||||
assert(Buffer.isBuffer(entropy));
|
|
||||||
assert(entropy.length * 8 >= 128);
|
|
||||||
assert((entropy.length * 8) % 32 === 0);
|
|
||||||
assert(!lang || Mnemonic.languages.indexOf(lang) !== -1);
|
|
||||||
|
|
||||||
this.entropy = entropy;
|
|
||||||
this.bits = entropy.length * 8;
|
|
||||||
|
|
||||||
if (lang)
|
|
||||||
this.language = lang;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate mnemonic from entropy.
|
|
||||||
* @param {Buffer} entropy
|
|
||||||
* @param {String?} lang
|
|
||||||
* @returns {Mnemonic}
|
|
||||||
*/
|
|
||||||
|
|
||||||
Mnemonic.fromEntropy = function fromEntropy(entropy, lang) {
|
|
||||||
return new Mnemonic().fromEntropy(entropy, lang);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject properties from phrase.
|
|
||||||
* @private
|
|
||||||
* @param {String} phrase
|
|
||||||
*/
|
|
||||||
|
|
||||||
Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
|
|
||||||
var i, j, bits, pos, oct, bit, b, ent, entropy, lang;
|
|
||||||
var chk, word, wordlist, index, cbits, cbytes, words;
|
|
||||||
|
|
||||||
assert(typeof phrase === 'string');
|
|
||||||
|
|
||||||
words = phrase.split(/[ \u3000]+/);
|
|
||||||
bits = words.length * 11;
|
|
||||||
lang = Mnemonic.getLanguage(words[0]);
|
|
||||||
ent = new Buffer(Math.ceil(bits / 8));
|
|
||||||
wordlist = Mnemonic.getWordlist(lang);
|
|
||||||
|
|
||||||
ent.fill(0);
|
|
||||||
|
|
||||||
for (i = 0; i < words.length; i++) {
|
|
||||||
word = words[i];
|
|
||||||
index = wordlist.indexOf(word);
|
|
||||||
|
|
||||||
if (index === -1)
|
|
||||||
throw new Error('Could not find word.');
|
|
||||||
|
|
||||||
for (j = 0; j < 11; j++) {
|
|
||||||
pos = i * 11 + j;
|
|
||||||
bit = pos % 8;
|
|
||||||
oct = (pos - bit) / 8;
|
|
||||||
b = (index >>> (10 - j)) & 1;
|
|
||||||
ent[oct] |= b << (7 - bit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checksum bits:
|
|
||||||
cbits = bits % 32;
|
|
||||||
cbytes = Math.ceil(cbits / 8);
|
|
||||||
|
|
||||||
entropy = ent.slice(0, ent.length - cbytes);
|
|
||||||
|
|
||||||
ent = ent.slice(ent.length - cbytes);
|
|
||||||
chk = utils.sha256(entropy);
|
|
||||||
|
|
||||||
for (i = 0; i < cbits; i++) {
|
|
||||||
bit = i % 8;
|
|
||||||
oct = (i - bit) / 8;
|
|
||||||
b = (ent[oct] >>> (7 - bit)) & 1;
|
|
||||||
j = (chk[oct] >>> (7 - bit)) & 1;
|
|
||||||
if (b !== j)
|
|
||||||
throw new Error('Invalid checksum.');
|
|
||||||
}
|
|
||||||
|
|
||||||
bits -= cbits;
|
|
||||||
|
|
||||||
assert(bits / 8 === entropy.length);
|
|
||||||
assert(bits >= 128);
|
|
||||||
assert(bits % 32 === 0);
|
|
||||||
|
|
||||||
this.bits = bits;
|
|
||||||
this.language = lang;
|
|
||||||
this.entropy = entropy;
|
|
||||||
this.phrase = phrase;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate mnemonic from a phrase (validates checksum).
|
|
||||||
* @param {String} phrase
|
|
||||||
* @returns {Mnemonic}
|
|
||||||
* @throws on bad checksum
|
|
||||||
*/
|
|
||||||
|
|
||||||
Mnemonic.fromPhrase = function fromPhrase(phrase) {
|
|
||||||
return new Mnemonic().fromPhrase(phrase);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the seed.
|
* Generate the seed.
|
||||||
* @param {String?} passphrase
|
* @param {String?} passphrase
|
||||||
@ -407,6 +295,117 @@ Mnemonic.prototype.getPhrase = function getPhrase() {
|
|||||||
return phrase;
|
return phrase;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from phrase.
|
||||||
|
* @private
|
||||||
|
* @param {String} phrase
|
||||||
|
*/
|
||||||
|
|
||||||
|
Mnemonic.prototype.fromPhrase = function fromPhrase(phrase) {
|
||||||
|
var i, j, bits, pos, oct, bit, b, ent, entropy, lang;
|
||||||
|
var chk, word, wordlist, index, cbits, cbytes, words;
|
||||||
|
|
||||||
|
assert(typeof phrase === 'string');
|
||||||
|
|
||||||
|
words = phrase.split(/[ \u3000]+/);
|
||||||
|
bits = words.length * 11;
|
||||||
|
lang = Mnemonic.getLanguage(words[0]);
|
||||||
|
ent = new Buffer(Math.ceil(bits / 8));
|
||||||
|
wordlist = Mnemonic.getWordlist(lang);
|
||||||
|
|
||||||
|
ent.fill(0);
|
||||||
|
|
||||||
|
for (i = 0; i < words.length; i++) {
|
||||||
|
word = words[i];
|
||||||
|
index = wordlist.indexOf(word);
|
||||||
|
|
||||||
|
if (index === -1)
|
||||||
|
throw new Error('Could not find word.');
|
||||||
|
|
||||||
|
for (j = 0; j < 11; j++) {
|
||||||
|
pos = i * 11 + j;
|
||||||
|
bit = pos % 8;
|
||||||
|
oct = (pos - bit) / 8;
|
||||||
|
b = (index >>> (10 - j)) & 1;
|
||||||
|
ent[oct] |= b << (7 - bit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checksum bits:
|
||||||
|
cbits = bits % 32;
|
||||||
|
cbytes = Math.ceil(cbits / 8);
|
||||||
|
|
||||||
|
entropy = ent.slice(0, ent.length - cbytes);
|
||||||
|
ent = ent.slice(ent.length - cbytes);
|
||||||
|
chk = utils.sha256(entropy);
|
||||||
|
|
||||||
|
for (i = 0; i < cbits; i++) {
|
||||||
|
bit = i % 8;
|
||||||
|
oct = (i - bit) / 8;
|
||||||
|
b = (ent[oct] >>> (7 - bit)) & 1;
|
||||||
|
j = (chk[oct] >>> (7 - bit)) & 1;
|
||||||
|
if (b !== j)
|
||||||
|
throw new Error('Invalid checksum.');
|
||||||
|
}
|
||||||
|
|
||||||
|
bits -= cbits;
|
||||||
|
|
||||||
|
assert(bits / 8 === entropy.length);
|
||||||
|
assert(bits >= 128);
|
||||||
|
assert(bits % 32 === 0);
|
||||||
|
|
||||||
|
this.bits = bits;
|
||||||
|
this.language = lang;
|
||||||
|
this.entropy = entropy;
|
||||||
|
this.phrase = phrase;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate mnemonic from a phrase (validates checksum).
|
||||||
|
* @param {String} phrase
|
||||||
|
* @returns {Mnemonic}
|
||||||
|
* @throws on bad checksum
|
||||||
|
*/
|
||||||
|
|
||||||
|
Mnemonic.fromPhrase = function fromPhrase(phrase) {
|
||||||
|
return new Mnemonic().fromPhrase(phrase);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inject properties from entropy.
|
||||||
|
* @private
|
||||||
|
* @param {Buffer} entropy
|
||||||
|
* @param {String?} lang
|
||||||
|
*/
|
||||||
|
|
||||||
|
Mnemonic.prototype.fromEntropy = function fromEntropy(entropy, lang) {
|
||||||
|
assert(Buffer.isBuffer(entropy));
|
||||||
|
assert(entropy.length * 8 >= 128);
|
||||||
|
assert((entropy.length * 8) % 32 === 0);
|
||||||
|
assert(!lang || Mnemonic.languages.indexOf(lang) !== -1);
|
||||||
|
|
||||||
|
this.entropy = entropy;
|
||||||
|
this.bits = entropy.length * 8;
|
||||||
|
|
||||||
|
if (lang)
|
||||||
|
this.language = lang;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiate mnemonic from entropy.
|
||||||
|
* @param {Buffer} entropy
|
||||||
|
* @param {String?} lang
|
||||||
|
* @returns {Mnemonic}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Mnemonic.fromEntropy = function fromEntropy(entropy, lang) {
|
||||||
|
return new Mnemonic().fromEntropy(entropy, lang);
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine a single word's language.
|
* Determine a single word's language.
|
||||||
* @param {String} word
|
* @param {String} word
|
||||||
@ -510,9 +509,12 @@ Mnemonic.fromJSON = function fromJSON(json) {
|
|||||||
|
|
||||||
Mnemonic.prototype.toRaw = function toRaw(writer) {
|
Mnemonic.prototype.toRaw = function toRaw(writer) {
|
||||||
var p = new BufferWriter(writer);
|
var p = new BufferWriter(writer);
|
||||||
|
var lang = Mnemonic.languages.indexOf(this.language);
|
||||||
|
|
||||||
|
assert(lang !== -1);
|
||||||
|
|
||||||
p.writeU16(this.bits);
|
p.writeU16(this.bits);
|
||||||
p.writeVarString(this.language, 'utf8');
|
p.writeU8(lang);
|
||||||
p.writeBytes(this.getEntropy());
|
p.writeBytes(this.getEntropy());
|
||||||
p.writeVarString(this.getPhrase(), 'utf8');
|
p.writeVarString(this.getPhrase(), 'utf8');
|
||||||
p.writeVarString(this.passphrase, 'utf8');
|
p.writeVarString(this.passphrase, 'utf8');
|
||||||
@ -533,11 +535,12 @@ Mnemonic.prototype.fromRaw = function fromRaw(data) {
|
|||||||
var p = new BufferReader(data);
|
var p = new BufferReader(data);
|
||||||
|
|
||||||
this.bits = p.readU16();
|
this.bits = p.readU16();
|
||||||
this.language = p.readVarString('utf8');
|
this.language = Mnemonic.languages[p.readU8()];
|
||||||
this.entropy = p.readBytes(this.bits / 8);
|
this.entropy = p.readBytes(this.bits / 8);
|
||||||
this.phrase = p.readVarString('utf8');
|
this.phrase = p.readVarString('utf8');
|
||||||
this.passphrase = p.readVarString('utf8');
|
this.passphrase = p.readVarString('utf8');
|
||||||
|
|
||||||
|
assert(this.language);
|
||||||
assert(this.bits >= 128);
|
assert(this.bits >= 128);
|
||||||
assert(this.bits % 32 === 0);
|
assert(this.bits % 32 === 0);
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user