Add Hypothesis fuzz test for EncryptionManager

This commit is contained in:
thePR0M3TH3AN
2025-07-13 13:51:15 -04:00
parent 6d092d08ba
commit f1018a5c2b
2 changed files with 68 additions and 0 deletions

View File

@@ -423,6 +423,11 @@ pip install -r src/requirements.txt
pytest -vv
```
`test_fuzz_key_derivation.py` uses Hypothesis to generate random passwords,
seeds and configuration data. It performs round-trip encryption tests with the
`EncryptionManager` to catch edge cases automatically. These fuzz tests run in
CI alongside the rest of the suite.
### Exploring Nostr Index Size Limits
`test_nostr_index_size.py` demonstrates how SeedPass rotates snapshots after too many delta events.

View File

@@ -0,0 +1,63 @@
import os
from pathlib import Path
from hypothesis import given, strategies as st, settings, HealthCheck
from mnemonic import Mnemonic
from utils.key_derivation import (
derive_key_from_password,
derive_key_from_password_argon2,
derive_index_key,
)
from password_manager.encryption import EncryptionManager
cfg_values = st.one_of(
st.integers(min_value=0, max_value=100),
st.text(min_size=0, max_size=20),
st.booleans(),
)
@given(
password=st.text(min_size=8, max_size=32),
seed_bytes=st.binary(min_size=16, max_size=16),
config=st.dictionaries(st.text(min_size=1, max_size=10), cfg_values, max_size=5),
mode=st.sampled_from(["pbkdf2", "argon2"]),
)
@settings(
deadline=None,
max_examples=20,
suppress_health_check=[HealthCheck.function_scoped_fixture],
)
def test_fuzz_key_round_trip(password, seed_bytes, config, mode, tmp_path: Path):
"""Ensure EncryptionManager round-trips arbitrary data."""
seed_phrase = Mnemonic("english").to_mnemonic(seed_bytes)
if mode == "argon2":
key = derive_key_from_password_argon2(
password, time_cost=1, memory_cost=8, parallelism=1
)
else:
key = derive_key_from_password(password, iterations=1)
enc_mgr = EncryptionManager(key, tmp_path)
# Parent seed round trip
enc_mgr.encrypt_parent_seed(seed_phrase)
assert enc_mgr.decrypt_parent_seed() == seed_phrase
# JSON data round trip
enc_mgr.save_json_data(config, Path("config.enc"))
loaded = enc_mgr.load_json_data(Path("config.enc"))
assert loaded == config
# Binary data round trip
blob = os.urandom(32)
enc_mgr.encrypt_and_save_file(blob, Path("blob.enc"))
assert enc_mgr.decrypt_file(Path("blob.enc")) == blob
# Index key derived from seed also decrypts
index_key = derive_index_key(seed_phrase)
idx_mgr = EncryptionManager(index_key, tmp_path)
idx_mgr.save_json_data(config)
assert idx_mgr.load_json_data() == config