1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//! # webauthn-kit
//!
//! Standalone `WebAuthn` / FIDO2 passkey verification kit: real CTAP2/COSE
//! cryptographic verification with zero framework coupling. This is not a
//! wrapper around `navigator.credentials` server emulation — it implements
//! the server side of the protocol directly on `ring`.
//!
//! ## What it does
//!
//! - Full CTAP2 authenticator data parsing (rpIdHash, flags, signCount,
//! attested credential data incl. AAGUID) — [`protocol`]
//! - `verify_registration` / `verify_authentication` ceremonies — [`protocol`]
//! - Attestation statement verification for the `none`, `packed` (self- and
//! x5c-based basic/AttCA), and `fido-u2f` formats, with X.509 chain
//! verification against caller-configured trust anchors — [`attestation`]
//! - COSE public key parsing and signature verification for **ES256**
//! (ECDSA P-256 + SHA-256), **ES384** (ECDSA P-384 + SHA-384), **EdDSA**
//! (Ed25519), and **RS256** (RSA PKCS#1 v1.5 + SHA-256) via `ring` —
//! [`crypto`]
//! - Enforceable credential policies — user verification (UV), multi-device
//! / backup eligibility (BE/BS), and registration algorithm allowlists —
//! [`policy`]
//! - Challenge generation from the OS CSPRNG, single-use consumption
//! (replay protection), freshness/expiry enforcement, and the sign-count
//! clone-detection state machine — [`challenge`]
//! - Storage-free credential record + browser wire DTOs — [`credential`]
//!
//! ## Quick start
//!
//! ```
//! use webauthn_kit::{
//! check_sign_count, verify_authentication, verify_registration, AttestationPolicy,
//! AuthenticationParams, ChallengeStore, CredentialPolicy, UserVerificationPolicy,
//! WebauthnConfig,
//! };
//!
//! let config = WebauthnConfig {
//! rp_id: "example.com".into(),
//! rp_name: "Example".into(),
//! rp_origins: vec!["https://example.com".into()],
//! allowed_algorithms: vec![-7, -35, -257], // ES256, ES384, RS256
//! challenge_timeout_secs: 300,
//! attestation: AttestationPolicy::default(),
//! // Server-side enforcement: UV required, synced passkeys rejected.
//! credential_policy: CredentialPolicy {
//! user_verification: UserVerificationPolicy::Required,
//! ..CredentialPolicy::default()
//! },
//! resident_key: Default::default(),
//! attestation_conveyance: Default::default(),
//! };
//!
//! // 1. Issue a challenge (single-use; store the (id, bytes) pair).
//! let store = ChallengeStore::new();
//! let (challenge_b64, create_options) =
//! store.generate_registration_challenge(&config, "alice", "Alice", &[]);
//! // ... send `create_options` to the browser, receive RegistrationResponse ...
//!
//! // 2. Verify a registration response (see tests/vectors.rs for a full
//! // roundtrip with a synthetic keypair).
//! // let result = verify_registration(&challenge, &client_data_json_b64,
//! // &attestation_object_b64, "", &config.rp_id, &config.rp_origins,
//! // &config.attestation)?;
//!
//! // 3. Verify an assertion; persist result.new_sign_count afterwards.
//! // let result = verify_authentication(&AuthenticationParams { ... })?;
//! ```
//!
//! ## Storage contract (what this crate does NOT do)
//!
//! This crate is deliberately storage-free. The integrator owns:
//!
//! - **Credential persistence**: after [`verify_registration`] succeeds,
//! store a [`credential::WebauthnCredential`] (credential ID, COSE public
//! key, sign count, timestamps). After each successful
//! [`verify_authentication`], atomically persist
//! [`credential::AuthenticationResult::new_sign_count`].
//! - **Challenge durability**: [`ChallengeStore`] holds pending challenges
//! in memory; they are lost on restart (users simply retry). Keep the
//! consume-then-verify ordering so restarts can never enable replays.
//! - **User mapping and session issuance** (cookies, JWTs, ...).
//! - **UI / HTTP layer**: the `credential` DTOs serialize with the `serde`
//! feature but no HTTP types are included.
//!
//! ## Security notes
//!
//! - `#![forbid(unsafe_code)]`; all cryptography via `ring`.
//! - Every parser accepts hostile input and returns `Err` instead of
//! panicking (property/fuzz-tested in `tests/fuzz.rs`).
//! - Challenge bytes are 32 bytes from the OS CSPRNG; consumption is
//! single-use and freshness-bounded.
//! - **Attestation is verified for `none`, `packed`, and `fido-u2f`**;
//! unknown formats are rejected unless the
//! `AttestationPolicy::allow_unknown_formats` escape hatch is set
//! (trust-weakening). Provenance claims are bounded by the configured
//! trust anchors: with none configured, unanchored certificate chains are
//! accepted but flagged (`TrustLevel::BasicAtt` + warning) and must be
//! treated as self-attested. Only `TrustLevel::AttCa` attests device
//! provenance. Other formats (`android-key`, `tpm`, ...) are tranche-2
//! work — see [`attestation`].
//! - Supported algorithms: ES256 (COSE −7), ES384 (COSE −35), EdDSA
//! (Ed25519, COSE −8), and RS256 (COSE −257). Curve/algorithm bindings are
//! enforced at parse time (a P-256 key claiming ES384 is rejected); other
//! algorithms are rejected with [`WebauthnError::UnsupportedAlgorithm`].
//! - Sign-count policy: a stored counter of 0 disables the check
//! (authenticators without counters); otherwise a strictly decreasing
//! counter is rejected. Equal counters are allowed by design.
//! - **User verification** ([`policy::UserVerificationPolicy`]): `Required`
//! is enforced server-side — ceremonies whose authenticator UV flag is
//! clear fail with [`WebauthnError::UserVerificationRequired`]. The
//! default (`Preferred`) reports the flag without rejecting, preserving
//! per-caller policy decisions.
//! - **Multi-device credentials** ([`policy::BackupPolicy`]): the BE/BS
//! flags are parsed from signed authenticator data and reported on both
//! ceremony results; `BackupPolicy::RequireDeviceBound` rejects syncable
//! (BE=1) credentials. See the policy module docs for account-recovery
//! implications before allowing synced passkeys on sensitive flows.
pub use known_aaguid;
pub use ;
pub use ;
pub use WebauthnConfig;
pub use ;
pub use ;
pub use WebauthnError;
pub use ;
pub use ;