1pub mod key_management;
13
14use std::collections::HashMap;
15
16use aes_gcm::aead::{Aead, KeyInit};
17use aes_gcm::{Aes256Gcm, Key, Nonce};
18use hmac::{Hmac, Mac};
19use pbkdf2::pbkdf2_hmac;
20use rand::rngs::OsRng;
21use rand::RngCore;
22use sha2::{Digest, Sha256};
23use subtle::ConstantTimeEq;
24
25type HmacSha256 = Hmac<Sha256>;
26
27pub fn sha256(data: &[u8]) -> [u8; 32] {
33 let mut hasher = Sha256::new();
34 hasher.update(data);
35 let result = hasher.finalize();
36 let mut out = [0u8; 32];
37 out.copy_from_slice(&result);
38 out
39}
40
41pub fn sha256_hex(data: &[u8]) -> String {
43 sha256(data).iter().map(|b| format!("{:02x}", b)).collect()
44}
45
46pub fn hmac_sha256(key: &[u8], message: &[u8]) -> [u8; 32] {
48 let mut mac = match <HmacSha256 as Mac>::new_from_slice(key) {
51 Ok(m) => m,
52 Err(_) => {
53 return [0u8; 32];
56 }
57 };
58 mac.update(message);
59 let result = mac.finalize().into_bytes();
60 let mut out = [0u8; 32];
61 out.copy_from_slice(&result);
62 out
63}
64
65pub fn hmac_sha256_hex(key: &[u8], message: &[u8]) -> String {
67 hmac_sha256(key, message)
68 .iter()
69 .map(|b| format!("{:02x}", b))
70 .collect()
71}
72
73fn constant_time_eq(a: &[u8], b: &[u8]) -> bool {
75 a.ct_eq(b).into()
76}
77
78pub trait Crypter: Send + Sync {
83 fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, CryptoError>;
84 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError>;
85}
86
87pub struct AesGcmCrypter {
92 cipher: Aes256Gcm,
93}
94
95impl AesGcmCrypter {
96 pub fn new(key: &[u8; 32]) -> Self {
98 let key = Key::<Aes256Gcm>::from_slice(key);
99 Self {
100 cipher: Aes256Gcm::new(key),
101 }
102 }
103
104 pub fn from_key_str(key: &str) -> Self {
106 let hash = sha256(key.as_bytes());
107 Self::new(&hash)
108 }
109
110 fn random_nonce() -> [u8; 12] {
111 let mut nonce = [0u8; 12];
112 OsRng.fill_bytes(&mut nonce);
113 nonce
114 }
115}
116
117impl Crypter for AesGcmCrypter {
118 fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, CryptoError> {
119 self.encrypt_with_aad(plaintext, &[])
120 }
121
122 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> {
123 self.decrypt_with_aad(ciphertext, &[])
124 }
125}
126
127impl AesGcmCrypter {
128 pub fn encrypt_with_aad(&self, plaintext: &[u8], aad: &[u8]) -> Result<Vec<u8>, CryptoError> {
134 let nonce_bytes = Self::random_nonce();
135 let nonce = Nonce::from_slice(&nonce_bytes);
136 let payload = aes_gcm::aead::Payload {
137 msg: plaintext,
138 aad,
139 };
140 let ciphertext = self
141 .cipher
142 .encrypt(nonce, payload)
143 .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))?;
144 let mut result = Vec::with_capacity(12 + ciphertext.len());
145 result.extend_from_slice(&nonce_bytes);
146 result.extend_from_slice(&ciphertext);
147 Ok(result)
148 }
149
150 pub fn decrypt_with_aad(&self, ciphertext: &[u8], aad: &[u8]) -> Result<Vec<u8>, CryptoError> {
154 if ciphertext.len() < 12 {
155 return Err(CryptoError::DecryptionFailed(
156 "Ciphertext too short".to_string(),
157 ));
158 }
159 let nonce = Nonce::from_slice(&ciphertext[..12]);
160 let encrypted = &ciphertext[12..];
161 let payload = aes_gcm::aead::Payload {
162 msg: encrypted,
163 aad,
164 };
165 self.cipher
166 .decrypt(nonce, payload)
167 .map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
168 }
169}
170
171pub trait PasswordHasher: Send + Sync {
176 fn hash(&self, password: &str) -> Result<String, CryptoError>;
177 fn verify(&self, password: &str, hash: &str) -> Result<bool, CryptoError>;
178}
179
180pub struct Pbkdf2Hasher {
185 iterations: u32,
186}
187
188impl Pbkdf2Hasher {
189 const DEFAULT_ITERATIONS: u32 = 100_000;
190 const SALT_LEN: usize = 16;
191 const HASH_LEN: usize = 32;
192
193 pub fn new() -> Self {
194 Self {
195 iterations: Self::DEFAULT_ITERATIONS,
196 }
197 }
198
199 pub fn with_iterations(iterations: u32) -> Self {
200 Self {
201 iterations: iterations.max(1),
202 }
203 }
204
205 pub const MIN_ITERATIONS: u32 = 100_000;
209 pub const MAX_ITERATIONS: u32 = 10_000_000;
210
211 fn compute_hash(password: &str, salt: &[u8], iterations: u32) -> [u8; Self::HASH_LEN] {
212 let mut out = [0u8; Self::HASH_LEN];
213 pbkdf2_hmac::<Sha256>(password.as_bytes(), salt, iterations, &mut out);
214 out
215 }
216}
217
218impl Default for Pbkdf2Hasher {
219 fn default() -> Self {
220 Self::new()
221 }
222}
223
224impl PasswordHasher for Pbkdf2Hasher {
225 fn hash(&self, password: &str) -> Result<String, CryptoError> {
226 if password.is_empty() {
227 return Err(CryptoError::InvalidHash(
228 "Password cannot be empty".to_string(),
229 ));
230 }
231 if self.iterations < Self::MIN_ITERATIONS {
234 return Err(CryptoError::InvalidHash(format!(
235 "Iterations below minimum ({} < {})",
236 self.iterations,
237 Self::MIN_ITERATIONS
238 )));
239 }
240 let salt = random_bytes(Self::SALT_LEN);
241 let hash = Self::compute_hash(password, &salt, self.iterations);
242 Ok(format!(
243 "${}${}${}",
244 self.iterations,
245 hex_encode(&salt),
246 hex_encode(&hash)
247 ))
248 }
249
250 fn verify(&self, password: &str, hash: &str) -> Result<bool, CryptoError> {
251 if !hash.starts_with('$') {
252 return Err(CryptoError::InvalidHash("Invalid hash format".to_string()));
253 }
254 let parts: Vec<&str> = hash[1..].splitn(3, '$').collect();
255 if parts.len() != 3 {
256 return Err(CryptoError::InvalidHash("Invalid hash format".to_string()));
257 }
258 let iterations: u32 = parts[0]
259 .parse()
260 .map_err(|_| CryptoError::InvalidHash("Invalid iterations".to_string()))?;
261
262 if iterations < Self::MIN_ITERATIONS {
265 return Err(CryptoError::InvalidHash(format!(
266 "Iterations below minimum ({iterations} < {})",
267 Self::MIN_ITERATIONS
268 )));
269 }
270 if iterations > Self::MAX_ITERATIONS {
271 return Err(CryptoError::InvalidHash(format!(
272 "Iterations above maximum ({iterations} > {})",
273 Self::MAX_ITERATIONS
274 )));
275 }
276
277 let salt = hex_decode(parts[1])
278 .map_err(|_| CryptoError::InvalidHash("Invalid salt hex".to_string()))?;
279 let expected_hash = hex_decode(parts[2])
280 .map_err(|_| CryptoError::InvalidHash("Invalid hash hex".to_string()))?;
281 let computed = Self::compute_hash(password, &salt, iterations);
282 Ok(constant_time_eq(&computed, &expected_hash))
283 }
284}
285
286pub trait ApiSigner: Send + Sync {
291 fn sign(&self, params: &HashMap<String, String>, secret: &str) -> String;
292 fn verify(&self, params: &HashMap<String, String>, secret: &str, signature: &str) -> bool;
293}
294
295pub struct HmacSigner;
306
307impl HmacSigner {
308 pub fn new() -> Self {
309 Self
310 }
311
312 fn percent_encode(s: &str) -> String {
315 let mut out = String::with_capacity(s.len());
316 for b in s.bytes() {
317 match b {
318 b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' | b'-' | b'.' | b'_' | b'~' => {
319 out.push(b as char)
320 }
321 _ => {
322 out.push('%');
323 out.push(
324 char::from_digit((b >> 4) as u32, 16)
325 .unwrap_or('0')
326 .to_ascii_uppercase(),
327 );
328 out.push(
329 char::from_digit((b & 0x0f) as u32, 16)
330 .unwrap_or('0')
331 .to_ascii_uppercase(),
332 );
333 }
334 }
335 }
336 out
337 }
338
339 fn compute_signature(params: &HashMap<String, String>, secret: &str) -> String {
340 let mut sorted: Vec<_> = params.iter().collect();
341 sorted.sort_by(|a, b| a.0.cmp(b.0));
342
343 let query_string: String = sorted
344 .iter()
345 .map(|(k, v)| format!("{}={}", Self::percent_encode(k), Self::percent_encode(v)))
346 .collect::<Vec<_>>()
347 .join("&");
348
349 hmac_sha256_hex(secret.as_bytes(), query_string.as_bytes())
350 }
351}
352
353impl Default for HmacSigner {
354 fn default() -> Self {
355 Self::new()
356 }
357}
358
359impl ApiSigner for HmacSigner {
360 fn sign(&self, params: &HashMap<String, String>, secret: &str) -> String {
361 Self::compute_signature(params, secret)
362 }
363
364 fn verify(&self, params: &HashMap<String, String>, secret: &str, signature: &str) -> bool {
365 let computed = Self::compute_signature(params, secret);
366 constant_time_eq(computed.as_bytes(), signature.as_bytes())
367 }
368}
369
370use rsa::oaep::Oaep;
375use rsa::{RsaPrivateKey, RsaPublicKey};
376use sha2::Sha256 as RsaSha256;
377
378pub struct RsaOaepCrypter {
383 public_key: RsaPublicKey,
384 private_key: RsaPrivateKey,
385}
386
387impl RsaOaepCrypter {
388 pub fn generate(key_bits: usize) -> Result<Self, CryptoError> {
390 let mut rng = OsRng;
391 let private_key = RsaPrivateKey::new(&mut rng, key_bits)
392 .map_err(|e| CryptoError::InvalidKey(e.to_string()))?;
393 let public_key = RsaPublicKey::from(&private_key);
394 Ok(Self {
395 public_key,
396 private_key,
397 })
398 }
399
400 pub fn from_keys(public_key: RsaPublicKey, private_key: RsaPrivateKey) -> Self {
402 Self {
403 public_key,
404 private_key,
405 }
406 }
407
408 pub fn public_key(&self) -> &RsaPublicKey {
410 &self.public_key
411 }
412
413 pub fn private_key(&self) -> &RsaPrivateKey {
415 &self.private_key
416 }
417
418 pub fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, CryptoError> {
420 let mut rng = OsRng;
421 let padding = Oaep::new::<RsaSha256>();
422 self.public_key
423 .encrypt(&mut rng, padding, plaintext)
424 .map_err(|e| CryptoError::EncryptionFailed(e.to_string()))
425 }
426
427 pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> {
429 let padding = Oaep::new::<RsaSha256>();
430 self.private_key
431 .decrypt(padding, ciphertext)
432 .map_err(|e| CryptoError::DecryptionFailed(e.to_string()))
433 }
434}
435
436impl Crypter for RsaOaepCrypter {
437 fn encrypt(&self, plaintext: &[u8]) -> Result<Vec<u8>, CryptoError> {
438 self.encrypt(plaintext)
439 }
440
441 fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, CryptoError> {
442 self.decrypt(ciphertext)
443 }
444}
445
446pub trait SignatureVerifier: Send + Sync {
452 fn sign(&self, message: &[u8]) -> Vec<u8>;
454 fn verify(&self, message: &[u8], signature: &[u8]) -> bool;
456}
457
458pub struct HmacSignatureVerifier {
462 key: Vec<u8>,
463}
464
465impl HmacSignatureVerifier {
466 pub fn new(key: &[u8]) -> Self {
468 Self { key: key.to_vec() }
469 }
470
471 pub fn from_key_str(key: &str) -> Self {
473 Self::new(key.as_bytes())
474 }
475}
476
477impl SignatureVerifier for HmacSignatureVerifier {
478 fn sign(&self, message: &[u8]) -> Vec<u8> {
479 hmac_sha256(&self.key, message).to_vec()
480 }
481
482 fn verify(&self, message: &[u8], signature: &[u8]) -> bool {
483 let expected = self.sign(message);
484 constant_time_eq(&expected, signature)
485 }
486}
487
488#[derive(Clone)]
494struct KeyVersion {
495 version: u32,
496 key: Vec<u8>,
497 created_at: u64,
498}
499
500pub struct KeyRotationManager {
508 keys: Vec<KeyVersion>,
509 current_version: u32,
510 max_versions: usize,
511}
512
513impl KeyRotationManager {
514 pub fn new(max_versions: usize) -> Self {
516 Self {
517 keys: vec![],
518 current_version: 0,
519 max_versions: max_versions.max(1),
520 }
521 }
522
523 pub fn with_initial_key(key: Vec<u8>) -> Self {
525 let mut mgr = Self::new(3);
526 mgr.rotate_key(key);
527 mgr
528 }
529
530 pub fn rotate_key(&mut self, new_key: Vec<u8>) -> u32 {
532 self.current_version += 1;
533 let now = current_timestamp_secs();
534 self.keys.push(KeyVersion {
535 version: self.current_version,
536 key: new_key,
537 created_at: now,
538 });
539 while self.keys.len() > self.max_versions {
541 self.keys.remove(0);
542 }
543 self.current_version
544 }
545
546 pub fn sign(&self, message: &[u8]) -> (u32, Vec<u8>) {
548 if let Some(kv) = self.keys.last() {
549 let sig = hmac_sha256(&kv.key, message).to_vec();
550 (kv.version, sig)
551 } else {
552 (0, vec![])
553 }
554 }
555
556 pub fn verify(&self, message: &[u8], version: u32, signature: &[u8]) -> bool {
558 for kv in &self.keys {
559 if kv.version == version {
560 let expected = hmac_sha256(&kv.key, message);
561 return constant_time_eq(&expected, signature);
562 }
563 }
564 false
565 }
566
567 pub fn current_version(&self) -> u32 {
569 self.current_version
570 }
571
572 pub fn version_count(&self) -> usize {
574 self.keys.len()
575 }
576
577 pub fn versions(&self) -> Vec<u32> {
579 self.keys.iter().map(|kv| kv.version).collect()
580 }
581
582 pub fn key_created_at(&self, version: u32) -> Option<u64> {
584 self.keys
585 .iter()
586 .find(|kv| kv.version == version)
587 .map(|kv| kv.created_at)
588 }
589}
590
591fn current_timestamp_secs() -> u64 {
592 use std::time::{SystemTime, UNIX_EPOCH};
593 SystemTime::now()
594 .duration_since(UNIX_EPOCH)
595 .unwrap_or_default()
596 .as_secs()
597}
598
599use std::sync::RwLock;
604use std::time::Duration;
605
606const DEFAULT_ROTATION_INTERVAL_SECS: u64 = 90 * 24 * 60 * 60;
608
609#[derive(Debug, Clone)]
611pub struct VersionedKey {
612 pub version: u32,
614 pub key: Vec<u8>,
616 pub created_at: std::time::SystemTime,
618}
619
620pub struct KeyManager {
625 current: RwLock<VersionedKey>,
627 previous: RwLock<Vec<VersionedKey>>,
629 rotation_interval: Duration,
631 last_rotation: RwLock<std::time::SystemTime>,
633}
634
635impl KeyManager {
636 pub fn new(initial_key: Vec<u8>) -> Self {
638 let now = std::time::SystemTime::now();
639 Self {
640 current: RwLock::new(VersionedKey {
641 version: 1,
642 key: initial_key,
643 created_at: now,
644 }),
645 previous: RwLock::new(Vec::new()),
646 rotation_interval: Duration::from_secs(DEFAULT_ROTATION_INTERVAL_SECS),
647 last_rotation: RwLock::new(now),
648 }
649 }
650
651 pub fn with_rotation_interval(mut self, interval: Duration) -> Self {
653 self.rotation_interval = interval;
654 self
655 }
656
657 pub fn rotate(&self, new_key: Vec<u8>) -> Result<(), CryptoError> {
659 let mut current = self.current.write().expect("KeyManager lock poisoned");
660 let mut previous = self.previous.write().expect("KeyManager lock poisoned");
661
662 previous.push(current.clone());
664
665 if previous.len() > 3 {
667 previous.remove(0);
668 }
669
670 *current = VersionedKey {
672 version: current.version + 1,
673 key: new_key,
674 created_at: std::time::SystemTime::now(),
675 };
676
677 *self
678 .last_rotation
679 .write()
680 .expect("KeyManager last_rotation lock poisoned") = std::time::SystemTime::now();
681 Ok(())
682 }
683
684 pub fn needs_rotation(&self) -> bool {
686 let last = *self
687 .last_rotation
688 .read()
689 .expect("KeyManager last_rotation lock poisoned");
690 std::time::SystemTime::now()
691 .duration_since(last)
692 .map(|d| d >= self.rotation_interval)
693 .unwrap_or(false)
694 }
695
696 pub fn current_key(&self) -> VersionedKey {
698 self.current
699 .read()
700 .expect("KeyManager current lock poisoned")
701 .clone()
702 }
703
704 pub fn key_by_version(&self, version: u32) -> Option<VersionedKey> {
706 if self
707 .current
708 .read()
709 .expect("KeyManager current lock poisoned")
710 .version
711 == version
712 {
713 return Some(
714 self.current
715 .read()
716 .expect("KeyManager current lock poisoned")
717 .clone(),
718 );
719 }
720 self.previous
721 .read()
722 .expect("KeyManager previous lock poisoned")
723 .iter()
724 .find(|k| k.version == version)
725 .cloned()
726 }
727
728 pub fn previous_count(&self) -> usize {
730 self.previous
731 .read()
732 .expect("KeyManager previous lock poisoned")
733 .len()
734 }
735}
736
737fn hex_encode(bytes: &[u8]) -> String {
742 bytes.iter().map(|b| format!("{:02x}", b)).collect()
743}
744
745fn hex_decode(hex: &str) -> Result<Vec<u8>, ()> {
746 if !hex.len().is_multiple_of(2) {
747 return Err(());
748 }
749 (0..hex.len())
750 .step_by(2)
751 .map(|i| u8::from_str_radix(&hex[i..i + 2], 16).map_err(|_| ()))
752 .collect()
753}
754
755fn random_bytes(len: usize) -> Vec<u8> {
756 let mut result = vec![0u8; len];
757 OsRng.fill_bytes(&mut result);
758 result
759}
760
761#[derive(Debug)]
766pub enum CryptoError {
767 EncryptionFailed(String),
768 DecryptionFailed(String),
769 InvalidKey(String),
770 InvalidNonce(String),
771 InvalidHash(String),
772 SigningFailed(String),
773}
774
775impl std::fmt::Display for CryptoError {
776 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
777 match self {
778 CryptoError::EncryptionFailed(msg) => write!(f, "Encryption failed: {}", msg),
779 CryptoError::DecryptionFailed(msg) => write!(f, "Decryption failed: {}", msg),
780 CryptoError::InvalidKey(msg) => write!(f, "Invalid key: {}", msg),
781 CryptoError::InvalidNonce(msg) => write!(f, "Invalid nonce: {}", msg),
782 CryptoError::InvalidHash(msg) => write!(f, "Invalid hash: {}", msg),
783 CryptoError::SigningFailed(msg) => write!(f, "Signing failed: {}", msg),
784 }
785 }
786}
787
788impl std::error::Error for CryptoError {}
789
790impl serde::Serialize for CryptoError {
791 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
792 where
793 S: serde::Serializer,
794 {
795 serializer.serialize_str(&self.to_string())
796 }
797}
798
799#[cfg(test)]
804mod tests {
805 use super::*;
806
807 #[test]
810 fn test_sha256_empty() {
811 assert_eq!(
812 sha256_hex(b""),
813 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
814 );
815 }
816
817 #[test]
818 fn test_sha256_abc() {
819 assert_eq!(
820 sha256_hex(b"abc"),
821 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
822 );
823 }
824
825 #[test]
826 fn test_sha256_hello() {
827 assert_eq!(
828 sha256_hex(b"hello"),
829 "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"
830 );
831 }
832
833 #[test]
834 fn test_sha256_long_message() {
835 assert_eq!(
836 sha256_hex(b"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"),
837 "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
838 );
839 }
840
841 #[test]
842 fn test_sha256_deterministic() {
843 assert_eq!(sha256_hex(b"test"), sha256_hex(b"test"));
844 assert_ne!(sha256_hex(b"test"), sha256_hex(b"Test"));
845 }
846
847 #[test]
850 fn test_hmac_sha256_rfc4231_case1() {
851 let key = vec![0x0bu8; 20];
852 let result = hmac_sha256_hex(&key, b"Hi There");
853 assert_eq!(
854 result,
855 "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
856 );
857 }
858
859 #[test]
860 fn test_hmac_sha256_rfc4231_case2() {
861 let result = hmac_sha256_hex(b"Jefe", b"what do ya want for nothing?");
862 assert_eq!(
863 result,
864 "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
865 );
866 }
867
868 #[test]
869 fn test_hmac_sha256_long_key() {
870 let key = vec![0xaau8; 130];
871 let result = hmac_sha256_hex(&key, b"test message");
872 assert_eq!(result.len(), 64);
873 let short_key = vec![0xaau8; 32];
874 let result_short = hmac_sha256_hex(&short_key, b"test message");
875 assert_ne!(result, result_short);
876 }
877
878 #[test]
879 fn test_hmac_sha256_different_messages() {
880 let key = b"secret";
881 assert_ne!(hmac_sha256_hex(key, b"msg1"), hmac_sha256_hex(key, b"msg2"));
882 }
883
884 #[test]
887 fn test_aes_gcm_roundtrip() {
888 let key = [0x42u8; 32];
889 let crypter = AesGcmCrypter::new(&key);
890 let plaintext = b"Hello, World!";
891 let encrypted = crypter.encrypt(plaintext).unwrap();
892 let decrypted = crypter.decrypt(&encrypted).unwrap();
893 assert_eq!(decrypted, plaintext);
894 }
895
896 #[test]
897 fn test_aes_gcm_random_nonce_per_encryption() {
898 let key = [0x42u8; 32];
899 let crypter = AesGcmCrypter::new(&key);
900 let plaintext = b"same plaintext";
901 let encrypted1 = crypter.encrypt(plaintext).unwrap();
902 let encrypted2 = crypter.encrypt(plaintext).unwrap();
903 assert_ne!(encrypted1, encrypted2, "随机 nonce 应使密文不同");
904 assert_eq!(crypter.decrypt(&encrypted1).unwrap(), plaintext);
905 assert_eq!(crypter.decrypt(&encrypted2).unwrap(), plaintext);
906 }
907
908 #[test]
909 fn test_aes_gcm_from_key_str() {
910 let crypter = AesGcmCrypter::from_key_str("my-secret-key");
911 let plaintext = b"data to encrypt";
912 let encrypted = crypter.encrypt(plaintext).unwrap();
913 let decrypted = crypter.decrypt(&encrypted).unwrap();
914 assert_eq!(decrypted, plaintext);
915 }
916
917 #[test]
918 fn test_aes_gcm_short_ciphertext() {
919 let key = [0x42u8; 32];
920 let crypter = AesGcmCrypter::new(&key);
921 assert!(crypter.decrypt(&[0u8; 8]).is_err());
922 }
923
924 #[test]
925 fn test_aes_gcm_empty_plaintext() {
926 let key = [0x42u8; 32];
927 let crypter = AesGcmCrypter::new(&key);
928 let encrypted = crypter.encrypt(b"").unwrap();
929 assert_eq!(encrypted.len(), 28);
931 let decrypted = crypter.decrypt(&encrypted).unwrap();
932 assert_eq!(decrypted, b"");
933 }
934
935 #[test]
936 fn test_aes_gcm_tampered_ciphertext() {
937 let key = [0x42u8; 32];
938 let crypter = AesGcmCrypter::new(&key);
939 let encrypted = crypter.encrypt(b"sensitive data").unwrap();
940 let mut tampered = encrypted.clone();
941 tampered[15] ^= 0x01;
942 assert!(crypter.decrypt(&tampered).is_err());
943 }
944
945 #[test]
948 fn test_pbkdf2_hasher_hash_format() {
949 let hasher = Pbkdf2Hasher::new();
950 let hash = hasher.hash("password123").unwrap();
951 assert!(hash.starts_with('$'));
952 let parts: Vec<&str> = hash[1..].splitn(3, '$').collect();
953 assert_eq!(parts.len(), 3);
954 assert_eq!(parts[0].parse::<u32>().unwrap(), 100_000);
955 assert_eq!(parts[1].len(), 32);
957 assert_eq!(parts[2].len(), 64);
959 }
960
961 #[test]
962 fn test_pbkdf2_hasher_verify_correct() {
963 let hasher = Pbkdf2Hasher::new();
964 let hash = hasher.hash("password123").unwrap();
965 assert!(hasher.verify("password123", &hash).unwrap());
966 }
967
968 #[test]
969 fn test_pbkdf2_hasher_verify_wrong() {
970 let hasher = Pbkdf2Hasher::new();
971 let hash = hasher.hash("password123").unwrap();
972 assert!(!hasher.verify("wrongpassword", &hash).unwrap());
973 }
974
975 #[test]
976 fn test_pbkdf2_hasher_different_passwords_different_hashes() {
977 let hasher = Pbkdf2Hasher::new();
978 let h1 = hasher.hash("pass1").unwrap();
979 let h2 = hasher.hash("pass2").unwrap();
980 assert_ne!(h1, h2);
981 }
982
983 #[test]
984 fn test_pbkdf2_hasher_same_password_different_salts() {
985 let hasher = Pbkdf2Hasher::new();
986 let h1 = hasher.hash("same").unwrap();
987 let h2 = hasher.hash("same").unwrap();
988 assert_ne!(h1, h2);
989 assert!(hasher.verify("same", &h1).unwrap());
990 assert!(hasher.verify("same", &h2).unwrap());
991 }
992
993 #[test]
994 fn test_pbkdf2_hasher_invalid_format() {
995 let hasher = Pbkdf2Hasher::new();
996 assert!(hasher.verify("password", "invalid-hash").is_err());
997 assert!(hasher.verify("password", "$abc").is_err());
998 assert!(hasher.verify("password", "$abc$def").is_err());
999 }
1000
1001 #[test]
1002 fn test_pbkdf2_hasher_with_iterations() {
1003 let low = Pbkdf2Hasher::with_iterations(1000);
1005 assert!(low.hash("secret").is_err());
1006
1007 let hasher = Pbkdf2Hasher::with_iterations(100_000);
1008 let hash = hasher.hash("secret").unwrap();
1009 let parts: Vec<&str> = hash[1..].splitn(3, '$').collect();
1010 assert_eq!(parts[0], "100000");
1011 assert!(hasher.verify("secret", &hash).unwrap());
1012 }
1013
1014 #[test]
1015 fn test_pbkdf2_hasher_empty_password() {
1016 let hasher = Pbkdf2Hasher::new();
1017 assert!(hasher.hash("").is_err());
1018 }
1019
1020 #[test]
1023 fn test_hmac_signer_sign_not_empty() {
1024 let signer = HmacSigner::new();
1025 let mut params = HashMap::new();
1026 params.insert("name".to_string(), "test".to_string());
1027 let signature = signer.sign(¶ms, "secret123");
1028 assert_eq!(signature.len(), 64);
1029 }
1030
1031 #[test]
1032 fn test_hmac_signer_verify_correct() {
1033 let signer = HmacSigner::new();
1034 let mut params = HashMap::new();
1035 params.insert("name".to_string(), "test".to_string());
1036 params.insert("age".to_string(), "25".to_string());
1037
1038 let signature = signer.sign(¶ms, "mysecret");
1039 assert!(signer.verify(¶ms, "mysecret", &signature));
1040 }
1041
1042 #[test]
1043 fn test_hmac_signer_verify_wrong_secret() {
1044 let signer = HmacSigner::new();
1045 let mut params = HashMap::new();
1046 params.insert("name".to_string(), "test".to_string());
1047 let signature = signer.sign(¶ms, "correctsecret");
1048 assert!(!signer.verify(¶ms, "wrongsecret", &signature));
1049 }
1050
1051 #[test]
1052 fn test_hmac_signer_verify_wrong_signature() {
1053 let signer = HmacSigner::new();
1054 let mut params = HashMap::new();
1055 params.insert("name".to_string(), "test".to_string());
1056 let valid_sig = signer.sign(¶ms, "secret");
1057 let tampered = if let Some(stripped) = valid_sig.strip_prefix('0') {
1058 format!("1{}", stripped)
1059 } else {
1060 format!("0{}", &valid_sig[1..])
1061 };
1062 assert!(!signer.verify(¶ms, "secret", &tampered));
1063 }
1064
1065 #[test]
1066 fn test_hmac_signer_different_params_different_signatures() {
1067 let signer = HmacSigner::new();
1068 let mut params1 = HashMap::new();
1069 params1.insert("a".to_string(), "1".to_string());
1070
1071 let mut params2 = HashMap::new();
1072 params2.insert("b".to_string(), "2".to_string());
1073
1074 let sig1 = signer.sign(¶ms1, "secret");
1075 let sig2 = signer.sign(¶ms2, "secret");
1076 assert_ne!(sig1, sig2);
1077 }
1078
1079 #[test]
1080 fn test_hmac_signer_param_order_independent() {
1081 let signer = HmacSigner::new();
1082 let mut params1 = HashMap::new();
1083 params1.insert("b".to_string(), "2".to_string());
1084 params1.insert("a".to_string(), "1".to_string());
1085
1086 let mut params2 = HashMap::new();
1087 params2.insert("a".to_string(), "1".to_string());
1088 params2.insert("b".to_string(), "2".to_string());
1089
1090 let sig1 = signer.sign(¶ms1, "secret");
1091 let sig2 = signer.sign(¶ms2, "secret");
1092 assert_eq!(sig1, sig2);
1093 }
1094
1095 #[test]
1096 fn test_hmac_signer_empty_params() {
1097 let signer = HmacSigner::new();
1098 let params = HashMap::new();
1099 let sig = signer.sign(¶ms, "secret");
1100 assert_eq!(sig.len(), 64);
1101 assert!(signer.verify(¶ms, "secret", &sig));
1102 }
1103
1104 #[test]
1107 fn test_random_bytes_length() {
1108 assert_eq!(random_bytes(0).len(), 0);
1109 assert_eq!(random_bytes(16).len(), 16);
1110 assert_eq!(random_bytes(100).len(), 100);
1111 }
1112
1113 #[test]
1114 fn test_random_bytes_random() {
1115 let a = random_bytes(32);
1116 let b = random_bytes(32);
1117 assert_ne!(a, b, "随机字节序列应不同");
1118 }
1119
1120 #[test]
1121 fn test_constant_time_eq() {
1122 assert!(constant_time_eq(b"abc", b"abc"));
1123 assert!(!constant_time_eq(b"abc", b"abd"));
1124 assert!(!constant_time_eq(b"abc", b"ab"));
1125 assert!(!constant_time_eq(b"abc", b"abcd"));
1126 assert!(constant_time_eq(b"", b""));
1127 }
1128
1129 #[test]
1130 fn test_hex_encode_decode_roundtrip() {
1131 let original = vec![0x00, 0xff, 0xab, 0x42];
1132 let encoded = hex_encode(&original);
1133 let decoded = hex_decode(&encoded).unwrap();
1134 assert_eq!(decoded, original);
1135 }
1136
1137 #[test]
1138 fn test_hex_decode_invalid() {
1139 assert!(hex_decode("abc").is_err());
1140 assert!(hex_decode("xy").is_err());
1141 }
1142
1143 #[test]
1146 fn test_aes_gcm_aad_roundtrip() {
1147 let key = [0x42u8; 32];
1148 let crypter = AesGcmCrypter::new(&key);
1149 let plaintext = b"sensitive data";
1150 let aad = b"associated metadata";
1151 let encrypted = crypter.encrypt_with_aad(plaintext, aad).unwrap();
1152 let decrypted = crypter.decrypt_with_aad(&encrypted, aad).unwrap();
1153 assert_eq!(decrypted, plaintext);
1154 }
1155
1156 #[test]
1157 fn test_aes_gcm_aad_wrong_aad_fails() {
1158 let key = [0x42u8; 32];
1159 let crypter = AesGcmCrypter::new(&key);
1160 let plaintext = b"sensitive data";
1161 let aad = b"correct aad";
1162 let encrypted = crypter.encrypt_with_aad(plaintext, aad).unwrap();
1163 let result = crypter.decrypt_with_aad(&encrypted, b"wrong aad");
1165 assert!(result.is_err());
1166 }
1167
1168 #[test]
1169 fn test_aes_gcm_aad_empty_aad_equivalent_to_no_aad() {
1170 let key = [0x42u8; 32];
1171 let crypter = AesGcmCrypter::new(&key);
1172 let plaintext = b"test data";
1173 let encrypted_no_aad = crypter.encrypt(plaintext).unwrap();
1175 let encrypted_empty_aad = crypter.encrypt_with_aad(plaintext, b"").unwrap();
1176 assert_eq!(crypter.decrypt(&encrypted_no_aad).unwrap(), plaintext);
1178 assert_eq!(
1179 crypter.decrypt_with_aad(&encrypted_empty_aad, b"").unwrap(),
1180 plaintext
1181 );
1182 }
1183
1184 #[test]
1185 fn test_aes_gcm_aad_tampered_ciphertext_fails() {
1186 let key = [0x42u8; 32];
1187 let crypter = AesGcmCrypter::new(&key);
1188 let encrypted = crypter.encrypt_with_aad(b"data", b"aad").unwrap();
1189 let mut tampered = encrypted.clone();
1190 tampered[15] ^= 0x01;
1191 assert!(crypter.decrypt_with_aad(&tampered, b"aad").is_err());
1192 }
1193
1194 #[test]
1195 fn test_aes_gcm_aad_empty_plaintext() {
1196 let key = [0x42u8; 32];
1197 let crypter = AesGcmCrypter::new(&key);
1198 let encrypted = crypter.encrypt_with_aad(b"", b"aad").unwrap();
1199 assert_eq!(encrypted.len(), 28);
1201 let decrypted = crypter.decrypt_with_aad(&encrypted, b"aad").unwrap();
1202 assert_eq!(decrypted, b"");
1203 }
1204
1205 #[test]
1208 fn test_rsa_oaep_roundtrip() {
1209 let crypter = RsaOaepCrypter::generate(2048).expect("RSA key generation");
1210 let plaintext = b"Hello, RSA-OAEP!";
1211 let encrypted = crypter.encrypt(plaintext).unwrap();
1212 let decrypted = crypter.decrypt(&encrypted).unwrap();
1213 assert_eq!(decrypted, plaintext);
1214 }
1215
1216 #[test]
1217 fn test_rsa_oaep_different_ciphertexts_same_plaintext() {
1218 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1219 let plaintext = b"same message";
1220 let enc1 = crypter.encrypt(plaintext).unwrap();
1221 let enc2 = crypter.encrypt(plaintext).unwrap();
1222 assert_ne!(enc1, enc2);
1224 assert_eq!(crypter.decrypt(&enc1).unwrap(), plaintext);
1226 assert_eq!(crypter.decrypt(&enc2).unwrap(), plaintext);
1227 }
1228
1229 #[test]
1230 fn test_rsa_oaep_empty_plaintext() {
1231 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1232 let encrypted = crypter.encrypt(b"").unwrap();
1233 let decrypted = crypter.decrypt(&encrypted).unwrap();
1234 assert_eq!(decrypted, b"");
1235 }
1236
1237 #[test]
1238 fn test_rsa_oaep_tampered_ciphertext_fails() {
1239 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1240 let encrypted = crypter.encrypt(b"secret").unwrap();
1241 let mut tampered = encrypted.clone();
1242 tampered[0] ^= 0x01;
1243 assert!(crypter.decrypt(&tampered).is_err());
1244 }
1245
1246 #[test]
1247 fn test_rsa_oaep_max_message_length() {
1248 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1250 let plaintext = vec![0xABu8; 190];
1251 let encrypted = crypter.encrypt(&plaintext).unwrap();
1252 let decrypted = crypter.decrypt(&encrypted).unwrap();
1253 assert_eq!(decrypted, plaintext);
1254 }
1255
1256 #[test]
1257 fn test_rsa_oaep_oversized_message_fails() {
1258 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1259 let plaintext = vec![0xABu8; 191];
1261 assert!(crypter.encrypt(&plaintext).is_err());
1262 }
1263
1264 #[test]
1265 fn test_rsa_oaep_from_keys() {
1266 let crypter1 = RsaOaepCrypter::generate(2048).unwrap();
1267 let crypter2 = RsaOaepCrypter::from_keys(
1268 crypter1.public_key().clone(),
1269 crypter1.private_key().clone(),
1270 );
1271 let plaintext = b"test from_keys";
1272 let encrypted = crypter2.encrypt(plaintext).unwrap();
1273 let decrypted = crypter2.decrypt(&encrypted).unwrap();
1274 assert_eq!(decrypted, plaintext);
1275 }
1276
1277 #[test]
1278 fn test_rsa_oaep_crypter_trait() {
1279 let crypter = RsaOaepCrypter::generate(2048).unwrap();
1280 let plaintext = b"trait test";
1281 let encrypted = Crypter::encrypt(&crypter, plaintext).unwrap();
1282 let decrypted = Crypter::decrypt(&crypter, &encrypted).unwrap();
1283 assert_eq!(decrypted, plaintext);
1284 }
1285
1286 #[test]
1289 fn test_hmac_signature_verifier_sign_verify() {
1290 let verifier = HmacSignatureVerifier::new(b"my-secret-key");
1291 let message = b"important message";
1292 let signature = verifier.sign(message);
1293 assert_eq!(signature.len(), 32);
1294 assert!(verifier.verify(message, &signature));
1295 }
1296
1297 #[test]
1298 fn test_hmac_signature_verifier_wrong_message() {
1299 let verifier = HmacSignatureVerifier::new(b"key");
1300 let signature = verifier.sign(b"message1");
1301 assert!(!verifier.verify(b"message2", &signature));
1302 }
1303
1304 #[test]
1305 fn test_hmac_signature_verifier_wrong_signature() {
1306 let verifier = HmacSignatureVerifier::new(b"key");
1307 let signature = verifier.sign(b"message");
1308 let mut tampered = signature.clone();
1309 tampered[0] ^= 0x01;
1310 assert!(!verifier.verify(b"message", &tampered));
1311 }
1312
1313 #[test]
1314 fn test_hmac_signature_verifier_from_key_str() {
1315 let verifier = HmacSignatureVerifier::from_key_str("string-key");
1316 let message = b"test";
1317 let sig = verifier.sign(message);
1318 assert!(verifier.verify(message, &sig));
1319 }
1320
1321 #[test]
1322 fn test_hmac_signature_verifier_different_keys_different_signatures() {
1323 let v1 = HmacSignatureVerifier::new(b"key1");
1324 let v2 = HmacSignatureVerifier::new(b"key2");
1325 let message = b"same message";
1326 let sig1 = v1.sign(message);
1327 let sig2 = v2.sign(message);
1328 assert_ne!(sig1, sig2);
1329 }
1330
1331 #[test]
1332 fn test_hmac_signature_verifier_empty_message() {
1333 let verifier = HmacSignatureVerifier::new(b"key");
1334 let sig = verifier.sign(b"");
1335 assert_eq!(sig.len(), 32);
1336 assert!(verifier.verify(b"", &sig));
1337 }
1338
1339 #[test]
1340 fn test_hmac_signature_verifier_wrong_length_signature() {
1341 let verifier = HmacSignatureVerifier::new(b"key");
1342 assert!(!verifier.verify(b"message", b"short"));
1344 assert!(!verifier.verify(b"message", &[]));
1345 }
1346
1347 #[test]
1350 fn test_key_rotation_initial_key() {
1351 let mgr = KeyRotationManager::with_initial_key(b"key-v1".to_vec());
1352 assert_eq!(mgr.current_version(), 1);
1353 assert_eq!(mgr.version_count(), 1);
1354 assert_eq!(mgr.versions(), vec![1]);
1355 }
1356
1357 #[test]
1358 fn test_key_rotation_sign_verify_current() {
1359 let mgr = KeyRotationManager::with_initial_key(b"secret-key".to_vec());
1360 let message = b"test message";
1361 let (version, signature) = mgr.sign(message);
1362 assert_eq!(version, 1);
1363 assert!(mgr.verify(message, version, &signature));
1364 }
1365
1366 #[test]
1367 fn test_key_rotation_old_version_still_valid() {
1368 let mut mgr = KeyRotationManager::with_initial_key(b"key-v1".to_vec());
1369 let message = b"persistent message";
1370 let (v1, sig1) = mgr.sign(message);
1371 mgr.rotate_key(b"key-v2".to_vec());
1373 let (v2, sig2) = mgr.sign(message);
1374 assert_eq!(v1, 1);
1375 assert_eq!(v2, 2);
1376 assert!(mgr.verify(message, v1, &sig1));
1378 assert!(mgr.verify(message, v2, &sig2));
1380 }
1381
1382 #[test]
1383 fn test_key_rotation_max_versions_evicts_oldest() {
1384 let mut mgr = KeyRotationManager::new(2);
1385 mgr.rotate_key(b"key-v1".to_vec());
1386 mgr.rotate_key(b"key-v2".to_vec());
1387 assert_eq!(mgr.version_count(), 2);
1388 mgr.rotate_key(b"key-v3".to_vec());
1390 assert_eq!(mgr.version_count(), 2);
1391 assert_eq!(mgr.versions(), vec![2, 3]);
1392 assert!(!mgr.versions().contains(&1));
1393 }
1394
1395 #[test]
1396 fn test_key_rotation_old_version_evicted_fails_verify() {
1397 let mut mgr = KeyRotationManager::new(2);
1398 mgr.rotate_key(b"key-v1".to_vec());
1399 let message = b"test";
1400 let (v1, sig1) = mgr.sign(message);
1401 mgr.rotate_key(b"key-v2".to_vec());
1402 mgr.rotate_key(b"key-v3".to_vec());
1403 assert!(!mgr.verify(message, v1, &sig1));
1405 }
1406
1407 #[test]
1408 fn test_key_rotation_wrong_version_fails() {
1409 let mgr = KeyRotationManager::with_initial_key(b"key".to_vec());
1410 let message = b"test";
1411 let (_, signature) = mgr.sign(message);
1412 assert!(!mgr.verify(message, 999, &signature));
1414 }
1415
1416 #[test]
1417 fn test_key_rotation_multiple_rotations() {
1418 let mut mgr = KeyRotationManager::new(5);
1419 for i in 1..=4 {
1420 let key = format!("key-v{}", i);
1421 let version = mgr.rotate_key(key.as_bytes().to_vec());
1422 assert_eq!(version, i as u32);
1423 }
1424 assert_eq!(mgr.current_version(), 4);
1425 assert_eq!(mgr.version_count(), 4);
1426 assert_eq!(mgr.versions(), vec![1, 2, 3, 4]);
1427 }
1428
1429 #[test]
1430 fn test_key_rotation_empty_manager_sign_returns_zero() {
1431 let mgr = KeyRotationManager::new(3);
1432 let (version, sig) = mgr.sign(b"message");
1433 assert_eq!(version, 0);
1434 assert!(sig.is_empty());
1435 }
1436
1437 #[test]
1438 fn test_key_rotation_verify_with_wrong_signature() {
1439 let mgr = KeyRotationManager::with_initial_key(b"key".to_vec());
1440 let message = b"test";
1441 let (version, _) = mgr.sign(message);
1442 let wrong_sig = vec![0u8; 32];
1443 assert!(!mgr.verify(message, version, &wrong_sig));
1444 }
1445
1446 #[test]
1447 fn test_key_rotation_max_versions_min_one() {
1448 let mut mgr = KeyRotationManager::new(0);
1450 mgr.rotate_key(b"k1".to_vec());
1451 mgr.rotate_key(b"k2".to_vec());
1452 assert_eq!(mgr.version_count(), 1);
1453 assert_eq!(mgr.versions(), vec![2]);
1454 }
1455
1456 #[test]
1459 fn test_key_manager_initial_key() {
1460 let mgr = KeyManager::new(b"initial-key".to_vec());
1461 let current = mgr.current_key();
1462 assert_eq!(current.version, 1);
1463 assert_eq!(current.key, b"initial-key");
1464 assert_eq!(mgr.previous_count(), 0);
1465 }
1466
1467 #[test]
1468 fn test_key_manager_rotate_increments_version() {
1469 let mgr = KeyManager::new(b"v1".to_vec());
1470 assert!(mgr.rotate(b"v2".to_vec()).is_ok());
1471 let current = mgr.current_key();
1472 assert_eq!(current.version, 2);
1473 assert_eq!(current.key, b"v2");
1474 assert_eq!(mgr.previous_count(), 1);
1475 }
1476
1477 #[test]
1478 fn test_key_manager_key_by_version_current() {
1479 let mgr = KeyManager::new(b"v1".to_vec());
1480 let found = mgr.key_by_version(1).expect("v1 should exist");
1481 assert_eq!(found.key, b"v1");
1482 }
1483
1484 #[test]
1485 fn test_key_manager_key_by_version_previous() {
1486 let mgr = KeyManager::new(b"v1".to_vec());
1487 mgr.rotate(b"v2".to_vec()).unwrap();
1488 let old = mgr.key_by_version(1).expect("v1 should still be retained");
1490 assert_eq!(old.key, b"v1");
1491 let new = mgr.key_by_version(2).expect("v2 should exist");
1493 assert_eq!(new.key, b"v2");
1494 }
1495
1496 #[test]
1497 fn test_key_manager_key_by_version_not_found() {
1498 let mgr = KeyManager::new(b"v1".to_vec());
1499 assert!(mgr.key_by_version(999).is_none());
1500 }
1501
1502 #[test]
1503 fn test_key_manager_retains_at_most_three_previous() {
1504 let mgr = KeyManager::new(b"v1".to_vec());
1505 mgr.rotate(b"v2".to_vec()).unwrap();
1506 mgr.rotate(b"v3".to_vec()).unwrap();
1507 mgr.rotate(b"v4".to_vec()).unwrap();
1508 assert_eq!(mgr.previous_count(), 3);
1510 mgr.rotate(b"v5".to_vec()).unwrap();
1511 assert_eq!(mgr.previous_count(), 3);
1512 assert!(mgr.key_by_version(1).is_none());
1514 assert!(mgr.key_by_version(2).is_some());
1516 assert_eq!(mgr.current_key().version, 5);
1518 }
1519
1520 #[test]
1521 fn test_key_manager_needs_rotation_false_initially() {
1522 let mgr = KeyManager::new(b"k".to_vec());
1523 assert!(!mgr.needs_rotation());
1525 }
1526
1527 #[test]
1528 fn test_key_manager_needs_rotation_true_after_interval() {
1529 let mgr = KeyManager::new(b"k".to_vec()).with_rotation_interval(Duration::from_millis(0));
1530 std::thread::sleep(Duration::from_millis(1));
1532 assert!(mgr.needs_rotation());
1533 }
1534
1535 #[test]
1536 fn test_key_manager_with_rotation_interval() {
1537 let mgr = KeyManager::new(b"k".to_vec()).with_rotation_interval(Duration::from_secs(60));
1538 assert!(!mgr.needs_rotation());
1539 }
1540
1541 #[test]
1542 fn test_key_manager_rotate_resets_last_rotation() {
1543 let mgr = KeyManager::new(b"k".to_vec()).with_rotation_interval(Duration::from_millis(1));
1544 std::thread::sleep(Duration::from_millis(5));
1545 assert!(mgr.needs_rotation());
1546 mgr.rotate(b"k2".to_vec()).unwrap();
1547 assert!(!mgr.needs_rotation());
1549 }
1550
1551 #[test]
1552 fn test_key_manager_concurrent_access() {
1553 use std::sync::Arc;
1554 use std::thread;
1555 let mgr = Arc::new(KeyManager::new(b"base".to_vec()));
1556 let mut handles = vec![];
1557 for _ in 0..4 {
1559 let m = mgr.clone();
1560 handles.push(thread::spawn(move || {
1561 let _ = m.current_key();
1562 let _ = m.previous_count();
1563 }));
1564 }
1565 for h in handles {
1566 h.join().expect("thread panicked");
1567 }
1568 assert_eq!(mgr.current_key().version, 1);
1570 }
1571}