diff --git a/packages/primitives/src/mnemonic.ts b/packages/primitives/src/mnemonic.ts index de746e9..ea44783 100644 --- a/packages/primitives/src/mnemonic.ts +++ b/packages/primitives/src/mnemonic.ts @@ -74,7 +74,10 @@ export class Mnemonic { * * @returns Instance of Mnemonic. */ - public static fromEntropy(entropy: Uint8Array, wordList: Array = bip39WordListEnglish) { + public static fromEntropy( + entropy: Uint8Array, + wordList: Array = bip39WordListEnglish, + ) { const mnemonic = encodeBip39MnemonicNonStandard(entropy, wordList); if (typeof mnemonic === 'string') { @@ -167,6 +170,18 @@ export class Mnemonic { ); } + // Ensure the checksum is correct by attempting to decode the mnemonic. + // NOTE: LibAuth doesn't currently expose a convenient function to check this by itself. + const decodeResult = decodeBip39MnemonicNonStandard( + mnemonicRaw.words.join(' '), + wordList, + ); + + // NOTE: The above function will return a string if there is an error. + if (typeof decodeResult === 'string') { + throw new Error(decodeResult); + } + return new this(mnemonicRaw); } diff --git a/packages/primitives/tests/mnemonic.spec.ts b/packages/primitives/tests/mnemonic.spec.ts index b6c4975..7f07d40 100644 --- a/packages/primitives/tests/mnemonic.spec.ts +++ b/packages/primitives/tests/mnemonic.spec.ts @@ -327,4 +327,23 @@ describe('Fail cases', () => { ]); }).toThrow(); }); + + it('fromWord should fail if checksum is invalid', () => { + expect(() => { + // Invalid word "fnord". + Mnemonic.fromWords([ + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'abandon', + 'banana', + ]); + }).toThrow(); + }); });