"""Key management tests: generation, persistence, signing, verification.""" from __future__ import annotations from pathlib import Path from pmp.errors import PMPError from pmp.keys import KeyStore, verify_signature def _verifies(key_id: str, data: bytes, sig: bytes) -> bool: """Verification helper tolerant of raise-vs-return failure signalling.""" try: return bool(verify_signature(key_id, data, sig)) except PMPError: return False def test_create_key_has_ed25519_key_id(tmp_path: Path): ks = KeyStore(tmp_path / "keys") key = ks.create("device") assert key.key_id assert "ed25519" in key.key_id.lower() def test_sign_and_verify_roundtrip(tmp_path: Path): ks = KeyStore(tmp_path / "keys") key = ks.create("device") message = b"what do you know about me and why?" sig = key.sign(message) assert sig and isinstance(sig, (bytes, bytearray)) assert _verifies(key.key_id, message, bytes(sig)) def test_verification_fails_on_modified_message(tmp_path: Path): ks = KeyStore(tmp_path / "keys") key = ks.create("device") sig = key.sign(b"original message") assert not _verifies(key.key_id, b"modified message", bytes(sig)) def test_verification_fails_on_modified_signature(tmp_path: Path): ks = KeyStore(tmp_path / "keys") key = ks.create("device") message = b"original message" sig = bytearray(key.sign(message)) sig[0] ^= 0xFF assert not _verifies(key.key_id, message, bytes(sig)) def test_verification_fails_under_wrong_key(tmp_path: Path): ks = KeyStore(tmp_path / "keys") key_a = ks.create("device-a") key_b = ks.create("device-b") message = b"hello" sig = key_a.sign(message) assert not _verifies(key_b.key_id, message, bytes(sig)) def test_two_generated_keys_are_distinct(tmp_path: Path): ks = KeyStore(tmp_path / "keys") a = ks.create("phone") b = ks.create("laptop") assert a.key_id != b.key_id def test_keys_persist_across_keystore_reopen(tmp_path: Path): keys_dir = tmp_path / "keys" ks1 = KeyStore(keys_dir) created = ks1.create("device") message = b"persistence check" sig_before = created.sign(message) ks2 = KeyStore(keys_dir) loaded = ks2.load("device") assert loaded.key_id == created.key_id sig_after = loaded.sign(message) assert _verifies(created.key_id, message, bytes(sig_before)) assert _verifies(created.key_id, message, bytes(sig_after))