Merge pull request #713 from PR0M3TH3AN/codex/replace-seed-validation-with-bip-39-check

Add BIP-39 seed validation
This commit is contained in:
thePR0M3TH3AN
2025-08-02 21:38:45 -04:00
committed by GitHub
2 changed files with 44 additions and 17 deletions

View File

@@ -24,6 +24,7 @@ from cryptography.exceptions import InvalidTag
from cryptography.fernet import Fernet, InvalidToken
from termcolor import colored
from utils.file_lock import exclusive_lock
from mnemonic import Mnemonic
# Instantiate the logger
logger = logging.getLogger(__name__)
@@ -314,25 +315,21 @@ class EncryptionManager:
)
raise
# ... validate_seed and derive_seed_from_mnemonic can remain the same ...
def validate_seed(self, seed_phrase: str) -> bool:
def validate_seed(self, seed_phrase: str) -> tuple[bool, Optional[str]]:
"""Validate a BIP-39 mnemonic.
Returns a tuple of ``(is_valid, error_message)`` where ``error_message``
is ``None`` when the mnemonic is valid.
"""
try:
words = seed_phrase.split()
if len(words) != 12:
logger.error("Seed phrase does not contain exactly 12 words.")
print(
colored(
"Error: Seed phrase must contain exactly 12 words.",
"red",
)
)
return False
logger.debug("Seed phrase validated successfully.")
return True
if Mnemonic("english").check(seed_phrase):
logger.debug("Seed phrase validated successfully.")
return True, None
logger.error("Seed phrase failed BIP-39 validation.")
return False, "Invalid seed phrase."
except Exception as e:
logging.error(f"Error validating seed phrase: {e}", exc_info=True)
print(colored(f"Error: Failed to validate seed phrase: {e}", "red"))
return False
logger.error(f"Error validating seed phrase: {e}", exc_info=True)
return False, f"Failed to validate seed phrase: {e}"
def derive_seed_from_mnemonic(self, mnemonic: str, passphrase: str = "") -> bytes:
try:

View File

@@ -0,0 +1,30 @@
import sys
from pathlib import Path
import pytest
from cryptography.fernet import Fernet
sys.path.append(str(Path(__file__).resolve().parents[1]))
from seedpass.core.encryption import EncryptionManager
def make_manager(tmp_path):
key = Fernet.generate_key()
return EncryptionManager(key, tmp_path)
def test_validate_seed_valid_mnemonic(tmp_path):
manager = make_manager(tmp_path)
valid = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
is_valid, error = manager.validate_seed(valid)
assert is_valid is True
assert error is None
def test_validate_seed_invalid_mnemonic(tmp_path):
manager = make_manager(tmp_path)
invalid = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon"
is_valid, error = manager.validate_seed(invalid)
assert is_valid is False
assert error == "Invalid seed phrase."