leptos_sync_core/security/
encryption.rs1use crate::SyncError;
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use tokio::sync::RwLock;
7use chrono::{DateTime, Utc};
8use rand::{Rng, rngs::OsRng};
9use base64::{Engine as _, engine::general_purpose};
10
11#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub enum EncryptionAlgorithm {
14 Aes256,
15 Aes128,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
20pub struct EncryptionKey {
21 pub id: String,
22 pub algorithm: EncryptionAlgorithm,
23 pub key_data: Vec<u8>,
24 pub created_at: DateTime<Utc>,
25 pub expires_at: Option<DateTime<Utc>>,
26 pub version: u32,
27}
28
29pub struct EncryptionManager {
31 algorithm: EncryptionAlgorithm,
32}
33
34impl EncryptionManager {
35 pub fn new(algorithm: EncryptionAlgorithm) -> Self {
37 Self { algorithm }
38 }
39
40 pub async fn encrypt(&self, data: &[u8], key: &EncryptionKey) -> Result<Vec<u8>, SyncError> {
42 if key.algorithm != self.algorithm {
43 return Err(SyncError::EncryptionError(format!(
44 "Key algorithm {:?} does not match manager algorithm {:?}",
45 key.algorithm, self.algorithm
46 )));
47 }
48
49 if let Some(expires_at) = key.expires_at {
51 if Utc::now() > expires_at {
52 return Err(SyncError::EncryptionError("Key has expired".to_string()));
53 }
54 }
55
56 match self.algorithm {
57 EncryptionAlgorithm::Aes256 => self.encrypt_aes256(data, &key.key_data).await,
58 EncryptionAlgorithm::Aes128 => self.encrypt_aes128(data, &key.key_data).await,
59 }
60 }
61
62 pub async fn decrypt(&self, encrypted_data: &[u8], key: &EncryptionKey) -> Result<Vec<u8>, SyncError> {
64 if key.algorithm != self.algorithm {
65 return Err(SyncError::EncryptionError(format!(
66 "Key algorithm {:?} does not match manager algorithm {:?}",
67 key.algorithm, self.algorithm
68 )));
69 }
70
71 if let Some(expires_at) = key.expires_at {
73 if Utc::now() > expires_at {
74 return Err(SyncError::EncryptionError("Key has expired".to_string()));
75 }
76 }
77
78 match self.algorithm {
79 EncryptionAlgorithm::Aes256 => self.decrypt_aes256(encrypted_data, &key.key_data).await,
80 EncryptionAlgorithm::Aes128 => self.decrypt_aes128(encrypted_data, &key.key_data).await,
81 }
82 }
83
84 async fn encrypt_aes256(&self, data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
86 #[cfg(feature = "encryption")]
87 {
88 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
89
90 let key = Key::<Aes256Gcm>::from_slice(key_data);
91 let cipher = Aes256Gcm::new(key);
92
93 let mut nonce_bytes = [0u8; 12];
95 OsRng.fill(&mut nonce_bytes);
96 let nonce = Nonce::from_slice(&nonce_bytes);
97
98 let ciphertext = cipher.encrypt(nonce, data)
100 .map_err(|e| SyncError::EncryptionError(format!("AES-256 encryption failed: {}", e)))?;
101
102 let mut result = nonce_bytes.to_vec();
104 result.extend_from_slice(&ciphertext);
105
106 Ok(result)
107 }
108 #[cfg(not(feature = "encryption"))]
109 {
110 Err(SyncError::EncryptionError("Encryption feature not enabled".to_string()))
111 }
112 }
113
114 async fn decrypt_aes256(&self, encrypted_data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
116 #[cfg(feature = "encryption")]
117 {
118 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
119
120 if encrypted_data.len() < 12 {
121 return Err(SyncError::EncryptionError("Invalid encrypted data length".to_string()));
122 }
123
124 let key = Key::<Aes256Gcm>::from_slice(key_data);
125 let cipher = Aes256Gcm::new(key);
126
127 let nonce = Nonce::from_slice(&encrypted_data[..12]);
129 let ciphertext = &encrypted_data[12..];
130
131 let plaintext = cipher.decrypt(nonce, ciphertext)
133 .map_err(|e| SyncError::EncryptionError(format!("AES-256 decryption failed: {}", e)))?;
134
135 Ok(plaintext)
136 }
137 #[cfg(not(feature = "encryption"))]
138 {
139 Err(SyncError::EncryptionError("Encryption feature not enabled".to_string()))
140 }
141 }
142
143 async fn encrypt_aes128(&self, data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
145 #[cfg(feature = "encryption")]
146 {
147 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
148
149 let key = Key::<Aes256Gcm>::from_slice(&key_data[..16]);
151 let cipher = Aes256Gcm::new(key);
152
153 let mut nonce_bytes = [0u8; 12];
154 OsRng.fill(&mut nonce_bytes);
155 let nonce = Nonce::from_slice(&nonce_bytes);
156
157 let ciphertext = cipher.encrypt(nonce, data)
158 .map_err(|e| SyncError::EncryptionError(format!("AES-128 encryption failed: {}", e)))?;
159
160 let mut result = nonce_bytes.to_vec();
161 result.extend_from_slice(&ciphertext);
162
163 Ok(result)
164 }
165 #[cfg(not(feature = "encryption"))]
166 {
167 Err(SyncError::EncryptionError("Encryption feature not enabled".to_string()))
168 }
169 }
170
171 async fn decrypt_aes128(&self, encrypted_data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
173 #[cfg(feature = "encryption")]
174 {
175 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
176
177 if encrypted_data.len() < 12 {
178 return Err(SyncError::EncryptionError("Invalid encrypted data length".to_string()));
179 }
180
181 let key = Key::<Aes256Gcm>::from_slice(&key_data[..16]);
182 let cipher = Aes256Gcm::new(key);
183
184 let nonce = Nonce::from_slice(&encrypted_data[..12]);
185 let ciphertext = &encrypted_data[12..];
186
187 let plaintext = cipher.decrypt(nonce, ciphertext)
188 .map_err(|e| SyncError::EncryptionError(format!("AES-128 decryption failed: {}", e)))?;
189
190 Ok(plaintext)
191 }
192 #[cfg(not(feature = "encryption"))]
193 {
194 Err(SyncError::EncryptionError("Encryption feature not enabled".to_string()))
195 }
196 }
197
198}
199
200pub struct KeyManager {
202 key_store: RwLock<HashMap<String, EncryptionKey>>,
203}
204
205impl KeyManager {
206 pub fn new() -> Self {
208 Self {
209 key_store: RwLock::new(HashMap::new()),
210 }
211 }
212
213 pub async fn generate_key(&self, algorithm: EncryptionAlgorithm) -> Result<EncryptionKey, SyncError> {
215 let key_id = self.generate_key_id();
216 let key_data = match algorithm {
217 EncryptionAlgorithm::Aes256 => self.generate_aes256_key().await?,
218 EncryptionAlgorithm::Aes128 => self.generate_aes128_key().await?,
219 };
220
221 let key = EncryptionKey {
222 id: key_id.clone(),
223 algorithm,
224 key_data,
225 created_at: Utc::now(),
226 expires_at: None,
227 version: 1,
228 };
229
230 let mut store = self.key_store.write().await;
232 store.insert(key_id, key.clone());
233
234 Ok(key)
235 }
236
237
238 pub async fn rotate_key(&self, old_key: &EncryptionKey) -> Result<EncryptionKey, SyncError> {
240 let new_key = self.generate_key(old_key.algorithm.clone()).await?;
241
242 let mut store = self.key_store.write().await;
244 if let Some(existing_key) = store.get_mut(&old_key.id) {
245 existing_key.expires_at = Some(Utc::now());
246 }
247
248 Ok(new_key)
249 }
250
251 pub async fn derive_key_from_password(&self, password: &str, salt: &[u8]) -> Result<Vec<u8>, SyncError> {
253 use sha2::{Sha256, Digest};
254
255 let mut hasher = Sha256::new();
256 hasher.update(password.as_bytes());
257 hasher.update(salt);
258 let derived_key = hasher.finalize().to_vec();
259
260 Ok(derived_key)
261 }
262
263 async fn generate_aes256_key(&self) -> Result<Vec<u8>, SyncError> {
265 let mut key = [0u8; 32];
266 OsRng.fill(&mut key);
267 Ok(key.to_vec())
268 }
269
270 async fn generate_aes128_key(&self) -> Result<Vec<u8>, SyncError> {
272 let mut key = [0u8; 16];
273 OsRng.fill(&mut key);
274 Ok(key.to_vec())
275 }
276
277
278 fn generate_key_id(&self) -> String {
280 let mut rng = OsRng;
281 let random_bytes: [u8; 16] = rng.r#gen();
282 format!("key_{}", general_purpose::STANDARD.encode(random_bytes))
283 }
284
285 pub async fn get_key(&self, key_id: &str) -> Option<EncryptionKey> {
287 let store = self.key_store.read().await;
288 store.get(key_id).cloned()
289 }
290
291 pub async fn revoke_key(&self, key_id: &str) -> Result<(), SyncError> {
293 let mut store = self.key_store.write().await;
294 if let Some(key) = store.get_mut(key_id) {
295 key.expires_at = Some(Utc::now());
296 Ok(())
297 } else {
298 Err(SyncError::EncryptionError("Key not found".to_string()))
299 }
300 }
301
302 pub async fn list_keys(&self) -> Vec<EncryptionKey> {
304 let store = self.key_store.read().await;
305 store.values().cloned().collect()
306 }
307
308 pub async fn cleanup_expired_keys(&self) -> usize {
310 let mut store = self.key_store.write().await;
311 let now = Utc::now();
312 let expired_keys: Vec<String> = store
313 .iter()
314 .filter(|(_, key)| key.expires_at.map_or(false, |expires| expires < now))
315 .map(|(id, _)| id.clone())
316 .collect();
317
318 for key_id in &expired_keys {
319 store.remove(key_id);
320 }
321
322 expired_keys.len()
323 }
324}
325
326#[cfg(test)]
327mod tests {
328 use super::*;
329
330 #[tokio::test]
331 async fn test_aes256_encryption_decryption() {
332 let key_manager = KeyManager::new();
333 let encryption_manager = EncryptionManager::new(EncryptionAlgorithm::Aes256);
334
335 let plaintext = b"Hello, World! This is a test message.";
336 let key = key_manager.generate_key(EncryptionAlgorithm::Aes256).await.unwrap();
337
338 let encrypted = encryption_manager.encrypt(plaintext, &key).await.unwrap();
340 assert_ne!(encrypted, plaintext);
341
342 let decrypted = encryption_manager.decrypt(&encrypted, &key).await.unwrap();
344 assert_eq!(decrypted, plaintext);
345 }
346
347 #[tokio::test]
348 async fn test_key_rotation() {
349 let key_manager = KeyManager::new();
350 let encryption_manager = EncryptionManager::new(EncryptionAlgorithm::Aes256);
351
352 let plaintext = b"Test data for key rotation";
353
354 let key1 = key_manager.generate_key(EncryptionAlgorithm::Aes256).await.unwrap();
356 let encrypted1 = encryption_manager.encrypt(plaintext, &key1).await.unwrap();
357
358 let key2 = key_manager.rotate_key(&key1).await.unwrap();
360 let encrypted2 = encryption_manager.encrypt(plaintext, &key2).await.unwrap();
361
362 let decrypted1 = encryption_manager.decrypt(&encrypted1, &key1).await.unwrap();
364 let decrypted2 = encryption_manager.decrypt(&encrypted2, &key2).await.unwrap();
365
366 assert_eq!(decrypted1, plaintext);
367 assert_eq!(decrypted2, plaintext);
368 assert_ne!(encrypted1, encrypted2);
369 }
370
371 #[tokio::test]
372 async fn test_password_derivation() {
373 let key_manager = KeyManager::new();
374 let password = "test_password_123";
375 let salt = b"test_salt";
376
377 let derived_key = key_manager.derive_key_from_password(password, salt).await.unwrap();
378 assert!(!derived_key.is_empty());
379
380 let derived_key2 = key_manager.derive_key_from_password(password, salt).await.unwrap();
382 assert_eq!(derived_key, derived_key2);
383 }
384}