|
| 1 | +"""Mnemonic helpers should follow BIP39 reference vectors.""" |
| 2 | +from __future__ import annotations |
| 3 | + |
| 4 | +import pytest |
| 5 | + |
| 6 | +from libcrypto.mnemonic import ( |
| 7 | + InvalidMnemonicError, |
| 8 | + generate_mnemonic, |
| 9 | + mnemonic_to_entropy, |
| 10 | + mnemonic_to_seed, |
| 11 | + validate_mnemonic, |
| 12 | +) |
| 13 | + |
| 14 | + |
| 15 | +REFERENCE_MNEMONIC = "abandon " * 11 + "about" |
| 16 | +REFERENCE_MNEMONIC = REFERENCE_MNEMONIC.strip() |
| 17 | +REFERENCE_SEED = ( |
| 18 | + "c55257c360c07c72029aebc1b53c05ed0362ada38ead3e3e9efa3708e5349553" |
| 19 | + "1f09a6987599d18264c1e1c92f2cf141630c7a3c4ab7c81b2f001698e7463b04" |
| 20 | +) |
| 21 | + |
| 22 | + |
| 23 | +def test_mnemonic_to_seed_matches_bip39_vector() -> None: |
| 24 | + """Mnemonic to seed must reproduce the official BIP39 test vector.""" |
| 25 | + seed = mnemonic_to_seed(REFERENCE_MNEMONIC, passphrase="TREZOR") |
| 26 | + |
| 27 | + assert seed.hex() == REFERENCE_SEED |
| 28 | + |
| 29 | + |
| 30 | +def test_validate_mnemonic_detects_invalid_word() -> None: |
| 31 | + """An unknown word should result in validation failure.""" |
| 32 | + invalid_phrase = REFERENCE_MNEMONIC.replace("about", "ab0ut") |
| 33 | + |
| 34 | + assert validate_mnemonic(invalid_phrase) is False |
| 35 | + |
| 36 | + |
| 37 | +def test_mnemonic_to_entropy_invalid_checksum() -> None: |
| 38 | + """Changing the final word should trigger a checksum error.""" |
| 39 | + altered_phrase = REFERENCE_MNEMONIC.replace("about", "absorb") |
| 40 | + |
| 41 | + with pytest.raises(InvalidMnemonicError): |
| 42 | + mnemonic_to_entropy(altered_phrase) |
| 43 | + |
| 44 | + |
| 45 | +def test_generate_mnemonic_default_length() -> None: |
| 46 | + """Generated mnemonics should produce 12-word phrases by default.""" |
| 47 | + mnemonic = generate_mnemonic() |
| 48 | + |
| 49 | + assert len(mnemonic.split()) == 12 |
| 50 | + assert validate_mnemonic(mnemonic) is True |
0 commit comments