""" Trusted-signer key registry for path-proof receipts. Dependency-free. Keys are Ed25519 public keys (raw 32-byte bytes) or their hex encoding. Verification here is a *simulated* cryptographic check: the signature must equal the canonical commitment bound to the key id. In a production recorder the signature would be a real Ed25519 signature and the key a verified public key from a hardware/service-isolated key store; the shape and the trust decision (known vs unknown vs revoked) are identical. The trust decision is what the gate enforces: - ``known``: (issuer, key_id) is present and not revoked - ``unknown``: not present - ``revoked``: present but revoked Everything is deterministic and in-memory so tests are reproducible from a clean checkout with no generated artifacts. """ from __future__ import annotations from dataclasses import dataclass, field from typing import Dict, Optional, Tuple @dataclass(frozen=True) class SignerKey: """A trusted runtime-recorder signing identity. ``public_key`` is the raw Ed25519 public key bytes (32 bytes) or hex text. ``valid_until`` is an explicit epoch-seconds bound (``None`` = no bound). """ issuer: str key_id: str public_key: str valid_until: Optional[int] = None revoked: bool = False def is_trusted(self, now: int) -> bool: if self.revoked: return False if self.valid_until is not None and now > self.valid_until: return False return True class KeyRegistry: """In-memory registry of trusted signer keys, keyed by (issuer, key_id).""" def __init__(self) -> None: self._keys: Dict[Tuple[str, str], SignerKey] = {} def add(self, key: SignerKey) -> None: self._keys[(key.issuer, key.key_id)] = key def add_hex(self, issuer: str, key_id: str, public_key_hex: str, valid_until: Optional[int] = None, revoked: bool = False) -> SignerKey: key = SignerKey(issuer=issuer, key_id=key_id, public_key=public_key_hex, valid_until=valid_until, revoked=revoked) self.add(key) return key def resolve(self, issuer: str, key_id: str) -> Optional[SignerKey]: return self._keys.get((issuer, key_id)) def __len__(self) -> int: return len(self._keys) def __contains__(self, item: Tuple[str, str]) -> bool: return item in self._keys def make_demo_registry() -> KeyRegistry: """A deterministic demo registry: two trusted recorders, one revoked.""" reg = KeyRegistry() reg.add_hex("recorder:forge", "recorder:forge/key-1", "aa" * 32) reg.add_hex("recorder:gateway", "recorder:gateway/key-1", "bb" * 32) reg.add_hex("recorder:old", "recorder:old/key-1", "cc" * 32, revoked=True) return reg # Backwards-compatible alias used by the public package surface. keys = make_demo_registry()