1use super::key_management::MasterKey;
6use crate::error::{BackupError, Result};
7use aes_gcm::aead::Aead;
8use aes_gcm::{Aes256Gcm, Key, KeyInit, Nonce};
9use rand::RngCore;
10use std::io::{Read, Write};
11
12#[cfg(debug_assertions)]
15use std::collections::HashSet;
16#[cfg(debug_assertions)]
17use std::sync::Mutex;
18
19#[cfg(debug_assertions)]
20static NONCE_TRACKER: Mutex<Option<HashSet<[u8; 12]>>> = Mutex::new(None);
21
22#[derive(Debug, Clone)]
24pub struct EncryptionConfig {
25 pub chunk_size: usize,
27 pub buffer_size: usize,
29}
30
31impl Default for EncryptionConfig {
32 fn default() -> Self {
33 Self {
34 chunk_size: 1024 * 1024, buffer_size: 64 * 1024, }
37 }
38}
39
40#[derive(Debug, Clone)]
42pub struct EncryptedData {
43 pub nonce: [u8; 12],
45 pub salt: [u8; 16],
47 pub ciphertext: Vec<u8>,
49 pub original_size: u64,
51}
52
53impl EncryptedData {
54 #[must_use]
56 pub fn to_bytes(&self) -> Vec<u8> {
57 let mut result = Vec::with_capacity(44 + self.ciphertext.len());
58 result.extend_from_slice(&self.nonce); result.extend_from_slice(&self.salt); result.extend_from_slice(&self.original_size.to_le_bytes()); result.extend_from_slice(&(self.ciphertext.len() as u64).to_le_bytes()); result.extend_from_slice(&self.ciphertext); result
64 }
65
66 pub fn from_bytes(data: &[u8]) -> Result<Self> {
68 if data.len() < 44 {
69 return Err(BackupError::EncryptionError(
70 "暗号化データが短すぎます".to_string(),
71 ));
72 }
73
74 let mut nonce = [0u8; 12];
75 nonce.copy_from_slice(&data[0..12]);
76
77 let mut salt = [0u8; 16];
78 salt.copy_from_slice(&data[12..28]);
79
80 let original_size = u64::from_le_bytes([
81 data[28], data[29], data[30], data[31], data[32], data[33], data[34], data[35],
82 ]);
83
84 let ciphertext_len = u64::from_le_bytes([
85 data[36], data[37], data[38], data[39], data[40], data[41], data[42], data[43],
86 ]) as usize;
87
88 let expected_len = match 44usize.checked_add(ciphertext_len) {
90 Some(len) => len,
91 None => {
92 return Err(BackupError::EncryptionError(
93 "暗号化データの長さが不正です(オーバーフロー)".to_string(),
94 ));
95 }
96 };
97
98 if data.len() != expected_len {
99 return Err(BackupError::EncryptionError(
100 "暗号化データの長さが一致しません".to_string(),
101 ));
102 }
103
104 let ciphertext = data[44..].to_vec();
105
106 Ok(Self {
107 nonce,
108 salt,
109 ciphertext,
110 original_size,
111 })
112 }
113}
114
115pub struct EncryptionEngine {
117 config: EncryptionConfig,
118}
119
120impl EncryptionEngine {
121 #[must_use]
123 pub fn new(config: EncryptionConfig) -> Self {
124 Self { config }
125 }
126
127 fn generate_nonce() -> [u8; 12] {
132 let mut nonce = [0u8; 12];
133 rand::rng().fill_bytes(&mut nonce);
134
135 #[cfg(debug_assertions)]
138 {
139 let mut tracker = NONCE_TRACKER.lock().unwrap();
140 let set = tracker.get_or_insert_with(HashSet::new);
141
142 assert!(set.insert(nonce),
143 "\n\
144 ╔══════════════════════════════════════════════════════════════╗\n\
145 ║ 🚨 CRITICAL SECURITY VIOLATION: Nonce Collision Detected! ║\n\
146 ╚══════════════════════════════════════════════════════════════╝\n\
147 \n\
148 Nonce (hex): {:02x?}\n\
149 \n\
150 ⚠️ SECURITY IMPACT:\n\
151 This is a CRITICAL security vulnerability in AES-256-GCM encryption.\n\
152 Nonce reuse completely breaks the confidentiality and authenticity guarantees.\n\
153 \n\
154 An attacker can:\n\
155 - Decrypt encrypted data without the key\n\
156 - Forge authenticated messages\n\
157 - Recover the encryption key\n\
158 \n\
159 📊 STATISTICS:\n\
160 - Total unique nonces generated so far: {}\n\
161 - Collision detected on nonce #{}\n\
162 \n\
163 ℹ️ DEBUG BUILD ONLY:\n\
164 This panic only occurs in debug builds to help detect bugs during development.\n\
165 Release builds have zero overhead (this code is removed at compile time).\n\
166 \n\
167 🔧 NEXT STEPS:\n\
168 1. Check if this is a test scenario (intentional collision test)\n\
169 2. If not, investigate random number generation (rand crate)\n\
170 3. Review recent changes to generate_nonce() function\n\
171 4. Run mutation testing to verify detection works correctly\n\
172 \n",
173 nonce,
174 set.len(),
175 set.len() + 1
176 );
177 }
178
179 nonce
180 }
181
182 #[must_use]
184 pub fn generate_nonce_internal() -> [u8; 12] {
185 Self::generate_nonce()
186 }
187
188 #[must_use]
190 pub fn get_chunk_size(&self) -> usize {
191 self.config.chunk_size
192 }
193
194 #[allow(deprecated)]
201 pub fn encrypt(
202 &self,
203 data: &[u8],
204 master_key: &MasterKey,
205 salt: [u8; 16],
206 ) -> Result<EncryptedData> {
207 let nonce_bytes = Self::generate_nonce();
208
209 let key = Key::<Aes256Gcm>::from_slice(master_key.as_bytes());
211 let cipher = Aes256Gcm::new(key);
212 let nonce = Nonce::from_slice(&nonce_bytes);
213
214 let ciphertext = cipher
215 .encrypt(nonce, data)
216 .map_err(|e| BackupError::EncryptionError(format!("暗号化エラー: {e}")))?;
217
218 Ok(EncryptedData {
219 nonce: nonce_bytes,
220 salt, ciphertext,
222 original_size: data.len() as u64,
223 })
224 }
225
226 #[allow(deprecated)]
235 pub fn decrypt(
236 &self,
237 encrypted_data: &EncryptedData,
238 master_key: &MasterKey,
239 ) -> Result<Vec<u8>> {
240 let key = Key::<Aes256Gcm>::from_slice(master_key.as_bytes());
241 let cipher = Aes256Gcm::new(key);
242 let nonce = Nonce::from_slice(&encrypted_data.nonce);
243
244 let plaintext = cipher
245 .decrypt(nonce, encrypted_data.ciphertext.as_ref())
246 .map_err(|e| BackupError::EncryptionError(format!("復号化エラー: {e}")))?;
247
248 Ok(plaintext)
249 }
250
251 #[allow(deprecated)]
260 pub fn encrypt_stream<R: Read, W: Write>(
261 &self,
262 mut reader: R,
263 mut writer: W,
264 master_key: &MasterKey,
265 ) -> Result<EncryptedData> {
266 let nonce_bytes = Self::generate_nonce();
267 let salt = crate::crypto::key_management::KeyDerivation::generate_salt();
268
269 writer.write_all(&nonce_bytes)?;
271 writer.write_all(&salt)?;
272
273 let key = Key::<Aes256Gcm>::from_slice(master_key.as_bytes());
274 let cipher = Aes256Gcm::new(key);
275
276 let mut total_size = 0u64;
277 let mut encrypted_chunks = Vec::new();
278 let mut buffer = vec![0u8; self.config.chunk_size];
279
280 loop {
281 let bytes_read = reader.read(&mut buffer)?;
282 if bytes_read == 0 {
283 break;
284 }
285
286 total_size += bytes_read as u64;
287
288 let mut chunk_nonce = nonce_bytes;
290 let chunk_index = encrypted_chunks.len() as u64;
291 chunk_nonce[4..12].copy_from_slice(&chunk_index.to_le_bytes());
292
293 #[allow(deprecated)]
294 let nonce = Nonce::from_slice(&chunk_nonce);
295 let chunk_ciphertext = cipher
296 .encrypt(nonce, &buffer[..bytes_read])
297 .map_err(|e| BackupError::EncryptionError(format!("チャンク暗号化エラー: {e}")))?;
298
299 writer.write_all(&(chunk_ciphertext.len() as u32).to_le_bytes())?;
301 writer.write_all(&chunk_ciphertext)?;
302
303 encrypted_chunks.push(chunk_ciphertext);
304 }
305
306 Ok(EncryptedData {
307 nonce: nonce_bytes,
308 salt,
309 ciphertext: encrypted_chunks.into_iter().flatten().collect(),
310 original_size: total_size,
311 })
312 }
313
314 #[allow(deprecated)]
326 pub fn decrypt_stream<R: Read, W: Write>(
327 &self,
328 mut reader: R,
329 mut writer: W,
330 master_key: &MasterKey,
331 ) -> Result<u64> {
332 let mut nonce_bytes = [0u8; 12];
334 let mut salt = [0u8; 16];
335 reader.read_exact(&mut nonce_bytes)?;
336 reader.read_exact(&mut salt)?;
337
338 let key = Key::<Aes256Gcm>::from_slice(master_key.as_bytes());
339 let cipher = Aes256Gcm::new(key);
340
341 let mut total_decrypted = 0u64;
342 let mut chunk_index = 0u64;
343
344 loop {
345 let mut chunk_size_bytes = [0u8; 4];
347 match reader.read_exact(&mut chunk_size_bytes) {
348 Ok(_) => {}
349 Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => break,
350 Err(e) => return Err(BackupError::IoError(e)),
351 }
352
353 let chunk_size = u32::from_le_bytes(chunk_size_bytes) as usize;
354 let mut chunk_data = vec![0u8; chunk_size];
355 reader.read_exact(&mut chunk_data)?;
356
357 let mut chunk_nonce = nonce_bytes;
359 chunk_nonce[4..12].copy_from_slice(&chunk_index.to_le_bytes());
360
361 #[allow(deprecated)]
362 let nonce = Nonce::from_slice(&chunk_nonce);
363 let plaintext = cipher
364 .decrypt(nonce, chunk_data.as_ref())
365 .map_err(|e| BackupError::EncryptionError(format!("チャンク復号化エラー: {e}")))?;
366
367 writer.write_all(&plaintext)?;
368 total_decrypted += plaintext.len() as u64;
369 chunk_index += 1;
370 }
371
372 Ok(total_decrypted)
373 }
374}
375
376impl Default for EncryptionEngine {
377 fn default() -> Self {
378 Self::new(EncryptionConfig::default())
379 }
380}
381
382#[cfg(test)]
383mod tests {
384 use super::*;
385
386 #[test]
387 fn test_encryption_decryption() {
388 let engine = EncryptionEngine::default();
389 let master_key = MasterKey::generate();
390 let original_data = b"Hello, World! This is a test message.";
391 let salt = [0u8; 16]; let encrypted = engine.encrypt(original_data, &master_key, salt).unwrap();
394 let decrypted = engine.decrypt(&encrypted, &master_key).unwrap();
395
396 assert_eq!(original_data, decrypted.as_slice());
397 assert_eq!(encrypted.original_size, original_data.len() as u64);
398 }
399
400 #[test]
401 fn test_encrypted_data_serialization() {
402 let engine = EncryptionEngine::default();
403 let master_key = MasterKey::generate();
404 let original_data = b"Test data for serialization";
405 let salt = [1u8; 16]; let encrypted = engine.encrypt(original_data, &master_key, salt).unwrap();
408 let serialized = encrypted.to_bytes();
409 let deserialized = EncryptedData::from_bytes(&serialized).unwrap();
410
411 let decrypted = engine.decrypt(&deserialized, &master_key).unwrap();
412 assert_eq!(original_data, decrypted.as_slice());
413 }
414
415 #[test]
416 fn test_different_keys_fail() {
417 let engine = EncryptionEngine::default();
418 let master_key1 = MasterKey::generate();
419 let master_key2 = MasterKey::generate();
420 let original_data = b"Secret message";
421 let salt = [2u8; 16]; let encrypted = engine.encrypt(original_data, &master_key1, salt).unwrap();
424
425 assert!(engine.decrypt(&encrypted, &master_key2).is_err());
427 }
428
429 #[test]
430 fn test_stream_encryption() {
431 use std::io::Cursor;
432
433 let engine = EncryptionEngine::default();
434 let master_key = MasterKey::generate();
435 let original_data = b"This is a longer message for stream testing. ".repeat(100);
436
437 let reader = Cursor::new(&original_data);
438 let mut encrypted_buffer = Vec::new();
439 let encrypted_meta = engine
440 .encrypt_stream(reader, &mut encrypted_buffer, &master_key)
441 .unwrap();
442
443 assert_eq!(encrypted_meta.original_size, original_data.len() as u64);
444
445 let encrypted_reader = Cursor::new(&encrypted_buffer);
446 let mut decrypted_buffer = Vec::new();
447 let decrypted_size = engine
448 .decrypt_stream(encrypted_reader, &mut decrypted_buffer, &master_key)
449 .unwrap();
450
451 assert_eq!(decrypted_size, original_data.len() as u64);
452 assert_eq!(original_data, decrypted_buffer);
453 }
454}