mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2025-09-08 23:38:49 +00:00
86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
import json
|
|
import hashlib
|
|
import hmac
|
|
import queue
|
|
from pathlib import Path
|
|
from types import SimpleNamespace
|
|
|
|
import importlib
|
|
import pytest
|
|
|
|
from seedpass.core.manager import PasswordManager, AuditLogger
|
|
import seedpass.core.manager as manager_module
|
|
|
|
|
|
def test_audit_logger_records_events(monkeypatch, tmp_path):
|
|
monkeypatch.setattr(Path, "home", lambda: tmp_path)
|
|
|
|
pm = PasswordManager.__new__(PasswordManager)
|
|
pm.fingerprint_dir = tmp_path
|
|
pm.current_fingerprint = "user123"
|
|
pm.profile_stack = []
|
|
pm.setup_encryption_manager = lambda *a, **k: None
|
|
pm.initialize_bip85 = lambda: None
|
|
pm.initialize_managers = lambda: None
|
|
pm.update_activity = lambda: None
|
|
pm.verify_password = lambda pw: True
|
|
pm.notifications = queue.Queue()
|
|
pm.parent_seed = "seed phrase"
|
|
pm.config_manager = SimpleNamespace(get_quick_unlock=lambda: True)
|
|
|
|
manager_module.clear_header_with_notification = lambda *a, **k: None
|
|
|
|
pm.unlock_vault(password="pw")
|
|
|
|
dest = tmp_path / "db.json.enc"
|
|
monkeypatch.setattr(manager_module, "export_backup", lambda *a, **k: dest)
|
|
pm.vault = object()
|
|
pm.backup_manager = object()
|
|
monkeypatch.setattr("seedpass.core.manager.confirm_action", lambda *_a, **_k: True)
|
|
pm.handle_export_database(dest)
|
|
|
|
confirms = iter([True, False])
|
|
monkeypatch.setattr(
|
|
"seedpass.core.manager.confirm_action", lambda *_a, **_k: next(confirms)
|
|
)
|
|
pm.encryption_manager = SimpleNamespace(encrypt_and_save_file=lambda *a, **k: None)
|
|
pm.handle_backup_reveal_parent_seed(password="pw")
|
|
|
|
log_path = tmp_path / ".seedpass" / "audit.log"
|
|
lines = [json.loads(l) for l in log_path.read_text().splitlines()]
|
|
events = [e["event"] for e in lines]
|
|
assert "quick_unlock" in events
|
|
assert "backup_export" in events
|
|
assert "seed_reveal" in events
|
|
|
|
|
|
def _verify_chain(path: Path, key: bytes) -> bool:
|
|
prev = "0" * 64
|
|
for line in path.read_text().splitlines():
|
|
data = json.loads(line)
|
|
sig = data.pop("sig")
|
|
payload = json.dumps(data, sort_keys=True, separators=(",", ":"))
|
|
expected = hmac.new(
|
|
key, f"{prev}{payload}".encode(), hashlib.sha256
|
|
).hexdigest()
|
|
if sig != expected:
|
|
return False
|
|
prev = sig
|
|
return True
|
|
|
|
|
|
def test_audit_log_tamper_evident(monkeypatch, tmp_path):
|
|
monkeypatch.setattr(Path, "home", lambda: tmp_path)
|
|
key = hashlib.sha256(b"seed").digest()
|
|
logger = AuditLogger(key)
|
|
logger.log("one", {})
|
|
logger.log("two", {})
|
|
log_path = tmp_path / ".seedpass" / "audit.log"
|
|
assert _verify_chain(log_path, key)
|
|
lines = log_path.read_text().splitlines()
|
|
tampered = json.loads(lines[0])
|
|
tampered["event"] = "evil"
|
|
lines[0] = json.dumps(tampered)
|
|
log_path.write_text("\n".join(lines) + "\n")
|
|
assert not _verify_chain(log_path, key)
|