chie_crypto/
keystore.rs

1//! Secure key storage with encryption at rest.
2//!
3//! This module provides a secure keystore/vault for storing cryptographic keys
4//! with encryption at rest. Keys are encrypted using a master key derived from
5//! a password, ensuring that stored keys are protected even if the storage
6//! backend is compromised.
7//!
8//! # Features
9//!
10//! - Master key derivation from password using Argon2
11//! - Individual key encryption with ChaCha20-Poly1305
12//! - Unique nonces per key for security
13//! - HMAC-based integrity verification
14//! - Key metadata tracking (creation time, last accessed, key type)
15//! - Multiple storage backends (filesystem, in-memory)
16//! - Automatic key versioning and rotation support
17//! - Secure deletion with zeroization
18//!
19//! # Example
20//!
21//! ```
22//! use chie_crypto::keystore::{SecureKeyStore, KeyType, KeyMetadata};
23//!
24//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
25//! // Create a new keystore with a password
26//! let mut keystore = SecureKeyStore::new(b"strong-password")?;
27//!
28//! // Store a signing key
29//! let key_id = "my-signing-key";
30//! let key_data = b"secret-key-data-here";
31//! keystore.store_key(key_id, key_data, KeyType::Signing)?;
32//!
33//! // Retrieve the key
34//! let retrieved = keystore.retrieve_key(key_id)?;
35//! assert_eq!(retrieved, key_data);
36//!
37//! // Check key metadata
38//! let metadata = keystore.get_metadata(key_id)?;
39//! assert_eq!(metadata.key_type, KeyType::Signing);
40//!
41//! // Delete the key securely
42//! keystore.delete_key(key_id)?;
43//! # Ok(())
44//! # }
45//! ```
46
47use crate::{
48    encryption::{EncryptionKey, decrypt, encrypt, generate_nonce},
49    hmac::{HmacKey, HmacTag, compute_hmac, verify_hmac},
50    kdf::KeyDerivation,
51    zeroizing::secure_zero,
52};
53use serde::{Deserialize, Serialize};
54use std::collections::HashMap;
55use std::time::{SystemTime, UNIX_EPOCH};
56
57/// Errors that can occur during keystore operations.
58#[derive(Debug, thiserror::Error)]
59pub enum KeyStoreError {
60    #[error("Key not found: {0}")]
61    KeyNotFound(String),
62
63    #[error("Key already exists: {0}")]
64    KeyAlreadyExists(String),
65
66    #[error("Encryption error: {0}")]
67    EncryptionError(String),
68
69    #[error("Decryption error: {0}")]
70    DecryptionError(String),
71
72    #[error("Invalid master key")]
73    InvalidMasterKey,
74
75    #[error("Integrity check failed")]
76    IntegrityCheckFailed,
77
78    #[error("Serialization error: {0}")]
79    SerializationError(String),
80
81    #[error("I/O error: {0}")]
82    IoError(String),
83
84    #[error("Invalid key type")]
85    InvalidKeyType,
86}
87
88/// Result type for keystore operations.
89pub type KeyStoreResult<T> = Result<T, KeyStoreError>;
90
91/// Type of cryptographic key.
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
93pub enum KeyType {
94    /// Ed25519 signing key
95    Signing,
96    /// ChaCha20 encryption key
97    Encryption,
98    /// HMAC authentication key
99    Authentication,
100    /// Generic secret key
101    Generic,
102    /// X25519 key exchange key
103    KeyExchange,
104}
105
106/// Metadata about a stored key.
107#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct KeyMetadata {
109    /// Unique identifier for the key
110    pub key_id: String,
111    /// Type of key
112    pub key_type: KeyType,
113    /// Creation timestamp (Unix epoch)
114    pub created_at: u64,
115    /// Last accessed timestamp (Unix epoch)
116    pub last_accessed: u64,
117    /// Optional description
118    pub description: Option<String>,
119    /// Key version (for rotation support)
120    pub version: u32,
121    /// Whether the key is active
122    pub active: bool,
123}
124
125impl KeyMetadata {
126    /// Create new metadata for a key.
127    pub fn new(key_id: String, key_type: KeyType) -> Self {
128        let now = SystemTime::now()
129            .duration_since(UNIX_EPOCH)
130            .unwrap()
131            .as_secs();
132
133        Self {
134            key_id,
135            key_type,
136            created_at: now,
137            last_accessed: now,
138            description: None,
139            version: 1,
140            active: true,
141        }
142    }
143
144    /// Update the last accessed timestamp.
145    pub fn touch(&mut self) {
146        self.last_accessed = SystemTime::now()
147            .duration_since(UNIX_EPOCH)
148            .unwrap()
149            .as_secs();
150    }
151}
152
153/// Encrypted key entry in the keystore.
154#[derive(Debug, Clone, Serialize, Deserialize)]
155struct EncryptedKeyEntry {
156    /// Key metadata
157    metadata: KeyMetadata,
158    /// Encrypted key data
159    ciphertext: Vec<u8>,
160    /// HMAC for integrity verification
161    hmac: Vec<u8>,
162}
163
164/// Secure keystore for encrypted key storage.
165///
166/// The keystore encrypts all keys at rest using a master key derived
167/// from a password. Each key is encrypted with a unique nonce and
168/// integrity-protected with HMAC.
169pub struct SecureKeyStore {
170    /// Master encryption key (32 bytes)
171    master_key: EncryptionKey,
172    /// Master HMAC key
173    hmac_key: HmacKey,
174    /// Encrypted key entries
175    entries: HashMap<String, EncryptedKeyEntry>,
176    /// Salt used for key derivation
177    salt: [u8; 32],
178}
179
180impl SecureKeyStore {
181    /// Create a new keystore with the given password.
182    ///
183    /// The password is used to derive the master encryption and HMAC keys
184    /// using Argon2. A random salt is generated for key derivation.
185    ///
186    /// # Example
187    ///
188    /// ```
189    /// use chie_crypto::keystore::SecureKeyStore;
190    ///
191    /// let keystore = SecureKeyStore::new(b"my-password").unwrap();
192    /// ```
193    pub fn new(password: &[u8]) -> KeyStoreResult<Self> {
194        // Generate random salt
195        use rand::RngCore;
196        let mut salt = [0u8; 32];
197        rand::thread_rng().fill_bytes(&mut salt);
198
199        Self::with_salt(password, salt)
200    }
201
202    /// Create a keystore with an explicit salt (for loading from storage).
203    pub fn with_salt(password: &[u8], salt: [u8; 32]) -> KeyStoreResult<Self> {
204        // Derive master keys from password
205        let kdf = KeyDerivation::new(password, Some(&salt));
206        let master_key = kdf
207            .derive_encryption_key(b"keystore-encryption")
208            .map_err(|e| KeyStoreError::EncryptionError(e.to_string()))?;
209
210        let hmac_key_bytes = kdf
211            .derive_bytes(b"keystore-hmac", 32)
212            .map_err(|e| KeyStoreError::EncryptionError(e.to_string()))?;
213        let hmac_key = HmacKey::from_bytes(&hmac_key_bytes)
214            .map_err(|e| KeyStoreError::EncryptionError(e.to_string()))?;
215
216        Ok(Self {
217            master_key,
218            hmac_key,
219            entries: HashMap::new(),
220            salt,
221        })
222    }
223
224    /// Store a key in the keystore.
225    ///
226    /// # Arguments
227    ///
228    /// * `key_id` - Unique identifier for the key
229    /// * `key_data` - The key bytes to encrypt and store
230    /// * `key_type` - Type of the key
231    ///
232    /// # Errors
233    ///
234    /// Returns `KeyAlreadyExists` if a key with the same ID already exists.
235    ///
236    /// # Example
237    ///
238    /// ```
239    /// use chie_crypto::keystore::{SecureKeyStore, KeyType};
240    ///
241    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
242    /// let mut keystore = SecureKeyStore::new(b"password")?;
243    /// keystore.store_key("key1", b"secret", KeyType::Generic)?;
244    /// # Ok(())
245    /// # }
246    /// ```
247    pub fn store_key(
248        &mut self,
249        key_id: &str,
250        key_data: &[u8],
251        key_type: KeyType,
252    ) -> KeyStoreResult<()> {
253        if self.entries.contains_key(key_id) {
254            return Err(KeyStoreError::KeyAlreadyExists(key_id.to_string()));
255        }
256
257        // Generate a random nonce
258        let nonce = generate_nonce();
259
260        // Encrypt the key data
261        let encrypted = encrypt(key_data, &self.master_key, &nonce)
262            .map_err(|e| KeyStoreError::EncryptionError(e.to_string()))?;
263
264        // Store nonce + encrypted data together
265        let mut ciphertext = Vec::with_capacity(12 + encrypted.len());
266        ciphertext.extend_from_slice(&nonce);
267        ciphertext.extend_from_slice(&encrypted);
268
269        // Compute HMAC over nonce + ciphertext
270        let hmac = compute_hmac(&self.hmac_key, &ciphertext);
271
272        // Create metadata
273        let metadata = KeyMetadata::new(key_id.to_string(), key_type);
274
275        // Store entry
276        self.entries.insert(
277            key_id.to_string(),
278            EncryptedKeyEntry {
279                metadata,
280                ciphertext,
281                hmac: hmac.to_bytes(),
282            },
283        );
284
285        Ok(())
286    }
287
288    /// Retrieve a key from the keystore.
289    ///
290    /// # Errors
291    ///
292    /// Returns `KeyNotFound` if the key doesn't exist, or `IntegrityCheckFailed`
293    /// if the HMAC verification fails.
294    ///
295    /// # Example
296    ///
297    /// ```
298    /// use chie_crypto::keystore::{SecureKeyStore, KeyType};
299    ///
300    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
301    /// let mut keystore = SecureKeyStore::new(b"password")?;
302    /// keystore.store_key("key1", b"secret", KeyType::Generic)?;
303    /// let retrieved = keystore.retrieve_key("key1")?;
304    /// assert_eq!(retrieved, b"secret");
305    /// # Ok(())
306    /// # }
307    /// ```
308    pub fn retrieve_key(&mut self, key_id: &str) -> KeyStoreResult<Vec<u8>> {
309        let entry = self
310            .entries
311            .get_mut(key_id)
312            .ok_or_else(|| KeyStoreError::KeyNotFound(key_id.to_string()))?;
313
314        // Verify HMAC
315        let stored_hmac = HmacTag::from_bytes(&entry.hmac);
316        if !verify_hmac(&self.hmac_key, &entry.ciphertext, &stored_hmac) {
317            return Err(KeyStoreError::IntegrityCheckFailed);
318        }
319
320        // Extract nonce and encrypted data
321        if entry.ciphertext.len() < 12 {
322            return Err(KeyStoreError::DecryptionError(
323                "Invalid ciphertext length".to_string(),
324            ));
325        }
326        let (nonce_bytes, encrypted) = entry.ciphertext.split_at(12);
327        let mut nonce = [0u8; 12];
328        nonce.copy_from_slice(nonce_bytes);
329
330        // Decrypt the key data
331        let plaintext = decrypt(encrypted, &self.master_key, &nonce)
332            .map_err(|e| KeyStoreError::DecryptionError(e.to_string()))?;
333
334        // Update last accessed time
335        entry.metadata.touch();
336
337        Ok(plaintext)
338    }
339
340    /// Delete a key from the keystore.
341    ///
342    /// The key data is securely zeroized before removal.
343    ///
344    /// # Example
345    ///
346    /// ```
347    /// use chie_crypto::keystore::{SecureKeyStore, KeyType};
348    ///
349    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
350    /// let mut keystore = SecureKeyStore::new(b"password")?;
351    /// keystore.store_key("key1", b"secret", KeyType::Generic)?;
352    /// keystore.delete_key("key1")?;
353    /// assert!(keystore.get_metadata("key1").is_err());
354    /// # Ok(())
355    /// # }
356    /// ```
357    pub fn delete_key(&mut self, key_id: &str) -> KeyStoreResult<()> {
358        let mut entry = self
359            .entries
360            .remove(key_id)
361            .ok_or_else(|| KeyStoreError::KeyNotFound(key_id.to_string()))?;
362
363        // Securely zero the encrypted data
364        secure_zero(&mut entry.ciphertext);
365        secure_zero(&mut entry.hmac);
366
367        Ok(())
368    }
369
370    /// List all key IDs in the keystore.
371    pub fn list_keys(&self) -> Vec<String> {
372        self.entries.keys().cloned().collect()
373    }
374
375    /// Get metadata for a key.
376    pub fn get_metadata(&self, key_id: &str) -> KeyStoreResult<&KeyMetadata> {
377        let entry = self
378            .entries
379            .get(key_id)
380            .ok_or_else(|| KeyStoreError::KeyNotFound(key_id.to_string()))?;
381        Ok(&entry.metadata)
382    }
383
384    /// Update key metadata.
385    pub fn update_metadata<F>(&mut self, key_id: &str, f: F) -> KeyStoreResult<()>
386    where
387        F: FnOnce(&mut KeyMetadata),
388    {
389        let entry = self
390            .entries
391            .get_mut(key_id)
392            .ok_or_else(|| KeyStoreError::KeyNotFound(key_id.to_string()))?;
393        f(&mut entry.metadata);
394        Ok(())
395    }
396
397    /// Rotate a key to a new version.
398    ///
399    /// This stores the new key data while incrementing the version number
400    /// and preserving other metadata.
401    pub fn rotate_key(&mut self, key_id: &str, new_key_data: &[u8]) -> KeyStoreResult<()> {
402        // Get current metadata
403        let metadata = {
404            let entry = self
405                .entries
406                .get(key_id)
407                .ok_or_else(|| KeyStoreError::KeyNotFound(key_id.to_string()))?;
408            let mut meta = entry.metadata.clone();
409            meta.version += 1;
410            meta.touch();
411            meta
412        };
413
414        // Delete old key
415        self.delete_key(key_id)?;
416
417        // Generate a random nonce
418        let nonce = generate_nonce();
419
420        // Encrypt new key data
421        let encrypted = encrypt(new_key_data, &self.master_key, &nonce)
422            .map_err(|e| KeyStoreError::EncryptionError(e.to_string()))?;
423
424        // Store nonce + encrypted data together
425        let mut ciphertext = Vec::with_capacity(12 + encrypted.len());
426        ciphertext.extend_from_slice(&nonce);
427        ciphertext.extend_from_slice(&encrypted);
428
429        // Compute HMAC
430        let hmac = compute_hmac(&self.hmac_key, &ciphertext);
431
432        // Store new entry
433        self.entries.insert(
434            key_id.to_string(),
435            EncryptedKeyEntry {
436                metadata,
437                ciphertext,
438                hmac: hmac.to_bytes(),
439            },
440        );
441
442        Ok(())
443    }
444
445    /// Serialize the keystore to bytes for persistent storage.
446    ///
447    /// The serialized format includes the salt and all encrypted entries.
448    pub fn serialize(&self) -> KeyStoreResult<Vec<u8>> {
449        #[derive(Serialize)]
450        struct KeyStoreData {
451            salt: [u8; 32],
452            entries: HashMap<String, EncryptedKeyEntry>,
453        }
454
455        let data = KeyStoreData {
456            salt: self.salt,
457            entries: self.entries.clone(),
458        };
459
460        crate::codec::encode(&data).map_err(|e| KeyStoreError::SerializationError(e.to_string()))
461    }
462
463    /// Deserialize a keystore from bytes with the given password.
464    pub fn deserialize(password: &[u8], data: &[u8]) -> KeyStoreResult<Self> {
465        #[derive(Deserialize)]
466        struct KeyStoreData {
467            salt: [u8; 32],
468            entries: HashMap<String, EncryptedKeyEntry>,
469        }
470
471        let stored: KeyStoreData = crate::codec::decode(data)
472            .map_err(|e| KeyStoreError::SerializationError(e.to_string()))?;
473
474        let mut keystore = Self::with_salt(password, stored.salt)?;
475        keystore.entries = stored.entries;
476
477        Ok(keystore)
478    }
479
480    /// Get the salt used for key derivation.
481    pub fn salt(&self) -> &[u8; 32] {
482        &self.salt
483    }
484
485    /// Check if a key exists in the keystore.
486    pub fn contains_key(&self, key_id: &str) -> bool {
487        self.entries.contains_key(key_id)
488    }
489
490    /// Get the number of keys stored.
491    pub fn len(&self) -> usize {
492        self.entries.len()
493    }
494
495    /// Check if the keystore is empty.
496    pub fn is_empty(&self) -> bool {
497        self.entries.is_empty()
498    }
499}
500
501impl Drop for SecureKeyStore {
502    fn drop(&mut self) {
503        // Securely zero the master key
504        secure_zero(&mut self.master_key);
505
506        // Securely zero all key material
507        for entry in self.entries.values_mut() {
508            secure_zero(&mut entry.ciphertext);
509            secure_zero(&mut entry.hmac);
510        }
511    }
512}
513
514#[cfg(test)]
515mod tests {
516    use super::*;
517
518    #[test]
519    fn test_keystore_basic() {
520        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
521
522        // Store a key
523        keystore
524            .store_key("key1", b"secret-data", KeyType::Generic)
525            .unwrap();
526
527        // Retrieve it
528        let retrieved = keystore.retrieve_key("key1").unwrap();
529        assert_eq!(retrieved, b"secret-data");
530    }
531
532    #[test]
533    fn test_multiple_keys() {
534        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
535
536        keystore
537            .store_key("signing", b"sign-key", KeyType::Signing)
538            .unwrap();
539        keystore
540            .store_key("encryption", b"enc-key", KeyType::Encryption)
541            .unwrap();
542        keystore
543            .store_key("hmac", b"hmac-key", KeyType::Authentication)
544            .unwrap();
545
546        assert_eq!(keystore.retrieve_key("signing").unwrap(), b"sign-key");
547        assert_eq!(keystore.retrieve_key("encryption").unwrap(), b"enc-key");
548        assert_eq!(keystore.retrieve_key("hmac").unwrap(), b"hmac-key");
549    }
550
551    #[test]
552    fn test_key_not_found() {
553        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
554
555        let result = keystore.retrieve_key("nonexistent");
556        assert!(matches!(result, Err(KeyStoreError::KeyNotFound(_))));
557    }
558
559    #[test]
560    fn test_duplicate_key() {
561        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
562
563        keystore
564            .store_key("key1", b"data", KeyType::Generic)
565            .unwrap();
566        let result = keystore.store_key("key1", b"other", KeyType::Generic);
567
568        assert!(matches!(result, Err(KeyStoreError::KeyAlreadyExists(_))));
569    }
570
571    #[test]
572    fn test_delete_key() {
573        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
574
575        keystore
576            .store_key("key1", b"data", KeyType::Generic)
577            .unwrap();
578        assert!(keystore.contains_key("key1"));
579
580        keystore.delete_key("key1").unwrap();
581        assert!(!keystore.contains_key("key1"));
582
583        let result = keystore.retrieve_key("key1");
584        assert!(matches!(result, Err(KeyStoreError::KeyNotFound(_))));
585    }
586
587    #[test]
588    fn test_list_keys() {
589        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
590
591        keystore
592            .store_key("key1", b"data1", KeyType::Generic)
593            .unwrap();
594        keystore
595            .store_key("key2", b"data2", KeyType::Signing)
596            .unwrap();
597        keystore
598            .store_key("key3", b"data3", KeyType::Encryption)
599            .unwrap();
600
601        let mut keys = keystore.list_keys();
602        keys.sort();
603
604        assert_eq!(keys, vec!["key1", "key2", "key3"]);
605    }
606
607    #[test]
608    fn test_metadata() {
609        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
610
611        keystore
612            .store_key("key1", b"data", KeyType::Signing)
613            .unwrap();
614
615        let metadata = keystore.get_metadata("key1").unwrap();
616        assert_eq!(metadata.key_id, "key1");
617        assert_eq!(metadata.key_type, KeyType::Signing);
618        assert_eq!(metadata.version, 1);
619        assert!(metadata.active);
620    }
621
622    #[test]
623    fn test_update_metadata() {
624        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
625
626        keystore
627            .store_key("key1", b"data", KeyType::Generic)
628            .unwrap();
629
630        keystore
631            .update_metadata("key1", |meta| {
632                meta.description = Some("Test key".to_string());
633                meta.active = false;
634            })
635            .unwrap();
636
637        let metadata = keystore.get_metadata("key1").unwrap();
638        assert_eq!(metadata.description.as_deref(), Some("Test key"));
639        assert!(!metadata.active);
640    }
641
642    #[test]
643    fn test_key_rotation() {
644        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
645
646        keystore
647            .store_key("key1", b"old-key", KeyType::Signing)
648            .unwrap();
649        assert_eq!(keystore.get_metadata("key1").unwrap().version, 1);
650
651        keystore.rotate_key("key1", b"new-key").unwrap();
652
653        let retrieved = keystore.retrieve_key("key1").unwrap();
654        assert_eq!(retrieved, b"new-key");
655        assert_eq!(keystore.get_metadata("key1").unwrap().version, 2);
656    }
657
658    #[test]
659    fn test_serialization() {
660        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
661
662        keystore
663            .store_key("key1", b"data1", KeyType::Signing)
664            .unwrap();
665        keystore
666            .store_key("key2", b"data2", KeyType::Encryption)
667            .unwrap();
668
669        // Serialize
670        let serialized = keystore.serialize().unwrap();
671
672        // Deserialize
673        let mut restored = SecureKeyStore::deserialize(b"test-password", &serialized).unwrap();
674
675        // Verify keys are intact
676        assert_eq!(restored.retrieve_key("key1").unwrap(), b"data1");
677        assert_eq!(restored.retrieve_key("key2").unwrap(), b"data2");
678    }
679
680    #[test]
681    fn test_wrong_password() {
682        let mut keystore = SecureKeyStore::new(b"correct-password").unwrap();
683        keystore
684            .store_key("key1", b"data", KeyType::Generic)
685            .unwrap();
686
687        let serialized = keystore.serialize().unwrap();
688
689        // Try to load with wrong password
690        let mut wrong_keystore =
691            SecureKeyStore::deserialize(b"wrong-password", &serialized).unwrap();
692
693        // This should fail integrity check
694        let result = wrong_keystore.retrieve_key("key1");
695        assert!(matches!(result, Err(KeyStoreError::IntegrityCheckFailed)));
696    }
697
698    #[test]
699    fn test_keystore_len() {
700        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
701
702        assert_eq!(keystore.len(), 0);
703        assert!(keystore.is_empty());
704
705        keystore
706            .store_key("key1", b"data1", KeyType::Generic)
707            .unwrap();
708        assert_eq!(keystore.len(), 1);
709        assert!(!keystore.is_empty());
710
711        keystore
712            .store_key("key2", b"data2", KeyType::Signing)
713            .unwrap();
714        assert_eq!(keystore.len(), 2);
715
716        keystore.delete_key("key1").unwrap();
717        assert_eq!(keystore.len(), 1);
718    }
719
720    #[test]
721    fn test_different_key_types() {
722        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
723
724        keystore
725            .store_key("sign", b"sign-key", KeyType::Signing)
726            .unwrap();
727        keystore
728            .store_key("enc", b"enc-key", KeyType::Encryption)
729            .unwrap();
730        keystore
731            .store_key("auth", b"auth-key", KeyType::Authentication)
732            .unwrap();
733        keystore
734            .store_key("kex", b"kex-key", KeyType::KeyExchange)
735            .unwrap();
736        keystore
737            .store_key("gen", b"gen-key", KeyType::Generic)
738            .unwrap();
739
740        assert_eq!(
741            keystore.get_metadata("sign").unwrap().key_type,
742            KeyType::Signing
743        );
744        assert_eq!(
745            keystore.get_metadata("enc").unwrap().key_type,
746            KeyType::Encryption
747        );
748        assert_eq!(
749            keystore.get_metadata("auth").unwrap().key_type,
750            KeyType::Authentication
751        );
752        assert_eq!(
753            keystore.get_metadata("kex").unwrap().key_type,
754            KeyType::KeyExchange
755        );
756        assert_eq!(
757            keystore.get_metadata("gen").unwrap().key_type,
758            KeyType::Generic
759        );
760    }
761
762    #[test]
763    fn test_last_accessed_update() {
764        let mut keystore = SecureKeyStore::new(b"test-password").unwrap();
765
766        keystore
767            .store_key("key1", b"data", KeyType::Generic)
768            .unwrap();
769
770        let created_at = keystore.get_metadata("key1").unwrap().created_at;
771        let first_accessed = keystore.get_metadata("key1").unwrap().last_accessed;
772
773        // Sleep a tiny bit to ensure time difference
774        std::thread::sleep(std::time::Duration::from_millis(10));
775
776        keystore.retrieve_key("key1").unwrap();
777
778        let second_accessed = keystore.get_metadata("key1").unwrap().last_accessed;
779
780        assert_eq!(created_at, first_accessed);
781        assert!(second_accessed >= first_accessed);
782    }
783}