Builds both WebAuthn ceremonies on top of the library, with real cryptography
proven in tests rather than stubbed:
- PasskeyCeremonyStore: server-authoritative, single-use challenge state in the
nonceCache pool. The client's challenge copy is never trusted, and consume()
deletes before verifying so a replay cannot retry the same challenge.
- PasskeyManager: registration and login ceremonies. Library types are confined
to this class and PasskeyCeremonyFactory. Failures return null rather than
distinguishing unknown-credential from bad-signature, so the endpoint is not
an enumeration oracle.
- PasskeyTestHelper: builds genuinely valid ceremonies (real P-256 keypair,
COSE key, signed authenticatorData, CBOR attestation object).
- PasskeyRealCryptoSpikeTest: proves registration and assertion verify, that
http:// origins are refused (D4), that challenges and rpIdHash are bound, and
that a synchronised passkey with a constant zero counter can log in repeatedly.
The library default (ThrowExceptionIfInvalid) requires the reported counter to
be strictly greater than the stored one. Synchronised passkeys report a
constant 0 forever, so the default rejects a brand-new credential on its first
login — and only on real hardware, never in a unit test that increments the
counter.
The replacement still rejects a counter that moves backwards, which is the only
signal the counter can carry. Clone detection remains explicitly not a property
this feature claims; see SECURITY.md.