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 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
87
88 let key = Key::<Aes256Gcm>::from_slice(key_data);
89 let cipher = Aes256Gcm::new(key);
90
91 let mut nonce_bytes = [0u8; 12];
93 OsRng.fill(&mut nonce_bytes);
94 let nonce = Nonce::from_slice(&nonce_bytes);
95
96 let ciphertext = cipher.encrypt(nonce, data)
98 .map_err(|e| SyncError::EncryptionError(format!("AES-256 encryption failed: {}", e)))?;
99
100 let mut result = nonce_bytes.to_vec();
102 result.extend_from_slice(&ciphertext);
103
104 Ok(result)
105 }
106
107 async fn decrypt_aes256(&self, encrypted_data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
109 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
110
111 if encrypted_data.len() < 12 {
112 return Err(SyncError::EncryptionError("Invalid encrypted data length".to_string()));
113 }
114
115 let key = Key::<Aes256Gcm>::from_slice(key_data);
116 let cipher = Aes256Gcm::new(key);
117
118 let nonce = Nonce::from_slice(&encrypted_data[..12]);
120 let ciphertext = &encrypted_data[12..];
121
122 let plaintext = cipher.decrypt(nonce, ciphertext)
124 .map_err(|e| SyncError::EncryptionError(format!("AES-256 decryption failed: {}", e)))?;
125
126 Ok(plaintext)
127 }
128
129 async fn encrypt_aes128(&self, data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
131 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
132
133 let key = Key::<Aes256Gcm>::from_slice(&key_data[..16]);
135 let cipher = Aes256Gcm::new(key);
136
137 let mut nonce_bytes = [0u8; 12];
138 OsRng.fill(&mut nonce_bytes);
139 let nonce = Nonce::from_slice(&nonce_bytes);
140
141 let ciphertext = cipher.encrypt(nonce, data)
142 .map_err(|e| SyncError::EncryptionError(format!("AES-128 encryption failed: {}", e)))?;
143
144 let mut result = nonce_bytes.to_vec();
145 result.extend_from_slice(&ciphertext);
146
147 Ok(result)
148 }
149
150 async fn decrypt_aes128(&self, encrypted_data: &[u8], key_data: &[u8]) -> Result<Vec<u8>, SyncError> {
152 use aes_gcm::{Aes256Gcm, Key, Nonce, aead::{Aead, KeyInit}};
153
154 if encrypted_data.len() < 12 {
155 return Err(SyncError::EncryptionError("Invalid encrypted data length".to_string()));
156 }
157
158 let key = Key::<Aes256Gcm>::from_slice(&key_data[..16]);
159 let cipher = Aes256Gcm::new(key);
160
161 let nonce = Nonce::from_slice(&encrypted_data[..12]);
162 let ciphertext = &encrypted_data[12..];
163
164 let plaintext = cipher.decrypt(nonce, ciphertext)
165 .map_err(|e| SyncError::EncryptionError(format!("AES-128 decryption failed: {}", e)))?;
166
167 Ok(plaintext)
168 }
169
170}
171
172pub struct KeyManager {
174 key_store: RwLock<HashMap<String, EncryptionKey>>,
175}
176
177impl KeyManager {
178 pub fn new() -> Self {
180 Self {
181 key_store: RwLock::new(HashMap::new()),
182 }
183 }
184
185 pub async fn generate_key(&self, algorithm: EncryptionAlgorithm) -> Result<EncryptionKey, SyncError> {
187 let key_id = self.generate_key_id();
188 let key_data = match algorithm {
189 EncryptionAlgorithm::Aes256 => self.generate_aes256_key().await?,
190 EncryptionAlgorithm::Aes128 => self.generate_aes128_key().await?,
191 };
192
193 let key = EncryptionKey {
194 id: key_id.clone(),
195 algorithm,
196 key_data,
197 created_at: Utc::now(),
198 expires_at: None,
199 version: 1,
200 };
201
202 let mut store = self.key_store.write().await;
204 store.insert(key_id, key.clone());
205
206 Ok(key)
207 }
208
209
210 pub async fn rotate_key(&self, old_key: &EncryptionKey) -> Result<EncryptionKey, SyncError> {
212 let new_key = self.generate_key(old_key.algorithm.clone()).await?;
213
214 let mut store = self.key_store.write().await;
216 if let Some(existing_key) = store.get_mut(&old_key.id) {
217 existing_key.expires_at = Some(Utc::now());
218 }
219
220 Ok(new_key)
221 }
222
223 pub async fn derive_key_from_password(&self, password: &str, salt: &[u8]) -> Result<Vec<u8>, SyncError> {
225 use sha2::{Sha256, Digest};
226
227 let mut hasher = Sha256::new();
228 hasher.update(password.as_bytes());
229 hasher.update(salt);
230 let derived_key = hasher.finalize().to_vec();
231
232 Ok(derived_key)
233 }
234
235 async fn generate_aes256_key(&self) -> Result<Vec<u8>, SyncError> {
237 let mut key = [0u8; 32];
238 OsRng.fill(&mut key);
239 Ok(key.to_vec())
240 }
241
242 async fn generate_aes128_key(&self) -> Result<Vec<u8>, SyncError> {
244 let mut key = [0u8; 16];
245 OsRng.fill(&mut key);
246 Ok(key.to_vec())
247 }
248
249
250 fn generate_key_id(&self) -> String {
252 let mut rng = OsRng;
253 let random_bytes: [u8; 16] = rng.r#gen();
254 format!("key_{}", general_purpose::STANDARD.encode(random_bytes))
255 }
256
257 pub async fn get_key(&self, key_id: &str) -> Option<EncryptionKey> {
259 let store = self.key_store.read().await;
260 store.get(key_id).cloned()
261 }
262
263 pub async fn revoke_key(&self, key_id: &str) -> Result<(), SyncError> {
265 let mut store = self.key_store.write().await;
266 if let Some(key) = store.get_mut(key_id) {
267 key.expires_at = Some(Utc::now());
268 Ok(())
269 } else {
270 Err(SyncError::EncryptionError("Key not found".to_string()))
271 }
272 }
273
274 pub async fn list_keys(&self) -> Vec<EncryptionKey> {
276 let store = self.key_store.read().await;
277 store.values().cloned().collect()
278 }
279
280 pub async fn cleanup_expired_keys(&self) -> usize {
282 let mut store = self.key_store.write().await;
283 let now = Utc::now();
284 let expired_keys: Vec<String> = store
285 .iter()
286 .filter(|(_, key)| key.expires_at.map_or(false, |expires| expires < now))
287 .map(|(id, _)| id.clone())
288 .collect();
289
290 for key_id in &expired_keys {
291 store.remove(key_id);
292 }
293
294 expired_keys.len()
295 }
296}
297
298#[cfg(test)]
299mod tests {
300 use super::*;
301
302 #[tokio::test]
303 async fn test_aes256_encryption_decryption() {
304 let key_manager = KeyManager::new();
305 let encryption_manager = EncryptionManager::new(EncryptionAlgorithm::Aes256);
306
307 let plaintext = b"Hello, World! This is a test message.";
308 let key = key_manager.generate_key(EncryptionAlgorithm::Aes256).await.unwrap();
309
310 let encrypted = encryption_manager.encrypt(plaintext, &key).await.unwrap();
312 assert_ne!(encrypted, plaintext);
313
314 let decrypted = encryption_manager.decrypt(&encrypted, &key).await.unwrap();
316 assert_eq!(decrypted, plaintext);
317 }
318
319 #[tokio::test]
320 async fn test_key_rotation() {
321 let key_manager = KeyManager::new();
322 let encryption_manager = EncryptionManager::new(EncryptionAlgorithm::Aes256);
323
324 let plaintext = b"Test data for key rotation";
325
326 let key1 = key_manager.generate_key(EncryptionAlgorithm::Aes256).await.unwrap();
328 let encrypted1 = encryption_manager.encrypt(plaintext, &key1).await.unwrap();
329
330 let key2 = key_manager.rotate_key(&key1).await.unwrap();
332 let encrypted2 = encryption_manager.encrypt(plaintext, &key2).await.unwrap();
333
334 let decrypted1 = encryption_manager.decrypt(&encrypted1, &key1).await.unwrap();
336 let decrypted2 = encryption_manager.decrypt(&encrypted2, &key2).await.unwrap();
337
338 assert_eq!(decrypted1, plaintext);
339 assert_eq!(decrypted2, plaintext);
340 assert_ne!(encrypted1, encrypted2);
341 }
342
343 #[tokio::test]
344 async fn test_password_derivation() {
345 let key_manager = KeyManager::new();
346 let password = "test_password_123";
347 let salt = b"test_salt";
348
349 let derived_key = key_manager.derive_key_from_password(password, salt).await.unwrap();
350 assert!(!derived_key.is_empty());
351
352 let derived_key2 = key_manager.derive_key_from_password(password, salt).await.unwrap();
354 assert_eq!(derived_key, derived_key2);
355 }
356}