1use std::collections::HashMap;
7
8use zeroize::{Zeroize, ZeroizeOnDrop};
9
10use super::{
11 crypto::{decrypt_private_key, derive_encryption_key, encrypt_private_key},
12 errors::UserError,
13 types::{KeyStorage, UserKey},
14};
15use crate::{
16 Result,
17 auth::crypto::{PrivateKey, PublicKey},
18};
19
20pub struct UserKeyManager {
30 decrypted_keys: HashMap<PublicKey, PrivateKey>,
32
33 key_metadata: HashMap<PublicKey, UserKey>,
35
36 encryption_key: Option<Vec<u8>>,
39}
40
41impl UserKeyManager {
42 pub fn new(password: &str, salt: &str, encrypted_keys: Vec<UserKey>) -> Result<Self> {
54 let encryption_key = derive_encryption_key(password, salt)?;
56
57 let capacity = encrypted_keys.len();
59 let mut manager = Self {
60 decrypted_keys: HashMap::with_capacity(capacity),
61 key_metadata: HashMap::with_capacity(capacity),
62 encryption_key: Some(encryption_key),
63 };
64
65 for user_key in encrypted_keys {
67 manager.add_key(user_key)?;
68 }
69
70 Ok(manager)
71 }
72
73 pub fn new_passwordless(keys: Vec<UserKey>) -> Result<Self> {
83 let capacity = keys.len();
84 let mut manager = Self {
85 decrypted_keys: HashMap::with_capacity(capacity),
86 key_metadata: HashMap::with_capacity(capacity),
87 encryption_key: None,
88 };
89
90 for user_key in keys {
92 manager.add_key(user_key)?;
93 }
94
95 Ok(manager)
96 }
97
98 pub fn get_signing_key(&self, key_id: &PublicKey) -> Option<&PrivateKey> {
106 self.decrypted_keys.get(key_id)
107 }
108
109 pub fn add_key(&mut self, metadata: UserKey) -> Result<()> {
120 let signing_key = match &metadata.storage {
122 KeyStorage::Encrypted {
123 algorithm,
124 ciphertext,
125 nonce,
126 } => {
127 if algorithm != "aes-256-gcm" {
129 return Err(UserError::DecryptionFailed {
130 reason: format!("Unsupported encryption algorithm: {algorithm}"),
131 }
132 .into());
133 }
134 let encryption_key =
136 self.encryption_key
137 .as_ref()
138 .ok_or_else(|| UserError::PasswordRequired {
139 operation: "decrypt encrypted key".to_string(),
140 })?;
141 decrypt_private_key(ciphertext, nonce, encryption_key)?
142 }
143 KeyStorage::Unencrypted { key } => {
144 key.clone()
146 }
147 };
148
149 let key_id = metadata.key_id.clone();
150 self.decrypted_keys.insert(key_id.clone(), signing_key);
151 self.key_metadata.insert(key_id, metadata);
152
153 Ok(())
154 }
155
156 pub fn serialize_keys(&self) -> Result<Vec<UserKey>> {
167 let mut serialized = Vec::new();
168
169 for (key_id, signing_key) in &self.decrypted_keys {
170 let metadata = self
172 .key_metadata
173 .get(key_id)
174 .ok_or_else(|| UserError::KeyNotFound {
175 key_id: key_id.to_string(),
176 })?;
177
178 let storage = match &metadata.storage {
180 KeyStorage::Encrypted { algorithm, .. } => {
181 let encryption_key = self.encryption_key.as_ref().ok_or_else(|| {
183 UserError::PasswordRequired {
184 operation: "encrypt key".to_string(),
185 }
186 })?;
187 let (ciphertext, nonce) = encrypt_private_key(signing_key, encryption_key)?;
188 KeyStorage::Encrypted {
189 algorithm: algorithm.clone(),
190 ciphertext,
191 nonce,
192 }
193 }
194 KeyStorage::Unencrypted { .. } => {
195 KeyStorage::Unencrypted {
197 key: signing_key.clone(),
198 }
199 }
200 };
201
202 let updated_key = UserKey {
204 key_id: key_id.clone(),
205 storage,
206 display_name: metadata.display_name.clone(),
207 created_at: metadata.created_at,
208 last_used: metadata.last_used,
209 is_default: metadata.is_default,
210 database_sigkeys: metadata.database_sigkeys.clone(),
211 };
212
213 serialized.push(updated_key);
214 }
215
216 serialized.sort_by(|a, b| a.key_id.to_string().cmp(&b.key_id.to_string()));
218
219 Ok(serialized)
220 }
221
222 pub fn clear(&mut self) {
227 self.zeroize();
228 }
229
230 pub fn list_key_ids(&self) -> Vec<PublicKey> {
234 let mut keys: Vec<(PublicKey, i64)> = self
235 .decrypted_keys
236 .keys()
237 .filter_map(|key_id| {
238 self.key_metadata
239 .get(key_id)
240 .map(|meta| (key_id.clone(), meta.created_at))
241 })
242 .collect();
243
244 keys.sort_by_key(|(_, created_at)| *created_at);
246
247 keys.into_iter().map(|(key_id, _)| key_id).collect()
249 }
250
251 pub fn get_key_metadata(&self, key_id: &PublicKey) -> Option<&UserKey> {
253 self.key_metadata.get(key_id)
254 }
255
256 pub fn get_default_key_id(&self) -> Option<PublicKey> {
264 for (key_id, metadata) in &self.key_metadata {
266 if metadata.is_default {
267 return Some(key_id.clone());
268 }
269 }
270
271 self.list_key_ids().first().cloned()
273 }
274
275 #[allow(dead_code)]
296 pub(super) fn encryption_key(&self) -> Option<&[u8]> {
297 self.encryption_key.as_deref()
298 }
299}
300
301impl Zeroize for UserKeyManager {
302 fn zeroize(&mut self) {
303 if let Some(key) = &mut self.encryption_key {
305 key.zeroize();
306 }
307
308 self.decrypted_keys.clear();
310
311 self.key_metadata.clear();
313 }
314}
315
316impl ZeroizeOnDrop for UserKeyManager {}
317
318#[cfg(test)]
319mod tests {
320 use super::*;
321 use crate::auth::crypto::generate_keypair;
322 use crate::user::crypto::{encrypt_private_key, hash_password};
323 use crate::{Clock, Error, SystemClock};
324
325 fn create_test_user_key(signing_key: &PrivateKey, encryption_key: &[u8]) -> UserKey {
326 let (ciphertext, nonce) = encrypt_private_key(signing_key, encryption_key).unwrap();
327 let key_id = signing_key.public_key();
328
329 UserKey {
330 key_id,
331 storage: KeyStorage::Encrypted {
332 algorithm: "aes-256-gcm".to_string(),
333 ciphertext,
334 nonce,
335 },
336 display_name: Some("Test key".to_string()),
337 created_at: SystemClock.now_secs(),
338 last_used: None,
339 is_default: false,
340 database_sigkeys: HashMap::new(),
341 }
342 }
343
344 #[test]
345 #[cfg_attr(miri, ignore)] fn test_key_manager_new() {
347 let password = "test_password";
348 let (_, salt) = hash_password(password).unwrap();
349 let encryption_key = derive_encryption_key(password, &salt).unwrap();
350
351 let (key1, pub1) = generate_keypair();
353 let (key2, pub2) = generate_keypair();
354
355 let user_key1 = create_test_user_key(&key1, &encryption_key);
356 let user_key2 = create_test_user_key(&key2, &encryption_key);
357
358 let manager = UserKeyManager::new(password, &salt, vec![user_key1, user_key2]).unwrap();
360
361 assert!(manager.get_signing_key(&pub1).is_some());
363 assert!(manager.get_signing_key(&pub2).is_some());
364
365 let (_, nonexistent) = generate_keypair();
367 assert!(manager.get_signing_key(&nonexistent).is_none());
368 }
369
370 #[test]
371 #[cfg_attr(miri, ignore)] fn test_key_manager_get_signing_key() {
373 let password = "test_password";
374 let (_, salt) = hash_password(password).unwrap();
375 let encryption_key = derive_encryption_key(password, &salt).unwrap();
376
377 let (key1, pub1) = generate_keypair();
378 let user_key1 = create_test_user_key(&key1, &encryption_key);
379
380 let manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
381
382 let retrieved_key = manager.get_signing_key(&pub1).unwrap();
384 assert_eq!(retrieved_key.to_bytes(), key1.to_bytes());
385 }
386
387 #[test]
388 #[cfg_attr(miri, ignore)] fn test_key_manager_signing_key_produces_correct_public_key() {
390 let password = "test_password";
391 let (_, salt) = hash_password(password).unwrap();
392 let encryption_key = derive_encryption_key(password, &salt).unwrap();
393
394 let (key1, pub_key1) = generate_keypair();
395 let user_key1 = create_test_user_key(&key1, &encryption_key);
396
397 let manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
398
399 let signing_key = manager.get_signing_key(&pub_key1).unwrap();
401 assert_eq!(signing_key.public_key(), pub_key1);
402 }
403
404 #[test]
405 #[cfg_attr(miri, ignore)] fn test_key_manager_multiple_keys() {
407 let password = "test_password";
408 let (_, salt) = hash_password(password).unwrap();
409 let encryption_key = derive_encryption_key(password, &salt).unwrap();
410
411 let (key1, pub_key1) = generate_keypair();
413 let (key2, pub_key2) = generate_keypair();
414 let (key3, pub_key3) = generate_keypair();
415
416 let user_key1 = create_test_user_key(&key1, &encryption_key);
417 let user_key2 = create_test_user_key(&key2, &encryption_key);
418 let user_key3 = create_test_user_key(&key3, &encryption_key);
419
420 let manager =
421 UserKeyManager::new(password, &salt, vec![user_key1, user_key2, user_key3]).unwrap();
422
423 assert!(manager.get_signing_key(&pub_key1).is_some());
425 assert!(manager.get_signing_key(&pub_key2).is_some());
426 assert!(manager.get_signing_key(&pub_key3).is_some());
427
428 assert_ne!(pub_key1, pub_key2);
430 assert_ne!(pub_key2, pub_key3);
431 assert_ne!(pub_key1, pub_key3);
432 }
433
434 #[test]
435 #[cfg_attr(miri, ignore)] fn test_key_manager_passwordless() {
437 let (key1, pub_key1) = generate_keypair();
439 let (key2, pub_key2) = generate_keypair();
440
441 let user_key1 = UserKey {
442 key_id: pub_key1.clone(),
443 storage: KeyStorage::Unencrypted { key: key1.clone() },
444 display_name: Some("Key 1".to_string()),
445 created_at: SystemClock.now_secs(),
446 last_used: None,
447 is_default: true,
448 database_sigkeys: HashMap::new(),
449 };
450
451 let user_key2 = UserKey {
452 key_id: pub_key2.clone(),
453 storage: KeyStorage::Unencrypted { key: key2.clone() },
454 display_name: Some("Key 2".to_string()),
455 created_at: SystemClock.now_secs(),
456 last_used: None,
457 is_default: false,
458 database_sigkeys: HashMap::new(),
459 };
460
461 let manager = UserKeyManager::new_passwordless(vec![user_key1, user_key2]).unwrap();
462
463 assert!(manager.get_signing_key(&pub_key1).is_some());
465 assert!(manager.get_signing_key(&pub_key2).is_some());
466 }
467
468 #[test]
469 #[cfg_attr(miri, ignore)] fn test_key_manager_add_key() {
471 let password = "test_password";
472 let (_, salt) = hash_password(password).unwrap();
473 let encryption_key = derive_encryption_key(password, &salt).unwrap();
474
475 let (key1, _) = generate_keypair();
476 let user_key1 = create_test_user_key(&key1, &encryption_key);
477
478 let mut manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
479
480 let (key2, pub2) = generate_keypair();
482 let user_key2 = create_test_user_key(&key2, &encryption_key);
483 manager.add_key(user_key2).unwrap();
484
485 assert!(manager.get_signing_key(&pub2).is_some());
487 let retrieved_key = manager.get_signing_key(&pub2).unwrap();
488 assert_eq!(retrieved_key.to_bytes(), key2.to_bytes());
489 }
490
491 #[test]
492 #[cfg_attr(miri, ignore)] fn test_key_manager_serialize_keys() {
494 let password = "test_password";
495 let (_, salt) = hash_password(password).unwrap();
496 let encryption_key = derive_encryption_key(password, &salt).unwrap();
497
498 let (key1, pub1) = generate_keypair();
499 let user_key1 = create_test_user_key(&key1, &encryption_key);
500
501 let manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
502
503 let serialized = manager.serialize_keys().unwrap();
505 assert_eq!(serialized.len(), 1);
506
507 let serialized_key = &serialized[0];
509 assert_eq!(serialized_key.key_id, pub1);
510
511 let (ciphertext, nonce) = match &serialized_key.storage {
513 KeyStorage::Encrypted {
514 ciphertext, nonce, ..
515 } => (ciphertext, nonce),
516 KeyStorage::Unencrypted { .. } => panic!("Expected encrypted key"),
517 };
518
519 let decrypted = decrypt_private_key(ciphertext, nonce, &encryption_key).unwrap();
520 assert_eq!(decrypted.to_bytes(), key1.to_bytes());
521 }
522
523 #[test]
524 #[cfg_attr(miri, ignore)] fn test_key_manager_serialize_keys_sorted() {
526 let password = "test_password";
527 let (_, salt) = hash_password(password).unwrap();
528 let encryption_key = derive_encryption_key(password, &salt).unwrap();
529
530 let (key1, _) = generate_keypair();
531 let (key2, _) = generate_keypair();
532 let (key3, _) = generate_keypair();
533
534 let user_key1 = create_test_user_key(&key1, &encryption_key);
535 let user_key2 = create_test_user_key(&key2, &encryption_key);
536 let user_key3 = create_test_user_key(&key3, &encryption_key);
537
538 let manager =
539 UserKeyManager::new(password, &salt, vec![user_key1, user_key2, user_key3]).unwrap();
540
541 let serialized = manager.serialize_keys().unwrap();
543 assert_eq!(serialized.len(), 3);
544
545 let ids: Vec<String> = serialized.iter().map(|k| k.key_id.to_string()).collect();
547 let mut sorted_ids = ids.clone();
548 sorted_ids.sort();
549 assert_eq!(ids, sorted_ids);
550 }
551
552 #[test]
553 #[cfg_attr(miri, ignore)] fn test_key_manager_clear() {
555 let password = "test_password";
556 let (_, salt) = hash_password(password).unwrap();
557 let encryption_key = derive_encryption_key(password, &salt).unwrap();
558
559 let (key1, pub1) = generate_keypair();
560 let user_key1 = create_test_user_key(&key1, &encryption_key);
561
562 let mut manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
563
564 assert!(manager.get_signing_key(&pub1).is_some());
566
567 manager.clear();
569
570 assert!(manager.get_signing_key(&pub1).is_none());
572 assert_eq!(manager.list_key_ids().len(), 0);
573 }
574
575 #[test]
576 #[cfg_attr(miri, ignore)] fn test_key_manager_list_key_ids() {
578 let password = "test_password";
579 let (_, salt) = hash_password(password).unwrap();
580 let encryption_key = derive_encryption_key(password, &salt).unwrap();
581
582 let (key1, pub1) = generate_keypair();
583 let (key2, pub2) = generate_keypair();
584 let user_key1 = create_test_user_key(&key1, &encryption_key);
585 let user_key2 = create_test_user_key(&key2, &encryption_key);
586
587 let manager = UserKeyManager::new(password, &salt, vec![user_key1, user_key2]).unwrap();
588
589 let key_ids = manager.list_key_ids();
590 assert_eq!(key_ids.len(), 2);
591 assert!(key_ids.contains(&pub1));
592 assert!(key_ids.contains(&pub2));
593 }
594
595 #[test]
596 #[cfg_attr(miri, ignore)] fn test_key_manager_list_key_ids_sorted_by_timestamp() {
598 let password = "test_password";
599 let (_, salt) = hash_password(password).unwrap();
600 let encryption_key = derive_encryption_key(password, &salt).unwrap();
601
602 let (key_new, pub_new) = generate_keypair();
604 let (key_old, pub_old) = generate_keypair();
605 let (key_mid, pub_mid) = generate_keypair();
606
607 let (ct_new, nonce_new) = encrypt_private_key(&key_new, &encryption_key).unwrap();
608 let (ct_old, nonce_old) = encrypt_private_key(&key_old, &encryption_key).unwrap();
609 let (ct_mid, nonce_mid) = encrypt_private_key(&key_mid, &encryption_key).unwrap();
610
611 let user_key_old = UserKey {
613 key_id: pub_old.clone(),
614 storage: KeyStorage::Encrypted {
615 algorithm: "aes-256-gcm".to_string(),
616 ciphertext: ct_old,
617 nonce: nonce_old,
618 },
619 display_name: Some("Old Key".to_string()),
620 created_at: 1000, last_used: None,
622 is_default: true, database_sigkeys: HashMap::new(),
624 };
625
626 let user_key_mid = UserKey {
627 key_id: pub_mid.clone(),
628 storage: KeyStorage::Encrypted {
629 algorithm: "aes-256-gcm".to_string(),
630 ciphertext: ct_mid,
631 nonce: nonce_mid,
632 },
633 display_name: Some("Mid Key".to_string()),
634 created_at: 2000, last_used: None,
636 is_default: false,
637 database_sigkeys: HashMap::new(),
638 };
639
640 let user_key_new = UserKey {
641 key_id: pub_new.clone(),
642 storage: KeyStorage::Encrypted {
643 algorithm: "aes-256-gcm".to_string(),
644 ciphertext: ct_new,
645 nonce: nonce_new,
646 },
647 display_name: Some("New Key".to_string()),
648 created_at: 3000, last_used: None,
650 is_default: false,
651 database_sigkeys: HashMap::new(),
652 };
653
654 let manager = UserKeyManager::new(
656 password,
657 &salt,
658 vec![user_key_new, user_key_old, user_key_mid],
659 )
660 .unwrap();
661
662 let key_ids = manager.list_key_ids();
664 assert_eq!(key_ids.len(), 3);
665 assert_eq!(key_ids[0], pub_old); assert_eq!(key_ids[1], pub_mid); assert_eq!(key_ids[2], pub_new); }
669
670 #[test]
671 #[cfg_attr(miri, ignore)] fn test_key_manager_get_metadata() {
673 let password = "test_password";
674 let (_, salt) = hash_password(password).unwrap();
675 let encryption_key = derive_encryption_key(password, &salt).unwrap();
676
677 let (key1, pub1) = generate_keypair();
678 let user_key1 = create_test_user_key(&key1, &encryption_key);
679
680 let manager = UserKeyManager::new(password, &salt, vec![user_key1]).unwrap();
681
682 let metadata = manager.get_key_metadata(&pub1).unwrap();
683 assert_eq!(metadata.key_id, pub1);
684 assert_eq!(metadata.display_name, Some("Test key".to_string()));
685 }
686
687 #[test]
688 #[cfg_attr(miri, ignore)] fn test_key_manager_wrong_password() {
690 let correct_password = "correct_password";
691 let wrong_password = "wrong_password";
692 let (_, salt) = hash_password(correct_password).unwrap();
693 let encryption_key = derive_encryption_key(correct_password, &salt).unwrap();
694
695 let (key1, _) = generate_keypair();
697 let user_key1 = create_test_user_key(&key1, &encryption_key);
698
699 let result = UserKeyManager::new(wrong_password, &salt, vec![user_key1]);
701 assert!(result.is_err());
702
703 if let Err(err) = result {
705 assert!(matches!(
706 err,
707 Error::User(UserError::DecryptionFailed { .. })
708 ));
709 }
710 }
711
712 #[test]
713 #[cfg_attr(miri, ignore)] fn test_key_manager_rejects_unknown_encryption_algorithm() {
715 let password = "test_password";
716 let (_, salt) = hash_password(password).unwrap();
717 let encryption_key = derive_encryption_key(password, &salt).unwrap();
718
719 let (key1, _) = generate_keypair();
720 let mut user_key = create_test_user_key(&key1, &encryption_key);
721
722 if let KeyStorage::Encrypted {
724 ref mut algorithm, ..
725 } = user_key.storage
726 {
727 *algorithm = "aes-128-gcm".to_string();
728 }
729
730 let Err(err) = UserKeyManager::new(password, &salt, vec![user_key]) else {
731 panic!("Expected error for unsupported algorithm");
732 };
733 assert!(matches!(
734 err,
735 Error::User(UserError::DecryptionFailed { .. })
736 ));
737 assert!(
738 err.to_string().contains("Unsupported encryption algorithm"),
739 "error message was: {err}"
740 );
741 }
742}