"""End-to-end simulation of the passkey -> Nostr key derivation flow. Without a real WebAuthn authenticator and browser handy, this script stubs the 32-byte PRF output with a deterministic hash so you can watch the rest of the pipeline work: HKDF stretches the entropy, the result becomes a Nostr private key, and nsec/npub fall out the other side. Run it with: python -m scripts.demo """ from __future__ import annotations import hashlib from nostr_passkey.derivation import derive_nostr_key def fake_prf_output(seed: str) -> bytes: """Stand-in for ``clientExtensionResults.prf.results.first``.""" return hashlib.sha256(seed.encode("utf-8")).digest() def main() -> None: prf = fake_prf_output("pretend-passkey-credential") print(f"Simulated PRF output (hex): {prf.hex()}") ident_none = derive_nostr_key(prf) print("\n-- No salt --") print(f" privkey_hex: {ident_none.privkey_hex}") print(f" nsec: {ident_none.nsec}") print(f" npub: {ident_none.npub}") ident_work = derive_nostr_key(prf, salt="work") print("\n-- salt='work' --") print(f" nsec: {ident_work.nsec}") print(f" npub: {ident_work.npub}") ident_personal = derive_nostr_key(prf, salt="personal") print("\n-- salt='personal' --") print(f" nsec: {ident_personal.nsec}") print(f" npub: {ident_personal.npub}") # Invariants the whole design rests on: ident_work_again = derive_nostr_key(prf, salt="work") assert ident_work.nsec == ident_work_again.nsec, "derivation must be deterministic" assert ident_work.nsec != ident_none.nsec, "salt must change the output" assert ident_work.nsec != ident_personal.nsec, "different salts must diverge" print("\nDeterminism and salt separation verified.") if __name__ == "__main__": main()