flare_core/common/encryption/
registry.rs1use super::algorithms::NoEncryptor;
6use super::traits::Encryptor;
7use std::collections::HashMap;
8use std::sync::Arc;
9use std::sync::RwLock;
10
11lazy_static::lazy_static! {
12 static ref ENCRYPTION_REGISTRY: EncryptionRegistry = {
14 let registry = EncryptionRegistry::new();
15 registry.register_defaults();
17 registry
18 };
19}
20
21pub struct EncryptionRegistry {
25 encryptors: Arc<RwLock<HashMap<String, Arc<dyn Encryptor>>>>,
26}
27
28impl Default for EncryptionRegistry {
29 fn default() -> Self {
30 Self {
31 encryptors: Arc::new(RwLock::new(HashMap::new())),
32 }
33 }
34}
35
36impl EncryptionRegistry {
37 pub fn new() -> Self {
39 Self::default()
40 }
41
42 pub fn register_defaults(&self) {
44 self.register("none", Arc::new(NoEncryptor));
45 }
47
48 pub fn register(&self, name: &str, encryptor: Arc<dyn Encryptor>) {
67 if let Ok(mut encryptors) = self.encryptors.write() {
68 encryptors.insert(name.to_string(), encryptor);
69 }
70 }
71
72 pub fn find(&self, name: &str) -> Option<Arc<dyn Encryptor>> {
80 if let Ok(encryptors) = self.encryptors.read() {
81 encryptors.get(name).cloned()
82 } else {
83 None
84 }
85 }
86
87 pub fn is_registered(&self, name: &str) -> bool {
95 if let Ok(encryptors) = self.encryptors.read() {
96 encryptors.contains_key(name)
97 } else {
98 false
99 }
100 }
101
102 pub fn list_registered(&self) -> Vec<String> {
107 if let Ok(encryptors) = self.encryptors.read() {
108 encryptors.keys().cloned().collect()
109 } else {
110 Vec::new()
111 }
112 }
113}
114
115impl EncryptionRegistry {
117 pub fn global() -> &'static EncryptionRegistry {
119 &ENCRYPTION_REGISTRY
120 }
121}
122
123pub struct EncryptionUtil;
127
128impl EncryptionUtil {
129 pub fn find(name: &str) -> Option<Arc<dyn Encryptor>> {
149 EncryptionRegistry::global().find(name)
150 }
151
152 pub fn is_registered(name: &str) -> bool {
160 EncryptionRegistry::global().is_registered(name)
161 }
162
163 pub fn register_custom(encryptor: Arc<dyn Encryptor>) {
180 let name = encryptor.name();
181 if EncryptionUtil::is_registered(name) {
183 tracing::warn!(
184 "Encryptor '{}' is already registered. Skipping registration to avoid key mismatch.",
185 name
186 );
187 return;
188 }
189 EncryptionRegistry::global().register(name, encryptor);
190 tracing::debug!("Registered encryptor: {}", name);
191 }
192
193 pub fn list_registered() -> Vec<String> {
198 EncryptionRegistry::global().list_registered()
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_encryption_registry() {
208 let registry = EncryptionRegistry::new();
209 registry.register_defaults();
210
211 assert!(registry.find("none").is_some());
212 assert!(registry.find("unknown").is_none());
213 }
214
215 #[test]
216 fn test_no_encryptor() {
217 let encryptor = NoEncryptor;
218 let data = b"hello world";
219 let encrypted = encryptor.encrypt(data).unwrap();
220 let decrypted = encryptor.decrypt(&encrypted).unwrap();
221 assert_eq!(data, decrypted.as_slice());
222 }
223
224 #[test]
225 #[cfg(feature = "encryption-aes-gcm")]
226 fn test_aes256gcm_encryptor() {
227 use crate::common::encryption::Aes256GcmEncryptor;
228
229 let key = b"01234567890123456789012345678901"; let encryptor = Aes256GcmEncryptor::new(key).unwrap();
232
233 let plaintext = b"Hello, World! This is a test message for AES-256-GCM encryption.";
235
236 let ciphertext = encryptor.encrypt(plaintext).unwrap();
238
239 assert!(ciphertext.len() >= plaintext.len() + 12 + 16); let decrypted = encryptor.decrypt(&ciphertext).unwrap();
245 assert_eq!(plaintext, decrypted.as_slice());
246
247 let ciphertext2 = encryptor.encrypt(plaintext).unwrap();
249 assert_ne!(ciphertext, ciphertext2); let decrypted2 = encryptor.decrypt(&ciphertext2).unwrap();
253 assert_eq!(plaintext, decrypted2.as_slice());
254 }
255
256 #[test]
257 #[cfg(feature = "encryption-aes-gcm")]
258 fn test_aes256gcm_from_password() {
259 use crate::common::encryption::Aes256GcmEncryptor;
260
261 let password = b"my_secret_password";
263 let salt = b"some_salt";
264 let encryptor = Aes256GcmEncryptor::from_password(password, Some(salt)).unwrap();
265
266 let plaintext = b"Test message";
267 let ciphertext = encryptor.encrypt(plaintext).unwrap();
268 let decrypted = encryptor.decrypt(&ciphertext).unwrap();
269 assert_eq!(plaintext, decrypted.as_slice());
270 }
271
272 #[test]
273 #[cfg(feature = "encryption-aes-gcm")]
274 fn test_aes256gcm_invalid_key_length() {
275 use crate::common::encryption::Aes256GcmEncryptor;
276
277 let short_key = b"short"; assert!(Aes256GcmEncryptor::new(short_key).is_err());
280
281 let long_key = b"0123456789012345678901234567890123456789"; assert!(Aes256GcmEncryptor::new(long_key).is_err());
283 }
284
285 #[test]
286 #[cfg(feature = "encryption-aes-gcm")]
287 fn test_aes256gcm_invalid_ciphertext() {
288 use crate::common::encryption::Aes256GcmEncryptor;
289
290 let key = b"01234567890123456789012345678901";
291 let encryptor = Aes256GcmEncryptor::new(key).unwrap();
292
293 let short_data = b"short";
295 assert!(encryptor.decrypt(short_data).is_err());
296
297 let invalid_data = vec![0u8; 20]; assert!(encryptor.decrypt(&invalid_data).is_err());
300 }
301
302 #[test]
303 #[cfg(not(feature = "encryption-aes-gcm"))]
304 fn test_aes256gcm_constructor_reports_disabled_feature() {
305 use crate::common::encryption::Aes256GcmEncryptor;
306 use crate::common::error::ErrorCode;
307
308 match Aes256GcmEncryptor::new(b"01234567890123456789012345678901") {
309 Ok(_) => panic!("AES-GCM should report disabled feature"),
310 Err(err) => assert_eq!(err.code(), Some(ErrorCode::OperationNotSupported)),
311 }
312 }
313}