Skip to content

Commit

Permalink
Fix coding style: curly + Promise handling
Browse files Browse the repository at this point in the history
  • Loading branch information
junderw committed Aug 29, 2020
1 parent 8461e83 commit 1d063b6
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 66 deletions.
79 changes: 49 additions & 30 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,26 @@ const INVALID_ENTROPY = 'Invalid entropy';
const INVALID_CHECKSUM = 'Invalid mnemonic checksum';
const WORDLIST_REQUIRED = 'A wordlist is required but a default could not be found.\n' +
'Please explicitly pass a 2048 word array explicitly.';
function pbkdf2Promise(password, saltMixin, iterations, keylen, digest) {
return Promise.resolve().then(() => new Promise((resolve, reject) => {
const callback = (err, derivedKey) => {
if (err) {
return reject(err);
}
else {
return resolve(derivedKey);
}
};
pbkdf2_1.pbkdf2(password, saltMixin, iterations, keylen, digest, callback);
}));
}
function normalize(str) {
return (str || '').normalize('NFKD');
}
function lpad(str, padString, length) {
while (str.length < length)
while (str.length < length) {
str = padString + str;
}
return str;
}
function binaryToByte(bin) {
Expand All @@ -42,20 +56,10 @@ function mnemonicToSeedSync(mnemonic, password) {
}
exports.mnemonicToSeedSync = mnemonicToSeedSync;
function mnemonicToSeed(mnemonic, password) {
return new Promise((resolve, reject) => {
try {
const mnemonicBuffer = Buffer.from(normalize(mnemonic), 'utf8');
const saltBuffer = Buffer.from(salt(normalize(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);
}
return Promise.resolve().then(() => {
const mnemonicBuffer = Buffer.from(normalize(mnemonic), 'utf8');
const saltBuffer = Buffer.from(salt(normalize(password)), 'utf8');
return pbkdf2Promise(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512');
});
}
exports.mnemonicToSeed = mnemonicToSeed;
Expand All @@ -65,14 +69,16 @@ function mnemonicToEntropy(mnemonic, wordlist) {
throw new Error(WORDLIST_REQUIRED);
}
const words = normalize(mnemonic).split(' ');
if (words.length % 3 !== 0)
if (words.length % 3 !== 0) {
throw new Error(INVALID_MNEMONIC);
}
// convert word indices to 11 bit binary strings
const bits = words
.map((word) => {
const index = wordlist.indexOf(word);
if (index === -1)
if (index === -1) {
throw new Error(INVALID_MNEMONIC);
}
return lpad(index.toString(2), '0', 11);
})
.join('');
Expand All @@ -82,33 +88,41 @@ function mnemonicToEntropy(mnemonic, wordlist) {
const checksumBits = bits.slice(dividerIndex);
// calculate the checksum and compare
const entropyBytes = entropyBits.match(/(.{1,8})/g).map(binaryToByte);
if (entropyBytes.length < 16)
if (entropyBytes.length < 16) {
throw new Error(INVALID_ENTROPY);
if (entropyBytes.length > 32)
}
if (entropyBytes.length > 32) {
throw new Error(INVALID_ENTROPY);
if (entropyBytes.length % 4 !== 0)
}
if (entropyBytes.length % 4 !== 0) {
throw new Error(INVALID_ENTROPY);
}
const entropy = Buffer.from(entropyBytes);
const newChecksum = deriveChecksumBits(entropy);
if (newChecksum !== checksumBits)
if (newChecksum !== checksumBits) {
throw new Error(INVALID_CHECKSUM);
}
return entropy.toString('hex');
}
exports.mnemonicToEntropy = mnemonicToEntropy;
function entropyToMnemonic(entropy, wordlist) {
if (!Buffer.isBuffer(entropy))
if (!Buffer.isBuffer(entropy)) {
entropy = Buffer.from(entropy, 'hex');
}
wordlist = wordlist || DEFAULT_WORDLIST;
if (!wordlist) {
throw new Error(WORDLIST_REQUIRED);
}
// 128 <= ENT <= 256
if (entropy.length < 16)
if (entropy.length < 16) {
throw new TypeError(INVALID_ENTROPY);
if (entropy.length > 32)
}
if (entropy.length > 32) {
throw new TypeError(INVALID_ENTROPY);
if (entropy.length % 4 !== 0)
}
if (entropy.length % 4 !== 0) {
throw new TypeError(INVALID_ENTROPY);
}
const entropyBits = bytesToBinary(Array.from(entropy));
const checksumBits = deriveChecksumBits(entropy);
const bits = entropyBits + checksumBits;
Expand All @@ -124,8 +138,9 @@ function entropyToMnemonic(entropy, wordlist) {
exports.entropyToMnemonic = entropyToMnemonic;
function generateMnemonic(strength, rng, wordlist) {
strength = strength || 128;
if (strength % 32 !== 0)
if (strength % 32 !== 0) {
throw new TypeError(INVALID_ENTROPY);
}
rng = rng || randomBytes;
return entropyToMnemonic(rng(strength / 8), wordlist);
}
Expand All @@ -142,18 +157,22 @@ function validateMnemonic(mnemonic, wordlist) {
exports.validateMnemonic = validateMnemonic;
function setDefaultWordlist(language) {
const result = _wordlists_1.wordlists[language];
if (result)
if (result) {
DEFAULT_WORDLIST = result;
else
}
else {
throw new Error('Could not find wordlist for language "' + language + '"');
}
}
exports.setDefaultWordlist = setDefaultWordlist;
function getDefaultWordlist() {
if (!DEFAULT_WORDLIST)
if (!DEFAULT_WORDLIST) {
throw new Error('No Default Wordlist set');
}
return Object.keys(_wordlists_1.wordlists).filter((lang) => {
if (lang === 'JA' || lang === 'EN')
if (lang === 'JA' || lang === 'EN') {
return false;
}
return _wordlists_1.wordlists[lang].every((word, index) => word === DEFAULT_WORDLIST[index]);
})[0];
}
Expand Down
110 changes: 75 additions & 35 deletions ts_src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,38 @@ const WORDLIST_REQUIRED =
'A wordlist is required but a default could not be found.\n' +
'Please explicitly pass a 2048 word array explicitly.';

function pbkdf2Promise(
password: string | Buffer,
saltMixin: string | Buffer,
iterations: number,
keylen: number,
digest: string,
): Promise<Buffer> {
return Promise.resolve().then(
(): Promise<Buffer> =>
new Promise(
(resolve, reject): void => {
const callback = (err: Error, derivedKey: Buffer): void => {
if (err) {
return reject(err);
} else {
return resolve(derivedKey);
}
};
pbkdf2(password, saltMixin, iterations, keylen, digest, callback);
},
),
);
}

function normalize(str?: string): string {
return (str || '').normalize('NFKD');
}

function lpad(str: string, padString: string, length: number): string {
while (str.length < length) str = padString + str;
while (str.length < length) {
str = padString + str;
}
return str;
}

Expand Down Expand Up @@ -57,25 +83,11 @@ export function mnemonicToSeed(
mnemonic: string,
password?: string,
): Promise<Buffer> {
return new Promise(
(resolve, reject): void => {
try {
const mnemonicBuffer = Buffer.from(normalize(mnemonic), 'utf8');
const saltBuffer = Buffer.from(salt(normalize(password)), 'utf8');
pbkdf2(
mnemonicBuffer,
saltBuffer,
2048,
64,
'sha512',
(err: Error, data: Buffer): void => {
if (err) return reject(err);
else return resolve(data);
},
);
} catch (error) {
return reject(error);
}
return Promise.resolve().then(
(): Promise<Buffer> => {
const mnemonicBuffer = Buffer.from(normalize(mnemonic), 'utf8');
const saltBuffer = Buffer.from(salt(normalize(password)), 'utf8');
return pbkdf2Promise(mnemonicBuffer, saltBuffer, 2048, 64, 'sha512');
},
);
}
Expand All @@ -90,14 +102,18 @@ export function mnemonicToEntropy(
}

const words = normalize(mnemonic).split(' ');
if (words.length % 3 !== 0) throw new Error(INVALID_MNEMONIC);
if (words.length % 3 !== 0) {
throw new Error(INVALID_MNEMONIC);
}

// convert word indices to 11 bit binary strings
const bits = words
.map(
(word: string): string => {
const index = wordlist!.indexOf(word);
if (index === -1) throw new Error(INVALID_MNEMONIC);
if (index === -1) {
throw new Error(INVALID_MNEMONIC);
}

return lpad(index.toString(2), '0', 11);
},
Expand All @@ -111,13 +127,21 @@ export function mnemonicToEntropy(

// calculate the checksum and compare
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);
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);
}

const entropy = Buffer.from(entropyBytes);
const newChecksum = deriveChecksumBits(entropy);
if (newChecksum !== checksumBits) throw new Error(INVALID_CHECKSUM);
if (newChecksum !== checksumBits) {
throw new Error(INVALID_CHECKSUM);
}

return entropy.toString('hex');
}
Expand All @@ -126,16 +150,24 @@ export function entropyToMnemonic(
entropy: Buffer | string,
wordlist?: string[],
): string {
if (!Buffer.isBuffer(entropy)) entropy = Buffer.from(entropy, 'hex');
if (!Buffer.isBuffer(entropy)) {
entropy = Buffer.from(entropy, 'hex');
}
wordlist = wordlist || DEFAULT_WORDLIST;
if (!wordlist) {
throw new Error(WORDLIST_REQUIRED);
}

// 128 <= ENT <= 256
if (entropy.length < 16) throw new TypeError(INVALID_ENTROPY);
if (entropy.length > 32) throw new TypeError(INVALID_ENTROPY);
if (entropy.length % 4 !== 0) throw new TypeError(INVALID_ENTROPY);
if (entropy.length < 16) {
throw new TypeError(INVALID_ENTROPY);
}
if (entropy.length > 32) {
throw new TypeError(INVALID_ENTROPY);
}
if (entropy.length % 4 !== 0) {
throw new TypeError(INVALID_ENTROPY);
}

const entropyBits = bytesToBinary(Array.from(entropy));
const checksumBits = deriveChecksumBits(entropy);
Expand All @@ -160,7 +192,9 @@ export function generateMnemonic(
wordlist?: string[],
): string {
strength = strength || 128;
if (strength % 32 !== 0) throw new TypeError(INVALID_ENTROPY);
if (strength % 32 !== 0) {
throw new TypeError(INVALID_ENTROPY);
}
rng = rng || randomBytes;

return entropyToMnemonic(rng(strength / 8), wordlist);
Expand All @@ -181,16 +215,22 @@ export function validateMnemonic(

export function setDefaultWordlist(language: string): void {
const result = wordlists[language];
if (result) DEFAULT_WORDLIST = result;
else
if (result) {
DEFAULT_WORDLIST = result;
} else {
throw new Error('Could not find wordlist for language "' + language + '"');
}
}

export function getDefaultWordlist(): string {
if (!DEFAULT_WORDLIST) throw new Error('No Default Wordlist set');
if (!DEFAULT_WORDLIST) {
throw new Error('No Default Wordlist set');
}
return Object.keys(wordlists).filter(
(lang: string): boolean => {
if (lang === 'JA' || lang === 'EN') return false;
if (lang === 'JA' || lang === 'EN') {
return false;
}
return wordlists[lang].every(
(word: string, index: number): boolean =>
word === DEFAULT_WORDLIST![index],
Expand Down
2 changes: 1 addition & 1 deletion tslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"extends": ["tslint:recommended"],
"rules": {
"arrow-parens": [true, "ban-single-arg-parens"],
"curly": false,
"curly": true,
"indent": [
true,
"spaces",
Expand Down

0 comments on commit 1d063b6

Please sign in to comment.