leptos_sync_core/security/
mod.rs

1//! Security features including encryption and compression
2
3use 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/// Security configuration
33#[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
56/// Re-export encryption algorithm from submodule
57pub use encryption::EncryptionAlgorithm;
58
59/// Re-export compression algorithm from submodule
60pub use compression::CompressionAlgorithm;
61
62/// Re-export authentication types from submodule
63pub use authentication::{AuthenticationManager, AuthProvider, UserSession, User, AuthConfig};
64
65/// Re-export GDPR types from submodule
66pub use gdpr::{GDPRCompliance, DataSubject, DataProcessingPurpose, PersonalDataRecord, AuditLogEntry};
67
68/// Key derivation configuration
69#[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/// Key derivation algorithm
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub enum KeyDerivationAlgorithm {
91    Argon2,
92    Pbkdf2,
93    Scrypt,
94}
95
96/// Security manager for handling encryption and compression
97pub 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    /// Secure data (encrypt and compress)
119    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        // Compress first (if enabled)
127        if self.config.compression_enabled {
128            processed_data = self.compression.compress(&processed_data)?;
129        }
130
131        // Encrypt (if enabled)
132        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        // Add integrity check (if enabled)
138        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    /// Unsecure data (decrypt and decompress)
147    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        // Verify integrity check (if enabled)
155        if self.config.integrity_checking {
156            let expected_hash_len = 32; // SHA-256 hash length
157            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        // Decrypt (if enabled)
173        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        // Decompress (if enabled)
179        if self.config.compression_enabled {
180            processed_data = self.compression.decompress(&processed_data)?;
181        }
182
183        Ok(processed_data)
184    }
185
186    /// Generate a secure key from a password
187    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                // Use Argon2 for key derivation
197                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                // Use PBKDF2 for key derivation
206                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                // Use Scrypt for key derivation
215                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    /// Generate a random nonce (for compatibility)
226    pub fn generate_nonce(&self) -> Result<Vec<u8>, SecurityError> {
227        // Generate a 12-byte nonce for GCM
228        use rand::{Rng, rngs::OsRng};
229        let mut nonce = [0u8; 12];
230        OsRng.fill(&mut nonce);
231        Ok(nonce.to_vec())
232    }
233
234    /// Get security configuration
235    pub fn config(&self) -> &SecurityConfig {
236        &self.config
237    }
238
239    /// Update security configuration
240    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}