dcrypt_symmetric/streaming/
gcm.rs1use super::{StreamingDecrypt, StreamingEncrypt};
4use crate::aead::gcm::{Aes128Gcm, Aes256Gcm, GcmNonce};
5use crate::aes::keys::{Aes128Key, Aes256Key};
6use crate::cipher::{Aead, SymmetricCipher};
7use crate::error::{validate_stream_state, Result, SymmetricResultExt};
8use std::io::{Read, Write};
9
10pub struct Aes128GcmEncryptStream<W: Write> {
12 writer: W,
13 cipher: Aes128Gcm,
14 buffer: Vec<u8>,
15 finalized: bool,
16 aad: Option<Vec<u8>>,
17 counter: u32,
19 base_nonce: GcmNonce,
21}
22
23impl<W: Write> Aes128GcmEncryptStream<W> {
24 pub fn new(writer: W, key: &Aes128Key, aad: Option<&[u8]>) -> Result<Self> {
26 let cipher = Aes128Gcm::new(key)?;
28 let base_nonce = Aes128Gcm::generate_nonce();
29
30 let mut w = writer;
32 w.write_all(base_nonce.as_bytes()).map_io_err()?;
33
34 Ok(Self {
35 writer: w,
36 cipher,
37 buffer: Vec::with_capacity(16384), finalized: false,
39 aad: aad.map(|a| a.to_vec()),
40 counter: 0,
41 base_nonce,
42 })
43 }
44
45 fn derive_chunk_nonce(&self) -> GcmNonce {
47 let mut nonce_bytes = *self.base_nonce.as_bytes();
49 let counter_bytes = self.counter.to_be_bytes();
50
51 for i in 0..4 {
53 nonce_bytes[8 + i] ^= counter_bytes[i];
54 }
55
56 GcmNonce::new(nonce_bytes)
57 }
58
59 fn flush_buffer(&mut self) -> Result<()> {
61 if self.buffer.is_empty() {
62 return Ok(());
63 }
64
65 let chunk_nonce = self.derive_chunk_nonce();
67
68 let ciphertext = self
70 .cipher
71 .encrypt(&chunk_nonce, &self.buffer, self.aad.as_deref())?;
72
73 self.writer.write_all(&[1]).map_io_err()?; let counter_bytes = self.counter.to_be_bytes();
78 self.writer.write_all(&counter_bytes).map_io_err()?;
79
80 let len = (ciphertext.len() as u32).to_be_bytes();
82 self.writer.write_all(&len).map_io_err()?;
83 self.writer.write_all(&ciphertext).map_io_err()?;
84
85 self.counter += 1;
87
88 self.buffer.clear();
90
91 Ok(())
92 }
93}
94
95impl<W: Write> StreamingEncrypt<W> for Aes128GcmEncryptStream<W> {
96 fn write(&mut self, data: &[u8]) -> Result<()> {
98 validate_stream_state(!self.finalized, "stream write", "stream already finalized")?;
99
100 self.buffer.extend_from_slice(data);
102
103 if self.buffer.len() >= 16384 {
105 self.flush_buffer()?;
106 }
107
108 Ok(())
109 }
110
111 fn finalize(mut self) -> Result<W> {
113 validate_stream_state(
114 !self.finalized,
115 "stream finalize",
116 "stream already finalized",
117 )?;
118
119 self.flush_buffer()?;
121
122 self.writer.write_all(&[0]).map_io_err()?;
124
125 self.finalized = true;
126 Ok(self.writer)
127 }
128}
129
130pub struct Aes128GcmDecryptStream<R: Read> {
132 reader: R,
133 cipher: Aes128Gcm,
134 base_nonce: GcmNonce,
135 finished: bool,
136 aad: Option<Vec<u8>>,
137}
138
139impl<R: Read> Aes128GcmDecryptStream<R> {
140 pub fn new(mut reader: R, key: &Aes128Key, aad: Option<&[u8]>) -> Result<Self> {
142 let mut nonce_bytes = [0u8; 12];
144 reader.read_exact(&mut nonce_bytes).map_io_err()?;
145
146 let base_nonce = GcmNonce::new(nonce_bytes);
147 let cipher = Aes128Gcm::new(key)?;
149
150 Ok(Self {
151 reader,
152 cipher,
153 base_nonce,
154 finished: false,
155 aad: aad.map(|a| a.to_vec()),
156 })
157 }
158
159 fn derive_chunk_nonce(&self, counter: u32) -> GcmNonce {
161 let mut nonce_bytes = *self.base_nonce.as_bytes();
162 let counter_bytes = counter.to_be_bytes();
163
164 for i in 0..4 {
166 nonce_bytes[8 + i] ^= counter_bytes[i];
167 }
168
169 GcmNonce::new(nonce_bytes)
170 }
171}
172
173impl<R: Read> StreamingDecrypt<R> for Aes128GcmDecryptStream<R> {
174 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
176 if self.finished {
177 return Ok(0);
178 }
179
180 let mut marker = [0u8; 1];
182 self.reader.read_exact(&mut marker).map_io_err()?;
183
184 if marker[0] == 0 {
186 self.finished = true;
187 return Ok(0);
188 }
189
190 let mut counter_bytes = [0u8; 4];
192 self.reader.read_exact(&mut counter_bytes).map_io_err()?;
193 let counter = u32::from_be_bytes(counter_bytes);
194
195 let chunk_nonce = self.derive_chunk_nonce(counter);
197
198 let mut len_bytes = [0u8; 4];
200 self.reader.read_exact(&mut len_bytes).map_io_err()?;
201 let len = u32::from_be_bytes(len_bytes) as usize;
202
203 let mut ciphertext = vec![0u8; len];
205 self.reader.read_exact(&mut ciphertext).map_io_err()?;
206
207 let plaintext = self
209 .cipher
210 .decrypt(&chunk_nonce, &ciphertext, self.aad.as_deref())?;
211
212 let to_copy = plaintext.len().min(buf.len());
214 buf[..to_copy].copy_from_slice(&plaintext[..to_copy]);
215
216 Ok(to_copy)
217 }
218}
219
220pub struct Aes256GcmEncryptStream<W: Write> {
222 writer: W,
223 cipher: Aes256Gcm,
224 buffer: Vec<u8>,
225 finalized: bool,
226 aad: Option<Vec<u8>>,
227 counter: u32,
229 base_nonce: GcmNonce,
231}
232
233impl<W: Write> Aes256GcmEncryptStream<W> {
234 pub fn new(writer: W, key: &Aes256Key, aad: Option<&[u8]>) -> Result<Self> {
236 let cipher = Aes256Gcm::new(key)?;
238 let base_nonce = Aes256Gcm::generate_nonce();
239
240 let mut w = writer;
242 w.write_all(base_nonce.as_bytes()).map_io_err()?;
243
244 Ok(Self {
245 writer: w,
246 cipher,
247 buffer: Vec::with_capacity(16384), finalized: false,
249 aad: aad.map(|a| a.to_vec()),
250 counter: 0,
251 base_nonce,
252 })
253 }
254
255 fn derive_chunk_nonce(&self) -> GcmNonce {
257 let mut nonce_bytes = *self.base_nonce.as_bytes();
259 let counter_bytes = self.counter.to_be_bytes();
260
261 for i in 0..4 {
263 nonce_bytes[8 + i] ^= counter_bytes[i];
264 }
265
266 GcmNonce::new(nonce_bytes)
267 }
268
269 fn flush_buffer(&mut self) -> Result<()> {
271 if self.buffer.is_empty() {
272 return Ok(());
273 }
274
275 let chunk_nonce = self.derive_chunk_nonce();
277
278 let ciphertext = self
280 .cipher
281 .encrypt(&chunk_nonce, &self.buffer, self.aad.as_deref())?;
282
283 self.writer.write_all(&[1]).map_io_err()?; let counter_bytes = self.counter.to_be_bytes();
288 self.writer.write_all(&counter_bytes).map_io_err()?;
289
290 let len = (ciphertext.len() as u32).to_be_bytes();
292 self.writer.write_all(&len).map_io_err()?;
293 self.writer.write_all(&ciphertext).map_io_err()?;
294
295 self.counter += 1;
297
298 self.buffer.clear();
300
301 Ok(())
302 }
303}
304
305impl<W: Write> StreamingEncrypt<W> for Aes256GcmEncryptStream<W> {
306 fn write(&mut self, data: &[u8]) -> Result<()> {
308 validate_stream_state(!self.finalized, "stream write", "stream already finalized")?;
309
310 self.buffer.extend_from_slice(data);
312
313 if self.buffer.len() >= 16384 {
315 self.flush_buffer()?;
316 }
317
318 Ok(())
319 }
320
321 fn finalize(mut self) -> Result<W> {
323 validate_stream_state(
324 !self.finalized,
325 "stream finalize",
326 "stream already finalized",
327 )?;
328
329 self.flush_buffer()?;
331
332 self.writer.write_all(&[0]).map_io_err()?;
334
335 self.finalized = true;
336 Ok(self.writer)
337 }
338}
339
340pub struct Aes256GcmDecryptStream<R: Read> {
342 reader: R,
343 cipher: Aes256Gcm,
344 base_nonce: GcmNonce,
345 finished: bool,
346 aad: Option<Vec<u8>>,
347}
348
349impl<R: Read> Aes256GcmDecryptStream<R> {
350 pub fn new(mut reader: R, key: &Aes256Key, aad: Option<&[u8]>) -> Result<Self> {
352 let mut nonce_bytes = [0u8; 12];
354 reader.read_exact(&mut nonce_bytes).map_io_err()?;
355
356 let base_nonce = GcmNonce::new(nonce_bytes);
357 let cipher = Aes256Gcm::new(key)?;
359
360 Ok(Self {
361 reader,
362 cipher,
363 base_nonce,
364 finished: false,
365 aad: aad.map(|a| a.to_vec()),
366 })
367 }
368
369 fn derive_chunk_nonce(&self, counter: u32) -> GcmNonce {
371 let mut nonce_bytes = *self.base_nonce.as_bytes();
372 let counter_bytes = counter.to_be_bytes();
373
374 for i in 0..4 {
376 nonce_bytes[8 + i] ^= counter_bytes[i];
377 }
378
379 GcmNonce::new(nonce_bytes)
380 }
381}
382
383impl<R: Read> StreamingDecrypt<R> for Aes256GcmDecryptStream<R> {
384 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
386 if self.finished {
387 return Ok(0);
388 }
389
390 let mut marker = [0u8; 1];
392 self.reader.read_exact(&mut marker).map_io_err()?;
393
394 if marker[0] == 0 {
396 self.finished = true;
397 return Ok(0);
398 }
399
400 let mut counter_bytes = [0u8; 4];
402 self.reader.read_exact(&mut counter_bytes).map_io_err()?;
403 let counter = u32::from_be_bytes(counter_bytes);
404
405 let chunk_nonce = self.derive_chunk_nonce(counter);
407
408 let mut len_bytes = [0u8; 4];
410 self.reader.read_exact(&mut len_bytes).map_io_err()?;
411 let len = u32::from_be_bytes(len_bytes) as usize;
412
413 let mut ciphertext = vec![0u8; len];
415 self.reader.read_exact(&mut ciphertext).map_io_err()?;
416
417 let plaintext = self
419 .cipher
420 .decrypt(&chunk_nonce, &ciphertext, self.aad.as_deref())?;
421
422 let to_copy = plaintext.len().min(buf.len());
424 buf[..to_copy].copy_from_slice(&plaintext[..to_copy]);
425
426 Ok(to_copy)
427 }
428}
429
430pub fn encrypt_file_aes128<R: Read, W: Write>(
432 mut reader: R,
433 writer: W,
434 key: &Aes128Key,
435 aad: Option<&[u8]>,
436) -> Result<()> {
437 let mut stream = Aes128GcmEncryptStream::new(writer, key, aad)?;
439
440 let mut buffer = [0u8; 8192];
441 loop {
442 let bytes_read = reader.read(&mut buffer).map_io_err()?;
443 if bytes_read == 0 {
444 break;
445 }
446
447 stream.write(&buffer[..bytes_read])?;
448 }
449
450 stream.finalize()?;
451 Ok(())
452}
453
454pub fn decrypt_file_aes128<R: Read, W: Write>(
456 reader: R,
457 mut writer: W,
458 key: &Aes128Key,
459 aad: Option<&[u8]>,
460) -> Result<()> {
461 let mut stream = Aes128GcmDecryptStream::new(reader, key, aad)?;
462
463 let mut buffer = [0u8; 8192];
464 loop {
465 let bytes_read = stream.read(&mut buffer)?;
466 if bytes_read == 0 {
467 break;
468 }
469
470 writer.write_all(&buffer[..bytes_read]).map_io_err()?;
471 }
472
473 Ok(())
474}
475
476pub fn encrypt_file_aes256<R: Read, W: Write>(
478 mut reader: R,
479 writer: W,
480 key: &Aes256Key,
481 aad: Option<&[u8]>,
482) -> Result<()> {
483 let mut stream = Aes256GcmEncryptStream::new(writer, key, aad)?;
485
486 let mut buffer = [0u8; 8192];
487 loop {
488 let bytes_read = reader.read(&mut buffer).map_io_err()?;
489 if bytes_read == 0 {
490 break;
491 }
492
493 stream.write(&buffer[..bytes_read])?;
494 }
495
496 stream.finalize()?;
497 Ok(())
498}
499
500pub fn decrypt_file_aes256<R: Read, W: Write>(
502 reader: R,
503 mut writer: W,
504 key: &Aes256Key,
505 aad: Option<&[u8]>,
506) -> Result<()> {
507 let mut stream = Aes256GcmDecryptStream::new(reader, key, aad)?;
508
509 let mut buffer = [0u8; 8192];
510 loop {
511 let bytes_read = stream.read(&mut buffer)?;
512 if bytes_read == 0 {
513 break;
514 }
515
516 writer.write_all(&buffer[..bytes_read]).map_io_err()?;
517 }
518
519 Ok(())
520}