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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// Copyright 2026 Grzegorz Blach
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Passki - A WebAuthn/Passkey implementation for Rust
//!
//! Passki provides a simple and secure way to implement passkey-based authentication
//! in your Rust applications. It handles the WebAuthn protocol for both registration
//! and authentication ceremonies.
//!
//! # Features
//!
//! - Support for multiple cryptographic algorithms (EdDSA/Ed25519, ES256/P-256, RS256/RSA)
//! - Full WebAuthn Level 2 compliance
//! - Replay attack protection via signature counters
//! - Flexible authenticator selection and user verification options
//! - Credential exclusion to prevent duplicate registrations
//! - Type-safe API with comprehensive error handling
//!
//! # Example
//!
//! ```rust
//! use passki::{
//! Passki, AttestationConveyancePreference, ResidentKeyRequirement,
//! UserVerificationRequirement, StoredPasskey,
//! };
//!
//! // Initialize Passki with your relying party information
//! let passki = Passki::new(
//! "example.com", // Relying Party ID (domain)
//! "https://example.com", // Relying Party Origin
//! "Example Corp" // Relying Party Name
//! );
//!
//! // Registration flow
//! // Step 1: Start registration and send challenge to client
//! # let user_existing_passkeys: Vec<StoredPasskey> = vec![];
//! let user_id = b"unique_user_identifier_12345"; // At least 16 bytes
//! let (registration_challenge, registration_state) = passki.start_passkey_registration(
//! user_id, // User ID (bytes)
//! "alice@example.com", // Username
//! "Alice Smith", // Display name
//! 60000, // Timeout (ms)
//! AttestationConveyancePreference::None, // Attestation
//! ResidentKeyRequirement::Preferred, // Resident key
//! UserVerificationRequirement::Preferred, // User verification
//! None, // Exclude existing credentials
//! ).expect("user_id must be at least 16 bytes");
//!
//! // Send registration_challenge to client (as JSON)
//! // Client uses WebAuthn API to create credential
//!
//! // Step 2: Receive credential from client and complete registration
//! # /*
//! let stored_passkey = passki.finish_passkey_registration(
//! ®istration_credential, // Credential from client
//! ®istration_state, // State from step 1
//! )?;
//! # */
//!
//! // Save stored_passkey to your database associated with the user
//!
//! // Authentication flow
//! // Step 1: Start authentication and send challenge to client
//! # let user_passkeys: Vec<StoredPasskey> = vec![];
//! let (authentication_challenge, authentication_state) = passki.start_passkey_authentication(
//! &user_passkeys, // User's stored passkeys
//! 60000, // Timeout (ms)
//! UserVerificationRequirement::Preferred, // User verification
//! );
//!
//! // Send authentication_challenge to client (as JSON)
//! // Client uses WebAuthn API to sign the challenge
//!
//! // Step 2: Receive credential from client and verify authentication
//! # /*
//! let result = passki.finish_passkey_authentication(
//! &authentication_credential, // Credential from client
//! &authentication_state, // State from step 1
//! &stored_passkey, // User's passkey from database
//! )?;
//!
//! // Update the counter in your database to prevent replay attacks
//! stored_passkey.counter = result.counter;
//! # */
//! ```
//!
//! # Security Considerations
//!
//! - Always verify that the origin matches your expected domain
//! - Store and check signature counters to detect cloned authenticators
//! - Use HTTPS in production to prevent man-in-the-middle attacks
//! - Store passkeys securely in your database (the public keys are not secret,
//! but credential IDs should be treated as sensitive)
//! - Use credential exclusion during registration to prevent duplicate credentials
//! - User IDs must be at least 16 bytes for security (recommended: use UUIDs or random bytes)
use ;
use Error as StdError;
// Re-export public types
pub use ;
pub use ;
pub use ;
pub use *;
/// Main Passki struct for managing passkey registration and authentication.
///
/// This struct holds the relying party configuration and provides methods
/// to start and finish passkey operations.