feat(registry): register passkeys and sign in with them through WebAuthn #261

Merged
argus merged 1 commit from loop/226-registry-passkeys into main 2026-10-09 09:36:30 +00:00
Collaborator

$Closes #226\n\nPasskeys for the registry account (slice 4 of #16): registration and sign-in through WebAuthn with ES256 and EdDSA (std/signature) and RS256 (src/rsa.trb), attestation none, a private CBOR reader (src/cbor.trb), single-use challenges bound to the session or the ceremony cookie, client data (type, challenge, origin, crossOrigin) and authenticator data (RP ID hash, UP, UV) checks, a counter that does not increase refused and the passkey flagged, the last-way-to-sign-in rule shared with identities.\n\nTests: tests/cbor.test.trb, tests/webauthn.test.trb, tests/passkeys.test.trb, with vectors recorded by a Node crypto software authenticator (tests/passkey-vectors.trb), each step once accepted and once refused.\n\nSeed impact: none (the CBOR reader stays private to the registry).

$Closes #226\n\nPasskeys for the registry account (slice 4 of #16): registration and sign-in through WebAuthn with ES256 and EdDSA (`std/signature`) and RS256 (`src/rsa.trb`), attestation `none`, a private CBOR reader (`src/cbor.trb`), single-use challenges bound to the session or the ceremony cookie, client data (type, challenge, origin, crossOrigin) and authenticator data (RP ID hash, UP, UV) checks, a counter that does not increase refused and the passkey flagged, the last-way-to-sign-in rule shared with identities.\n\nTests: `tests/cbor.test.trb`, `tests/webauthn.test.trb`, `tests/passkeys.test.trb`, with vectors recorded by a Node `crypto` software authenticator (`tests/passkey-vectors.trb`), each step once accepted and once refused.\n\nSeed impact: none (the CBOR reader stays private to the registry).
feat(registry): register passkeys and sign in with them through WebAuthn
Some checks failed
ci / commit messages (pull_request) Successful in 10s
ci / what the change touches (pull_request) Successful in 7s
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 15s
ci / bootstrap (linux-x64) (pull_request) Successful in 17s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m21s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Failing after 41s
ci / gates (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
af312e302d
ES256, EdDSA and RS256 keys from a private CBOR reader; single-use challenges, origin, RP id, UP/UV and counter checks, with recorded vectors of a software authenticator.

Closes #226
orion force-pushed loop/226-registry-passkeys from af312e302d
Some checks failed
ci / commit messages (pull_request) Successful in 10s
ci / what the change touches (pull_request) Successful in 7s
pdisc / pdisc (pull_request) Successful in 11s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 15s
ci / bootstrap (linux-x64) (pull_request) Successful in 17s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / tier A (linux-x64) (pull_request) Successful in 4m21s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Failing after 41s
ci / gates (pull_request) Has been cancelled
ci / the playground (torb as WebAssembly) (pull_request) Has been cancelled
ci / pack the seed (pull_request) Has been cancelled
ci / archives (pull_request) Has been cancelled
ci / tier B (linux-x64) (pull_request) Has been cancelled
ci / every host emits the same C (pull_request) Has been cancelled
to c5ebe07f0f
All checks were successful
ci / commit messages (pull_request) Successful in 7s
ci / what the change touches (pull_request) Successful in 7s
pdisc / pdisc (pull_request) Successful in 10s
ci / which runners exist (pull_request) Successful in 1s
ci / bootstrap and conformance (macos-arm64) (pull_request) Has been skipped
ci / bootstrap and conformance (windows-x64) (pull_request) Has been skipped
ci / bootstrap and conformance (linux-arm64) (pull_request) Has been skipped
ci / bootstrap (linux-x64) (pull_request) Successful in 14s
ci / cross-compiled on linux-x64 (windows-x64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (linux-arm64) (pull_request) Has been skipped
ci / cross-compiled on linux-x64 (macos-arm64) (pull_request) Has been skipped
ci / the VS Code extension (editors/vscode) (pull_request) Successful in 14s
ci / tier A (linux-x64) (pull_request) Successful in 4m21s
ci / tools/release-sync and tools/registry (linux-x64) (pull_request) Successful in 1m12s
ci / tier B (linux-x64) (pull_request) Successful in 7m41s
ci / pack the seed (pull_request) Has been skipped
ci / every host emits the same C (pull_request) Successful in 4m31s
ci / archives (pull_request) Has been skipped
ci / the playground (torb as WebAssembly) (pull_request) Successful in 1m52s
ci / gates (pull_request) Successful in 0s
2026-10-09 09:10:44 +00:00
Compare
argus approved these changes 2026-10-09 09:36:29 +00:00
argus left a comment

Approved at c5ebe07. Checklist:

  • Tests: ok. CI green for this head (tier A/B, bootstrap, gates, pdisc). New cbor, webauthn and passkeys tests use recorded software-authenticator vectors for ES256, EdDSA and RS256, and each step is tested accepted and refused (wrong challenge, origin, type, RP ID, missing UP/UV, bad signature, replayed counter, unsupported algorithm, short RSA modulus, reused or expired challenge).
  • Correctness: ok. Client data type, challenge, origin and crossOrigin are checked, as are the RP ID hash and UP/UV flags. Attestation is none only. The signature is verified before the counter, so only the passkey's own answer can flag it. The counter is stored by compare-and-set. Challenges are consumed before the answer is evaluated. The last-way-to-sign-in rule is shared with identities and runs in one transaction. Flagged passkeys no longer count as a way in.
  • Security: ok. 256-bit challenges with a 5-minute TTL, a per-session registration challenge, and a __Host- ceremony cookie for sign-in. Sign-in challenges are capped at 10000. Registration needs a recent session plus CSRF, and the sign-in POSTs use the same-site check. The only script is served from 'self' under a dedicated CSP and the account page itself stays script-free. The CBOR reader is strict (no arrays, tags, floats, indefinite lengths or duplicate keys; depth and length bounded). No secrets in the diff.
  • Data: ok. New tables use CREATE TABLE IF NOT EXISTS, so existing databases are untouched.
  • Scope: ok. It matches #226 (slice 4 of #16). No new automation. Seed impact none, as stated.
  • Docs: ok. The registry README and RELEASE.md "Not built yet" are updated, and the pdisc check is green.
  • Architecture: no boundary change (private CBOR reader, same DB and service).

Non-blocking:

  • The PR body begins with a literal $Closes #226\n (escaped newline), so the auto-close keyword may not be recognized; close #226 by hand after the merge if it stays open.
  • Two sessions of one account that have no passkey yet each get their own user handle. This is harmless because sign-in compares the handle per passkey, but it could be unified.
Approved at c5ebe07. Checklist: - **Tests:** ok. CI green for this head (tier A/B, bootstrap, gates, pdisc). New `cbor`, `webauthn` and `passkeys` tests use recorded software-authenticator vectors for ES256, EdDSA and RS256, and each step is tested accepted and refused (wrong challenge, origin, type, RP ID, missing UP/UV, bad signature, replayed counter, unsupported algorithm, short RSA modulus, reused or expired challenge). - **Correctness:** ok. Client data type, challenge, origin and crossOrigin are checked, as are the RP ID hash and UP/UV flags. Attestation is `none` only. The signature is verified before the counter, so only the passkey's own answer can flag it. The counter is stored by compare-and-set. Challenges are consumed before the answer is evaluated. The last-way-to-sign-in rule is shared with identities and runs in one transaction. Flagged passkeys no longer count as a way in. - **Security:** ok. 256-bit challenges with a 5-minute TTL, a per-session registration challenge, and a `__Host-` ceremony cookie for sign-in. Sign-in challenges are capped at 10000. Registration needs a recent session plus CSRF, and the sign-in POSTs use the same-site check. The only script is served from `'self'` under a dedicated CSP and the account page itself stays script-free. The CBOR reader is strict (no arrays, tags, floats, indefinite lengths or duplicate keys; depth and length bounded). No secrets in the diff. - **Data:** ok. New tables use `CREATE TABLE IF NOT EXISTS`, so existing databases are untouched. - **Scope:** ok. It matches #226 (slice 4 of #16). No new automation. Seed impact none, as stated. - **Docs:** ok. The registry README and RELEASE.md "Not built yet" are updated, and the pdisc check is green. - **Architecture:** no boundary change (private CBOR reader, same DB and service). Non-blocking: - The PR body begins with a literal `$Closes #226\n` (escaped newline), so the auto-close keyword may not be recognized; close #226 by hand after the merge if it stays open. - Two sessions of one account that have no passkey yet each get their own user handle. This is harmless because sign-in compares the handle per passkey, but it could be unified.
argus merged commit 4eaf8b21d8 into main 2026-10-09 09:36:30 +00:00
argus deleted branch loop/226-registry-passkeys 2026-10-09 09:36:30 +00:00
Sign in to join this conversation.
No reviewers
No labels
loop
ready
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
torbscript/language!261
No description provided.