leptos_sync_core/security/
mod.rs1use serde::{Deserialize, Serialize};
4use thiserror::Error;
5
6pub mod encryption;
7pub mod compression;
8pub mod hashing;
9pub mod authentication;
10pub mod gdpr;
11
12#[derive(Error, Debug)]
13pub enum SecurityError {
14 #[error("Encryption error: {0}")]
15 Encryption(String),
16 #[error("Decryption error: {0}")]
17 Decryption(String),
18 #[error("Compression error: {0}")]
19 Compression(String),
20 #[error("Decompression error: {0}")]
21 Decompression(String),
22 #[error("Hash error: {0}")]
23 Hash(String),
24 #[error("Invalid key: {0}")]
25 InvalidKey(String),
26 #[error("Invalid algorithm: {0}")]
27 InvalidAlgorithm(String),
28 #[error("Invalid data: {0}")]
29 InvalidData(String),
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
34pub struct SecurityConfig {
35 pub encryption_enabled: bool,
36 pub compression_enabled: bool,
37 pub encryption_algorithm: EncryptionAlgorithm,
38 pub compression_algorithm: CompressionAlgorithm,
39 pub key_derivation: KeyDerivationConfig,
40 pub integrity_checking: bool,
41}
42
43impl Default for SecurityConfig {
44 fn default() -> Self {
45 Self {
46 encryption_enabled: true,
47 compression_enabled: true,
48 encryption_algorithm: EncryptionAlgorithm::Aes256,
49 compression_algorithm: CompressionAlgorithm::Lz4,
50 key_derivation: KeyDerivationConfig::default(),
51 integrity_checking: true,
52 }
53 }
54}
55
56pub use encryption::EncryptionAlgorithm;
58
59pub use compression::CompressionAlgorithm;
61
62pub use authentication::{AuthenticationManager, AuthProvider, UserSession, User, AuthConfig};
64
65pub use gdpr::{GDPRCompliance, DataSubject, DataProcessingPurpose, PersonalDataRecord, AuditLogEntry};
67
68#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct KeyDerivationConfig {
71 pub algorithm: KeyDerivationAlgorithm,
72 pub iterations: u32,
73 pub salt_length: usize,
74 pub key_length: usize,
75}
76
77impl Default for KeyDerivationConfig {
78 fn default() -> Self {
79 Self {
80 algorithm: KeyDerivationAlgorithm::Argon2,
81 iterations: 100_000,
82 salt_length: 32,
83 key_length: 32,
84 }
85 }
86}
87
88#[derive(Debug, Clone, Serialize, Deserialize)]
90pub enum KeyDerivationAlgorithm {
91 Argon2,
92 Pbkdf2,
93 Scrypt,
94}
95
96pub struct SecurityManager {
98 config: SecurityConfig,
99 encryption: encryption::EncryptionManager,
100 compression: compression::CompressionManager,
101 hashing: hashing::HashManager,
102}
103
104impl SecurityManager {
105 pub fn new(config: SecurityConfig) -> Result<Self, SecurityError> {
106 let encryption = encryption::EncryptionManager::new(config.encryption_algorithm.clone());
107 let compression = compression::CompressionManager::new(config.compression_algorithm.clone())?;
108 let hashing = hashing::HashManager::new()?;
109
110 Ok(Self {
111 config,
112 encryption,
113 compression,
114 hashing,
115 })
116 }
117
118 pub async fn secure_data(
120 &self,
121 data: &[u8],
122 key: &encryption::EncryptionKey,
123 ) -> Result<Vec<u8>, SecurityError> {
124 let mut processed_data = data.to_vec();
125
126 if self.config.compression_enabled {
128 processed_data = self.compression.compress(&processed_data)?;
129 }
130
131 if self.config.encryption_enabled {
133 processed_data = self.encryption.encrypt(&processed_data, key).await
134 .map_err(|e| SecurityError::Encryption(e.to_string()))?;
135 }
136
137 if self.config.integrity_checking {
139 let hash = self.hashing.hash(&processed_data)?;
140 processed_data.extend_from_slice(&hash);
141 }
142
143 Ok(processed_data)
144 }
145
146 pub async fn unsecure_data(
148 &self,
149 data: &[u8],
150 key: &encryption::EncryptionKey,
151 ) -> Result<Vec<u8>, SecurityError> {
152 let mut processed_data = data.to_vec();
153
154 if self.config.integrity_checking {
156 let expected_hash_len = 32; if processed_data.len() < expected_hash_len {
158 return Err(SecurityError::InvalidData("Data too short for integrity check".to_string()));
159 }
160
161 let data_len = processed_data.len() - expected_hash_len;
162 let (data_part, hash_part) = processed_data.split_at(data_len);
163
164 let actual_hash = self.hashing.hash(data_part)?;
165 if actual_hash != hash_part {
166 return Err(SecurityError::Hash("Integrity check failed".to_string()));
167 }
168
169 processed_data = data_part.to_vec();
170 }
171
172 if self.config.encryption_enabled {
174 processed_data = self.encryption.decrypt(&processed_data, key).await
175 .map_err(|e| SecurityError::Decryption(e.to_string()))?;
176 }
177
178 if self.config.compression_enabled {
180 processed_data = self.compression.decompress(&processed_data)?;
181 }
182
183 Ok(processed_data)
184 }
185
186 pub async fn derive_key(
188 &self,
189 password: &str,
190 salt: Option<&[u8]>,
191 ) -> Result<Vec<u8>, SecurityError> {
192 let salt = salt.unwrap_or_else(|| b"default_salt");
193
194 match self.config.key_derivation.algorithm {
195 KeyDerivationAlgorithm::Argon2 => {
196 self.hashing.derive_key_argon2(
198 password.as_bytes(),
199 salt,
200 self.config.key_derivation.iterations,
201 self.config.key_derivation.key_length,
202 )
203 }
204 KeyDerivationAlgorithm::Pbkdf2 => {
205 self.hashing.derive_key_pbkdf2(
207 password.as_bytes(),
208 salt,
209 self.config.key_derivation.iterations,
210 self.config.key_derivation.key_length,
211 )
212 }
213 KeyDerivationAlgorithm::Scrypt => {
214 self.hashing.derive_key_scrypt(
216 password.as_bytes(),
217 salt,
218 self.config.key_derivation.iterations,
219 self.config.key_derivation.key_length,
220 )
221 }
222 }
223 }
224
225 pub fn generate_nonce(&self) -> Result<Vec<u8>, SecurityError> {
227 use rand::{Rng, rngs::OsRng};
229 let mut nonce = [0u8; 12];
230 OsRng.fill(&mut nonce);
231 Ok(nonce.to_vec())
232 }
233
234 pub fn config(&self) -> &SecurityConfig {
236 &self.config
237 }
238
239 pub fn update_config(&mut self, config: SecurityConfig) -> Result<(), SecurityError> {
241 let encryption = encryption::EncryptionManager::new(config.encryption_algorithm.clone());
242 let compression = compression::CompressionManager::new(config.compression_algorithm.clone())?;
243
244 self.config = config;
245 self.encryption = encryption;
246 self.compression = compression;
247
248 Ok(())
249 }
250}
251
252#[cfg(test)]
253mod tests {
254 use super::*;
255
256 #[tokio::test]
257 async fn test_security_manager_creation() {
258 let config = SecurityConfig::default();
259 let manager = SecurityManager::new(config);
260 assert!(manager.is_ok());
261 }
262
263 #[tokio::test]
264 async fn test_security_config_default() {
265 let config = SecurityConfig::default();
266 assert!(config.encryption_enabled);
267 assert!(config.compression_enabled);
268 assert!(config.integrity_checking);
269 }
270
271 #[tokio::test]
272 async fn test_key_derivation_config_default() {
273 let config = KeyDerivationConfig::default();
274 assert_eq!(config.iterations, 100_000);
275 assert_eq!(config.salt_length, 32);
276 assert_eq!(config.key_length, 32);
277 }
278}