|
|
@ -1,4 +1,12 @@ |
|
|
|
"use strict"; |
|
|
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { |
|
|
|
return new (P || (P = Promise))(function (resolve, reject) { |
|
|
|
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } |
|
|
|
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } |
|
|
|
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } |
|
|
|
step((generator = generator.apply(thisArg, _arguments || [])).next()); |
|
|
|
}); |
|
|
|
}; |
|
|
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
|
|
const createHash = require("create-hash"); |
|
|
|
const pbkdf2_1 = require("pbkdf2"); |
|
|
@ -27,16 +35,12 @@ function binaryToByte(bin) { |
|
|
|
return parseInt(bin, 2); |
|
|
|
} |
|
|
|
function bytesToBinary(bytes) { |
|
|
|
return bytes |
|
|
|
.map(function (x) { |
|
|
|
return lpad(x.toString(2), '0', 8); |
|
|
|
}) |
|
|
|
.join(''); |
|
|
|
return bytes.map(x => lpad(x.toString(2), '0', 8)).join(''); |
|
|
|
} |
|
|
|
function deriveChecksumBits(entropyBuffer) { |
|
|
|
var ENT = entropyBuffer.length * 8; |
|
|
|
var CS = ENT / 32; |
|
|
|
var hash = createHash('sha256') |
|
|
|
const ENT = entropyBuffer.length * 8; |
|
|
|
const CS = ENT / 32; |
|
|
|
const hash = createHash('sha256') |
|
|
|
.update(entropyBuffer) |
|
|
|
.digest(); |
|
|
|
return bytesToBinary([].slice.call(hash)).slice(0, CS); |
|
|
@ -53,55 +57,56 @@ function mnemonicToSeedHex(mnemonic, password) { |
|
|
|
return mnemonicToSeed(mnemonic, password).toString('hex'); |
|
|
|
} |
|
|
|
function mnemonicToSeedAsync(mnemonic, password) { |
|
|
|
return new Promise(function (resolve, reject) { |
|
|
|
return new Promise((resolve, reject) => { |
|
|
|
try { |
|
|
|
var mnemonicBuffer = Buffer.from(unorm.nfkd(mnemonic), 'utf8'); |
|
|
|
var saltBuffer = Buffer.from(salt(unorm.nfkd(password)), 'utf8'); |
|
|
|
const mnemonicBuffer = Buffer.from(unorm.nfkd(mnemonic), 'utf8'); |
|
|
|
const saltBuffer = Buffer.from(salt(unorm.nfkd(password)), 'utf8'); |
|
|
|
pbkdf2_1.pbkdf2(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512', (err, data) => { |
|
|
|
if (err) |
|
|
|
return reject(err); |
|
|
|
else |
|
|
|
return resolve(data); |
|
|
|
}); |
|
|
|
} |
|
|
|
catch (error) { |
|
|
|
return reject(error); |
|
|
|
} |
|
|
|
pbkdf2_1.pbkdf2(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512', function (err, data) { |
|
|
|
if (err) |
|
|
|
return reject(err); |
|
|
|
else |
|
|
|
return resolve(data); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
function mnemonicToSeedHexAsync(mnemonic, password) { |
|
|
|
return mnemonicToSeedAsync(mnemonic, password).then(function (buf) { |
|
|
|
return __awaiter(this, void 0, void 0, function* () { |
|
|
|
const buf = yield mnemonicToSeedAsync(mnemonic, password); |
|
|
|
return buf.toString('hex'); |
|
|
|
}); |
|
|
|
} |
|
|
|
function mnemonicToEntropy(mnemonic, wordlist) { |
|
|
|
wordlist = wordlist || DEFAULT_WORDLIST; |
|
|
|
var words = unorm.nfkd(mnemonic).split(' '); |
|
|
|
const words = unorm.nfkd(mnemonic).split(' '); |
|
|
|
if (words.length % 3 !== 0) |
|
|
|
throw new Error(INVALID_MNEMONIC); |
|
|
|
// convert word indices to 11 bit binary strings
|
|
|
|
var bits = words |
|
|
|
.map(function (word) { |
|
|
|
var index = wordlist.indexOf(word); |
|
|
|
const bits = words |
|
|
|
.map(word => { |
|
|
|
const index = wordlist.indexOf(word); |
|
|
|
if (index === -1) |
|
|
|
throw new Error(INVALID_MNEMONIC); |
|
|
|
return lpad(index.toString(2), '0', 11); |
|
|
|
}) |
|
|
|
.join(''); |
|
|
|
// split the binary string into ENT/CS
|
|
|
|
var dividerIndex = Math.floor(bits.length / 33) * 32; |
|
|
|
var entropyBits = bits.slice(0, dividerIndex); |
|
|
|
var checksumBits = bits.slice(dividerIndex); |
|
|
|
const dividerIndex = Math.floor(bits.length / 33) * 32; |
|
|
|
const entropyBits = bits.slice(0, dividerIndex); |
|
|
|
const checksumBits = bits.slice(dividerIndex); |
|
|
|
// calculate the checksum and compare
|
|
|
|
var entropyBytes = entropyBits.match(/(.{1,8})/g).map(binaryToByte); |
|
|
|
const entropyBytes = entropyBits.match(/(.{1,8})/g).map(binaryToByte); |
|
|
|
if (entropyBytes.length < 16) |
|
|
|
throw new Error(INVALID_ENTROPY); |
|
|
|
if (entropyBytes.length > 32) |
|
|
|
throw new Error(INVALID_ENTROPY); |
|
|
|
if (entropyBytes.length % 4 !== 0) |
|
|
|
throw new Error(INVALID_ENTROPY); |
|
|
|
var entropy = Buffer.from(entropyBytes); |
|
|
|
var newChecksum = deriveChecksumBits(entropy); |
|
|
|
const entropy = Buffer.from(entropyBytes); |
|
|
|
const newChecksum = deriveChecksumBits(entropy); |
|
|
|
if (newChecksum !== checksumBits) |
|
|
|
throw new Error(INVALID_CHECKSUM); |
|
|
|
return entropy.toString('hex'); |
|
|
@ -117,12 +122,12 @@ function entropyToMnemonic(entropy, wordlist) { |
|
|
|
throw new TypeError(INVALID_ENTROPY); |
|
|
|
if (entropy.length % 4 !== 0) |
|
|
|
throw new TypeError(INVALID_ENTROPY); |
|
|
|
var entropyBits = bytesToBinary([].slice.call(entropy)); |
|
|
|
var checksumBits = deriveChecksumBits(entropy); |
|
|
|
var bits = entropyBits + checksumBits; |
|
|
|
var chunks = bits.match(/(.{1,11})/g); |
|
|
|
var words = chunks.map(function (binary) { |
|
|
|
var index = binaryToByte(binary); |
|
|
|
const entropyBits = bytesToBinary([].slice.call(entropy)); |
|
|
|
const checksumBits = deriveChecksumBits(entropy); |
|
|
|
const bits = entropyBits + checksumBits; |
|
|
|
const chunks = bits.match(/(.{1,11})/g); |
|
|
|
const words = chunks.map(binary => { |
|
|
|
const index = binaryToByte(binary); |
|
|
|
return wordlist[index]; |
|
|
|
}); |
|
|
|
return wordlist === JAPANESE_WORDLIST |
|
|
@ -146,14 +151,14 @@ function validateMnemonic(mnemonic, wordlist) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
module.exports = { |
|
|
|
mnemonicToSeed: mnemonicToSeed, |
|
|
|
mnemonicToSeedAsync: mnemonicToSeedAsync, |
|
|
|
mnemonicToSeedHex: mnemonicToSeedHex, |
|
|
|
mnemonicToSeedHexAsync: mnemonicToSeedHexAsync, |
|
|
|
mnemonicToEntropy: mnemonicToEntropy, |
|
|
|
entropyToMnemonic: entropyToMnemonic, |
|
|
|
generateMnemonic: generateMnemonic, |
|
|
|
validateMnemonic: validateMnemonic, |
|
|
|
mnemonicToSeed, |
|
|
|
mnemonicToSeedAsync, |
|
|
|
mnemonicToSeedHex, |
|
|
|
mnemonicToSeedHexAsync, |
|
|
|
mnemonicToEntropy, |
|
|
|
entropyToMnemonic, |
|
|
|
generateMnemonic, |
|
|
|
validateMnemonic, |
|
|
|
wordlists: { |
|
|
|
EN: ENGLISH_WORDLIST, |
|
|
|
JA: JAPANESE_WORDLIST, |
|
|
|