ant_quic/relay/
authenticator.rs1use crate::relay::{RelayError, RelayResult};
4use ed25519_dalek::{Signature, Signer, SigningKey, Verifier, VerifyingKey};
5use rand::rngs::OsRng;
6use std::collections::HashSet;
7use std::sync::{Arc, Mutex};
8use std::time::{SystemTime, UNIX_EPOCH};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12pub struct AuthToken {
13 pub nonce: u64,
15 pub timestamp: u64,
17 pub bandwidth_limit: u32,
19 pub timeout_seconds: u32,
21 pub signature: [u8; 64],
23}
24
25#[derive(Debug)]
27pub struct RelayAuthenticator {
28 signing_key: SigningKey,
30 verifying_key: VerifyingKey,
32 used_nonces: Arc<Mutex<HashSet<u64>>>,
34 max_token_age: u64,
36 replay_window_size: u64,
38}
39
40impl AuthToken {
41 pub fn new(
43 bandwidth_limit: u32,
44 timeout_seconds: u32,
45 signing_key: &SigningKey,
46 ) -> RelayResult<Self> {
47 let nonce = Self::generate_nonce();
48 let timestamp = Self::current_timestamp()?;
49
50 let mut token = Self {
51 nonce,
52 timestamp,
53 bandwidth_limit,
54 timeout_seconds,
55 signature: [0; 64],
56 };
57
58 let signature_bytes = signing_key.sign(&token.signable_data()).to_bytes();
60 token.signature = signature_bytes;
61
62 Ok(token)
63 }
64
65 fn generate_nonce() -> u64 {
67 use rand::Rng;
68 OsRng.r#gen()
69 }
70
71 fn current_timestamp() -> RelayResult<u64> {
73 SystemTime::now()
74 .duration_since(UNIX_EPOCH)
75 .map(|d| d.as_secs())
76 .map_err(|_| RelayError::AuthenticationFailed {
77 reason: "System time before Unix epoch".to_string(),
78 })
79 }
80
81 fn signable_data(&self) -> Vec<u8> {
83 let mut data = Vec::new();
84 data.extend_from_slice(&self.nonce.to_le_bytes());
85 data.extend_from_slice(&self.timestamp.to_le_bytes());
86 data.extend_from_slice(&self.bandwidth_limit.to_le_bytes());
87 data.extend_from_slice(&self.timeout_seconds.to_le_bytes());
88 data
89 }
90
91 pub fn verify(&self, verifying_key: &VerifyingKey) -> RelayResult<()> {
93 let signature = Signature::from_bytes(&self.signature);
94
95 verifying_key
96 .verify(&self.signable_data(), &signature)
97 .map_err(|_| RelayError::AuthenticationFailed {
98 reason: "Signature verification failed".to_string(),
99 })
100 }
101
102 pub fn is_expired(&self, max_age_seconds: u64) -> RelayResult<bool> {
104 let current_time = Self::current_timestamp()?;
105 Ok(current_time > self.timestamp + max_age_seconds)
106 }
107}
108
109impl RelayAuthenticator {
110 pub fn new() -> Self {
112 let signing_key = SigningKey::generate(&mut OsRng);
113 let verifying_key = signing_key.verifying_key();
114
115 Self {
116 signing_key,
117 verifying_key,
118 used_nonces: Arc::new(Mutex::new(HashSet::new())),
119 max_token_age: 300, replay_window_size: 1000,
121 }
122 }
123
124 pub fn with_key(signing_key: SigningKey) -> Self {
126 let verifying_key = signing_key.verifying_key();
127
128 Self {
129 signing_key,
130 verifying_key,
131 used_nonces: Arc::new(Mutex::new(HashSet::new())),
132 max_token_age: 300,
133 replay_window_size: 1000,
134 }
135 }
136
137 pub fn verifying_key(&self) -> &VerifyingKey {
139 &self.verifying_key
140 }
141
142 pub fn create_token(
144 &self,
145 bandwidth_limit: u32,
146 timeout_seconds: u32,
147 ) -> RelayResult<AuthToken> {
148 AuthToken::new(bandwidth_limit, timeout_seconds, &self.signing_key)
149 }
150
151 pub fn verify_token(
153 &self,
154 token: &AuthToken,
155 peer_verifying_key: &VerifyingKey,
156 ) -> RelayResult<()> {
157 token.verify(peer_verifying_key)?;
159
160 if token.is_expired(self.max_token_age)? {
162 return Err(RelayError::AuthenticationFailed {
163 reason: "Token expired".to_string(),
164 });
165 }
166
167 let mut used_nonces = self.used_nonces.lock().unwrap();
169
170 if used_nonces.contains(&token.nonce) {
171 return Err(RelayError::AuthenticationFailed {
172 reason: "Token replay detected".to_string(),
173 });
174 }
175
176 if used_nonces.len() >= self.replay_window_size as usize {
178 let to_remove: Vec<_> = used_nonces.iter().take(100).cloned().collect();
180 for nonce in to_remove {
181 used_nonces.remove(&nonce);
182 }
183 }
184
185 used_nonces.insert(token.nonce);
186
187 Ok(())
188 }
189
190 pub fn set_max_token_age(&mut self, max_age_seconds: u64) {
192 self.max_token_age = max_age_seconds;
193 }
194
195 pub fn clear_nonces(&self) {
197 let mut used_nonces = self.used_nonces.lock().unwrap();
198 used_nonces.clear();
199 }
200
201 pub fn nonce_count(&self) -> usize {
203 let used_nonces = self.used_nonces.lock().unwrap();
204 used_nonces.len()
205 }
206}
207
208impl Default for RelayAuthenticator {
209 fn default() -> Self {
210 Self::new()
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217 use std::thread;
218 use std::time::Duration;
219
220 #[test]
221 fn test_auth_token_creation_and_verification() {
222 let authenticator = RelayAuthenticator::new();
223 let token = authenticator.create_token(1024, 300).unwrap();
224
225 assert!(token.bandwidth_limit == 1024);
226 assert!(token.timeout_seconds == 300);
227 assert!(token.nonce != 0);
228 assert!(token.timestamp > 0);
229
230 assert!(token.verify(authenticator.verifying_key()).is_ok());
232 }
233
234 #[test]
235 fn test_token_verification_with_wrong_key() {
236 let authenticator1 = RelayAuthenticator::new();
237 let authenticator2 = RelayAuthenticator::new();
238
239 let token = authenticator1.create_token(1024, 300).unwrap();
240
241 assert!(token.verify(authenticator2.verifying_key()).is_err());
243 }
244
245 #[test]
246 fn test_token_expiration() {
247 let mut authenticator = RelayAuthenticator::new();
248 authenticator.set_max_token_age(1); let token = authenticator.create_token(1024, 300).unwrap();
251
252 assert!(!token.is_expired(1).unwrap());
254
255 thread::sleep(Duration::from_millis(1100));
257
258 assert!(token.is_expired(1).unwrap());
260 }
261
262 #[test]
263 fn test_anti_replay_protection() {
264 let authenticator = RelayAuthenticator::new();
265 let token = authenticator.create_token(1024, 300).unwrap();
266
267 assert!(authenticator.verify_token(&token, authenticator.verifying_key()).is_ok());
269
270 assert!(authenticator.verify_token(&token, authenticator.verifying_key()).is_err());
272 }
273
274 #[test]
275 fn test_nonce_uniqueness() {
276 let authenticator = RelayAuthenticator::new();
277 let mut nonces = HashSet::new();
278
279 for _ in 0..1000 {
281 let token = authenticator.create_token(1024, 300).unwrap();
282 assert!(!nonces.contains(&token.nonce), "Duplicate nonce detected");
283 nonces.insert(token.nonce);
284 }
285 }
286
287 #[test]
288 fn test_token_signable_data() {
289 let authenticator = RelayAuthenticator::new();
290 let token1 = authenticator.create_token(1024, 300).unwrap();
291 let token2 = authenticator.create_token(1024, 300).unwrap();
292
293 assert_ne!(token1.signable_data(), token2.signable_data());
295 }
296
297 #[test]
298 fn test_nonce_window_management() {
299 let authenticator = RelayAuthenticator::new();
300
301 for _ in 0..1000 {
303 let token = authenticator.create_token(1024, 300).unwrap();
304 let _ = authenticator.verify_token(&token, authenticator.verifying_key());
305 }
306
307 assert_eq!(authenticator.nonce_count(), 1000);
308
309 let token = authenticator.create_token(1024, 300).unwrap();
311 let _ = authenticator.verify_token(&token, authenticator.verifying_key());
312
313 assert!(authenticator.nonce_count() <= 1000);
315 }
316
317 #[test]
318 fn test_clear_nonces() {
319 let authenticator = RelayAuthenticator::new();
320 let token = authenticator.create_token(1024, 300).unwrap();
321
322 let _ = authenticator.verify_token(&token, authenticator.verifying_key());
324 assert!(authenticator.nonce_count() > 0);
325
326 authenticator.clear_nonces();
328 assert_eq!(authenticator.nonce_count(), 0);
329
330 assert!(authenticator.verify_token(&token, authenticator.verifying_key()).is_ok());
332 }
333
334 #[test]
335 fn test_with_specific_key() {
336 let signing_key = SigningKey::generate(&mut OsRng);
337 let authenticator = RelayAuthenticator::with_key(signing_key);
338
339 let token = authenticator.create_token(1024, 300).unwrap();
340 assert!(token.verify(authenticator.verifying_key()).is_ok());
341 }
342}