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;
9
10#[derive(Error, Debug)]
11pub enum SecurityError {
12    #[error("Encryption error: {0}")]
13    Encryption(String),
14    #[error("Decryption error: {0}")]
15    Decryption(String),
16    #[error("Compression error: {0}")]
17    Compression(String),
18    #[error("Decompression error: {0}")]
19    Decompression(String),
20    #[error("Hash error: {0}")]
21    Hash(String),
22    #[error("Invalid key: {0}")]
23    InvalidKey(String),
24    #[error("Invalid algorithm: {0}")]
25    InvalidAlgorithm(String),
26    #[error("Invalid data: {0}")]
27    InvalidData(String),
28}
29
30/// Security configuration
31#[derive(Debug, Clone, Serialize, Deserialize)]
32pub struct SecurityConfig {
33    pub encryption_enabled: bool,
34    pub compression_enabled: bool,
35    pub encryption_algorithm: EncryptionAlgorithm,
36    pub compression_algorithm: CompressionAlgorithm,
37    pub key_derivation: KeyDerivationConfig,
38    pub integrity_checking: bool,
39}
40
41impl Default for SecurityConfig {
42    fn default() -> Self {
43        Self {
44            encryption_enabled: true,
45            compression_enabled: true,
46            encryption_algorithm: EncryptionAlgorithm::Aes256Gcm,
47            compression_algorithm: CompressionAlgorithm::Lz4,
48            key_derivation: KeyDerivationConfig::default(),
49            integrity_checking: true,
50        }
51    }
52}
53
54/// Re-export encryption algorithm from submodule
55pub use encryption::EncryptionAlgorithm;
56
57/// Re-export compression algorithm from submodule
58pub use compression::CompressionAlgorithm;
59
60/// Key derivation configuration
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct KeyDerivationConfig {
63    pub algorithm: KeyDerivationAlgorithm,
64    pub iterations: u32,
65    pub salt_length: usize,
66    pub key_length: usize,
67}
68
69impl Default for KeyDerivationConfig {
70    fn default() -> Self {
71        Self {
72            algorithm: KeyDerivationAlgorithm::Argon2,
73            iterations: 100_000,
74            salt_length: 32,
75            key_length: 32,
76        }
77    }
78}
79
80/// Key derivation algorithm
81#[derive(Debug, Clone, Serialize, Deserialize)]
82pub enum KeyDerivationAlgorithm {
83    Argon2,
84    Pbkdf2,
85    Scrypt,
86}
87
88/// Security manager for handling encryption and compression
89pub struct SecurityManager {
90    config: SecurityConfig,
91    encryption: encryption::EncryptionManager,
92    compression: compression::CompressionManager,
93    hashing: hashing::HashManager,
94}
95
96impl SecurityManager {
97    pub fn new(config: SecurityConfig) -> Result<Self, SecurityError> {
98        let encryption = encryption::EncryptionManager::new(config.encryption_algorithm.clone())?;
99        let compression = compression::CompressionManager::new(config.compression_algorithm.clone())?;
100        let hashing = hashing::HashManager::new()?;
101
102        Ok(Self {
103            config,
104            encryption,
105            compression,
106            hashing,
107        })
108    }
109
110    /// Secure data (encrypt and compress)
111    pub async fn secure_data(
112        &self,
113        data: &[u8],
114        key: &[u8],
115        nonce: Option<&[u8]>,
116    ) -> Result<Vec<u8>, SecurityError> {
117        let mut processed_data = data.to_vec();
118
119        // Compress first (if enabled)
120        if self.config.compression_enabled {
121            processed_data = self.compression.compress(&processed_data)?;
122        }
123
124        // Encrypt (if enabled)
125        if self.config.encryption_enabled {
126            processed_data = self.encryption.encrypt(&processed_data, key, nonce)?;
127        }
128
129        // Add integrity check (if enabled)
130        if self.config.integrity_checking {
131            let hash = self.hashing.hash(&processed_data)?;
132            processed_data.extend_from_slice(&hash);
133        }
134
135        Ok(processed_data)
136    }
137
138    /// Unsecure data (decrypt and decompress)
139    pub async fn unsecure_data(
140        &self,
141        data: &[u8],
142        key: &[u8],
143        nonce: Option<&[u8]>,
144    ) -> Result<Vec<u8>, SecurityError> {
145        let mut processed_data = data.to_vec();
146
147        // Verify integrity check (if enabled)
148        if self.config.integrity_checking {
149            let expected_hash_len = 32; // SHA-256 hash length
150            if processed_data.len() < expected_hash_len {
151                return Err(SecurityError::InvalidData("Data too short for integrity check".to_string()));
152            }
153
154            let data_len = processed_data.len() - expected_hash_len;
155            let (data_part, hash_part) = processed_data.split_at(data_len);
156            
157            let actual_hash = self.hashing.hash(data_part)?;
158            if actual_hash != hash_part {
159                return Err(SecurityError::Hash("Integrity check failed".to_string()));
160            }
161
162            processed_data = data_part.to_vec();
163        }
164
165        // Decrypt (if enabled)
166        if self.config.encryption_enabled {
167            processed_data = self.encryption.decrypt(&processed_data, key, nonce)?;
168        }
169
170        // Decompress (if enabled)
171        if self.config.compression_enabled {
172            processed_data = self.compression.decompress(&processed_data)?;
173        }
174
175        Ok(processed_data)
176    }
177
178    /// Generate a secure key from a password
179    pub async fn derive_key(
180        &self,
181        password: &str,
182        salt: Option<&[u8]>,
183    ) -> Result<Vec<u8>, SecurityError> {
184        let salt = salt.unwrap_or_else(|| b"default_salt");
185        
186        match self.config.key_derivation.algorithm {
187            KeyDerivationAlgorithm::Argon2 => {
188                // Use Argon2 for key derivation
189                self.hashing.derive_key_argon2(
190                    password.as_bytes(),
191                    salt,
192                    self.config.key_derivation.iterations,
193                    self.config.key_derivation.key_length,
194                )
195            }
196            KeyDerivationAlgorithm::Pbkdf2 => {
197                // Use PBKDF2 for key derivation
198                self.hashing.derive_key_pbkdf2(
199                    password.as_bytes(),
200                    salt,
201                    self.config.key_derivation.iterations,
202                    self.config.key_derivation.key_length,
203                )
204            }
205            KeyDerivationAlgorithm::Scrypt => {
206                // Use Scrypt for key derivation
207                self.hashing.derive_key_scrypt(
208                    password.as_bytes(),
209                    salt,
210                    self.config.key_derivation.iterations,
211                    self.config.key_derivation.key_length,
212                )
213            }
214        }
215    }
216
217    /// Generate a random nonce
218    pub fn generate_nonce(&self) -> Result<Vec<u8>, SecurityError> {
219        self.encryption.generate_nonce()
220    }
221
222    /// Get security configuration
223    pub fn config(&self) -> &SecurityConfig {
224        &self.config
225    }
226
227    /// Update security configuration
228    pub fn update_config(&mut self, config: SecurityConfig) -> Result<(), SecurityError> {
229        let encryption = encryption::EncryptionManager::new(config.encryption_algorithm.clone())?;
230        let compression = compression::CompressionManager::new(config.compression_algorithm.clone())?;
231        
232        self.config = config;
233        self.encryption = encryption;
234        self.compression = compression;
235        
236        Ok(())
237    }
238}
239
240#[cfg(test)]
241mod tests {
242    use super::*;
243
244    #[tokio::test]
245    async fn test_security_manager_creation() {
246        let config = SecurityConfig::default();
247        let manager = SecurityManager::new(config);
248        assert!(manager.is_ok());
249    }
250
251    #[tokio::test]
252    async fn test_security_config_default() {
253        let config = SecurityConfig::default();
254        assert!(config.encryption_enabled);
255        assert!(config.compression_enabled);
256        assert!(config.integrity_checking);
257    }
258
259    #[tokio::test]
260    async fn test_key_derivation_config_default() {
261        let config = KeyDerivationConfig::default();
262        assert_eq!(config.iterations, 100_000);
263        assert_eq!(config.salt_length, 32);
264        assert_eq!(config.key_length, 32);
265    }
266}