aesstream/lib.rs
1//! Read/Write Wrapper for AES Encryption and Decryption during I/O Operations
2//!
3//! This crate provides an [`AesWriter`](struct.AesWriter.html), which can be used to wrap any
4//! existing [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) implementation with AES
5//! encryption, and [`AesReader`](struct.AesReader.html), which can wrap any existing
6//! [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) implemntation with AES decryption.
7//! If the inner reader provides a [`Seek`](https://doc.rust-lang.org/std/io/trait.Seek.html)
8//! implementation, AesReader will do so as well.
9//! See their struct-level documentation for more information.
10//!
11//! In fact this crate is not limited to AES.
12//! It can wrap any kind of [`BlockEncryptor`][be] i.e. [`BlockDecryptor`][bd] with CBC.
13//!
14//! [be]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockEncryptor.html
15//! [bd]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockEncryptor.html
16//!
17//! # Examples
18//!
19//! All examples use the following extern crates and imports:
20//!
21//! ```no_run
22//! extern crate crypto;
23//! extern crate rand;
24//! extern crate aesstream;
25//!
26//! use std::io::{Read, Write, Cursor};
27//! use std::fs::File;
28//! use crypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor};
29//! use rand::{Rng, OsRng};
30//! use aesstream::{AesWriter, AesReader};
31//! # fn main() {}
32//! ```
33//!
34//! You can use [`AesWriter`](struct.AesWriter.html) to wrap a file with encryption.
35//!
36//! ```no_run
37//! # extern crate crypto;
38//! # extern crate rand;
39//! # extern crate aesstream;
40//! # use std::io::{Write, Result};
41//! # use std::fs::File;
42//! # use crypto::aessafe::AesSafe128Encryptor;
43//! # use rand::{Rng, OsRng};
44//! # use aesstream::AesWriter;
45//! # fn encrypt() -> Result<()> {
46//! let key: [u8; 16] = OsRng::new()?.gen();
47//! let file = File::create("...")?;
48//! let encryptor = AesSafe128Encryptor::new(&key);
49//! let mut writer = AesWriter::new(file, encryptor)?;
50//! writer.write_all("Hello World!".as_bytes())?;
51//! # Ok(())
52//! # }
53//! # fn main() { let _ = encrypt(); }
54//! ```
55//!
56//! And [`AesReader`](struct.AesReader.html) to decrypt it again.
57//!
58//! ```no_run
59//! # extern crate crypto;
60//! # extern crate rand;
61//! # extern crate aesstream;
62//! # use std::io::{Read, Result};
63//! # use std::fs::File;
64//! # use crypto::aessafe::AesSafe128Decryptor;
65//! # use rand::{Rng, OsRng};
66//! # use aesstream::AesReader;
67//! # fn decrypt() -> Result<()> {
68//! let key: [u8; 16] = OsRng::new()?.gen();
69//! let file = File::open("...")?;
70//! let decryptor = AesSafe128Decryptor::new(&key);
71//! let mut reader = AesReader::new(file, decryptor)?;
72//! let mut decrypted = String::new();
73//! reader.read_to_string(&mut decrypted)?;
74//! assert_eq!(decrypted, "Hello World!");
75//! # Ok(())
76//! # }
77//! # fn main() { let _ = decrypt(); }
78//! ```
79//!
80//! They can be used to en- and decrypt in-memory as well.
81//!
82//! ```
83//! # extern crate crypto;
84//! # extern crate rand;
85//! # extern crate aesstream;
86//! # use std::io::{Read, Write, Result, Cursor};
87//! # use crypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor};
88//! # use rand::{Rng, OsRng};
89//! # use aesstream::{AesWriter, AesReader};
90//! # fn in_memory() -> Result<()> {
91//! let key: [u8; 16] = OsRng::new()?.gen();
92//! let encryptor = AesSafe128Encryptor::new(&key);
93//! let mut encrypted = Vec::new();
94//! {
95//! let mut writer = AesWriter::new(&mut encrypted, encryptor)?;
96//! writer.write_all("Hello World!".as_bytes())?;
97//! }
98//! let decryptor = AesSafe128Decryptor::new(&key);
99//! let mut reader = AesReader::new(Cursor::new(encrypted), decryptor)?;
100//! let mut decrypted = String::new();
101//! reader.read_to_string(&mut decrypted)?;
102//! assert_eq!(decrypted, "Hello World!");
103//! # Ok(())
104//! # }
105//! # fn main() { let _ = in_memory(); }
106//! ```
107
108extern crate crypto;
109extern crate rand;
110
111#[cfg(test)] mod tests;
112
113use std::io::{Read, Write, Seek, SeekFrom, Result, Error, ErrorKind};
114
115use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor, Encryptor, Decryptor};
116use crypto::blockmodes::{PkcsPadding, CbcEncryptor, CbcDecryptor, EncPadding, DecPadding};
117use crypto::buffer::{RefReadBuffer, RefWriteBuffer, BufferResult, WriteBuffer, ReadBuffer};
118use rand::{OsRng, Rng};
119
120const BUFFER_SIZE: usize = 8192;
121
122/// Wraps a [`Write`](https://doc.rust-lang.org/std/io/trait.Write.html) implementation with CBC
123/// based on given [`BlockEncryptor`][be]
124///
125/// [be]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockEncryptor.html
126///
127/// # Examples
128///
129/// Write encrypted to a file.
130///
131/// ```no_run
132/// # extern crate crypto;
133/// # extern crate rand;
134/// # extern crate aesstream;
135/// # use std::io::{Write, Result};
136/// # use std::fs::File;
137/// # use crypto::aessafe::AesSafe128Encryptor;
138/// # use rand::{OsRng, Rng};
139/// # use aesstream::AesWriter;
140/// # fn foo() -> Result<()> {
141/// let key: [u8; 16] = OsRng::new()?.gen();
142/// let file = File::create("...")?;
143/// let encryptor = AesSafe128Encryptor::new(&key);
144/// let mut writer = AesWriter::new(file, encryptor)?;
145/// writer.write_all("Hello World!".as_bytes())?;
146/// # Ok(())
147/// # }
148/// # fn main() { let _ = foo(); }
149/// ```
150///
151/// Encrypt in-memory.
152///
153/// ```
154/// # extern crate crypto;
155/// # extern crate rand;
156/// # extern crate aesstream;
157/// # use std::io::{Write, Result, Cursor};
158/// # use crypto::aessafe::AesSafe128Encryptor;
159/// # use rand::{OsRng, Rng};
160/// # use aesstream::AesWriter;
161/// # fn foo() -> Result<()> {
162/// let key: [u8; 16] = OsRng::new()?.gen();
163/// let encryptor = AesSafe128Encryptor::new(&key);
164/// let mut encrypted = Vec::new();
165/// {
166/// let mut writer = AesWriter::new(&mut encrypted, encryptor)?;
167/// writer.write_all("Hello World!".as_bytes())?;
168/// }
169/// # Ok(())
170/// # }
171/// # fn main() { let _ = foo(); }
172/// ```
173pub struct AesWriter<E: BlockEncryptor, W: Write> {
174 /// Writer to write encrypted data to
175 writer: Option<W>,
176 /// Encryptor to encrypt data with
177 enc: CbcEncryptor<E, EncPadding<PkcsPadding>>,
178 /// Indicates weather the encryptor has done its final operation (inserting padding)
179 closed: bool,
180}
181
182impl<E: BlockEncryptor, W: Write> AesWriter<E, W> {
183 /// Creates a new AesWriter with a random IV.
184 ///
185 /// The IV will be written as first block of the file.
186 ///
187 /// # Parameters
188 ///
189 /// * **writer**: Writer to write encrypted data into
190 /// * **enc**: [`BlockEncryptor`][be] to use for encyrption
191 ///
192 /// # Examples
193 ///
194 /// ```no_run
195 /// # extern crate crypto;
196 /// # extern crate rand;
197 /// # extern crate aesstream;
198 /// # use crypto::aessafe::AesSafe128Encryptor;
199 /// # use rand::{OsRng, Rng};
200 /// # use std::io::Result;
201 /// # use std::fs::File;
202 /// # use aesstream::AesWriter;
203 /// # fn foo() -> Result<()> {
204 /// let key: [u8; 16] = OsRng::new()?.gen();
205 /// let encryptor = AesSafe128Encryptor::new(&key);
206 /// let file = File::create("...")?;
207 /// let mut writer = AesWriter::new(file, encryptor)?;
208 /// # Ok(())
209 /// # }
210 /// # fn main() { let _ = foo(); }
211 /// ```
212 ///
213 /// [be]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockEncryptor.html
214 pub fn new(mut writer: W, enc: E) -> Result<AesWriter<E, W>> {
215 let mut iv = vec![0u8; enc.block_size()];
216 OsRng::new()?.fill_bytes(&mut iv);
217 writer.write_all(&iv)?;
218 Ok(AesWriter {
219 writer: Some(writer),
220 enc: CbcEncryptor::new(enc, PkcsPadding, iv),
221 closed: false,
222 })
223 }
224
225 /// Encrypts passed buffer and writes all resulting encrypted blocks to the underlying writer
226 ///
227 /// # Parameters
228 ///
229 /// * **buf**: Plaintext to encrypt and write
230 /// * **eof**: If the provided buf is the last one to come and therefore encryption should be
231 /// finished and padding added.
232 fn encrypt_write(&mut self, buf: &[u8], eof: bool) -> Result<usize> {
233 let mut read_buf = RefReadBuffer::new(buf);
234 let mut out = [0u8; BUFFER_SIZE];
235 let mut write_buf = RefWriteBuffer::new(&mut out);
236 loop {
237 let res = self.enc.encrypt(&mut read_buf, &mut write_buf, eof)
238 .map_err(|e| Error::new(ErrorKind::Other, format!("encryption error: {:?}", e)))?;
239 let mut enc = write_buf.take_read_buffer();
240 let enc = enc.take_remaining();
241 self.writer.as_mut().unwrap().write_all(enc)?;
242 match res {
243 BufferResult::BufferUnderflow => break,
244 BufferResult::BufferOverflow if eof =>
245 panic!("read_buf underflow during encryption with eof"),
246 BufferResult::BufferOverflow => {},
247 }
248 }
249 // CbcEncryptor has its own internal buffer and always consumes all input
250 assert_eq!(read_buf.remaining(), 0);
251 Ok(buf.len())
252 }
253}
254
255impl<E: BlockEncryptor, W: Write> Write for AesWriter<E, W> {
256 /// Encrypts the passed buffer and writes the result to the underlying writer.
257 ///
258 /// Due to the blocksize of CBC not all data will be written instantaneously.
259 /// For example if 17 bytes are passed, the first 16 will be encrypted as one block and written
260 /// the underlying writer, but the last byte won't be encrypted and written yet.
261 ///
262 /// If [`flush`](#method.flush) has been called, this method will always return an error.
263 fn write(&mut self, buf: &[u8]) -> Result<usize> {
264 if self.closed {
265 return Err(Error::new(ErrorKind::Other, "AesWriter is closed"));
266 }
267 let written = self.encrypt_write(buf, false)?;
268 Ok(written)
269 }
270
271 /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
272 /// [Read more](https://doc.rust-lang.org/nightly/std/io/trait.Write.html#tymethod.flush)
273 ///
274 /// **Warning**: When this method is called, the encryption will finish and insert final padding.
275 /// After calling `flush`, this writer cannot be written to anymore and will always return an
276 /// error.
277 fn flush(&mut self) -> Result<()> {
278 if self.closed {
279 return Ok(());
280 }
281 self.encrypt_write(&[], true)?;
282 self.closed = true;
283 self.writer.as_mut().unwrap().flush()
284 }
285}
286
287impl<E: BlockEncryptor, W: Write> Drop for AesWriter<E, W> {
288 /// Drops this AesWriter trying to finish encryption and to write everything to the underlying writer.
289 fn drop(&mut self) {
290 if self.writer.is_some() {
291 if !std::thread::panicking() {
292 self.flush().unwrap();
293 } else {
294 let _ = self.flush();
295 }
296 }
297 }
298}
299
300/// Wraps a [`Read`](https://doc.rust-lang.org/std/io/trait.Read.html) implementation with CBC
301/// based on given [`BlockDecryptor`][bd]
302///
303/// [bd]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockDecryptor.html
304///
305/// # Examples
306///
307/// Read encrypted file.
308///
309/// ```no_run
310/// # extern crate crypto;
311/// # extern crate rand;
312/// # extern crate aesstream;
313/// # use std::io::{Read, Result};
314/// # use std::fs::File;
315/// # use crypto::aessafe::AesSafe128Decryptor;
316/// # use rand::{OsRng, Rng};
317/// # use aesstream::AesReader;
318/// # fn foo() -> Result<()> {
319/// let key: [u8; 16] = OsRng::new()?.gen();
320/// let file = File::open("...")?;
321/// let decryptor = AesSafe128Decryptor::new(&key);
322/// let mut reader = AesReader::new(file, decryptor)?;
323/// let mut decrypted = Vec::new();
324/// reader.read_to_end(&mut decrypted)?;
325/// # Ok(())
326/// # }
327/// # fn main() { let _ = foo(); }
328/// ```
329///
330/// Decrypt in-memory.
331///
332/// ```
333/// # extern crate crypto;
334/// # extern crate rand;
335/// # extern crate aesstream;
336/// # use std::io::{Read, Result, Cursor};
337/// # use std::fs::File;
338/// # use crypto::aessafe::AesSafe128Decryptor;
339/// # use rand::{OsRng, Rng};
340/// # use aesstream::AesReader;
341/// # fn foo() -> Result<()> {
342/// let encrypted = vec![];
343/// let key: [u8; 16] = OsRng::new()?.gen();
344/// let decryptor = AesSafe128Decryptor::new(&key);
345/// let mut reader = AesReader::new(Cursor::new(encrypted), decryptor)?;
346/// let mut decrypted = Vec::new();
347/// reader.read_to_end(&mut decrypted)?;
348/// # Ok(())
349/// # }
350/// # fn main() { let _ = foo(); }
351/// ```
352pub struct AesReader<D: BlockDecryptor, R: Read> {
353 /// Reader to read encrypted data from
354 reader: R,
355 /// Decryptor to decrypt data with
356 dec: CbcDecryptor<D, DecPadding<PkcsPadding>>,
357 /// Block size of BlockDecryptor, needed when seeking to correctly seek to the nearest block
358 block_size: usize,
359 /// Buffer used to store blob needed to find out if we reached eof
360 buffer: Vec<u8>,
361 /// Indicates wheather eof of the underlying buffer was reached
362 eof: bool,
363}
364
365impl<D: BlockDecryptor, R: Read> AesReader<D, R> {
366 /// Creates a new AesReader.
367 ///
368 /// Assumes that the first block of given reader is the IV.
369 ///
370 /// # Parameters
371 ///
372 /// * **reader**: Reader to read encrypted data from
373 /// * **dec**: [`BlockDecryptor`][bd] to use for decyrption
374 ///
375 /// # Examples
376 ///
377 /// ```no_run
378 /// # extern crate crypto;
379 /// # extern crate rand;
380 /// # extern crate aesstream;
381 /// # use crypto::aessafe::AesSafe128Decryptor;
382 /// # use rand::{OsRng, Rng};
383 /// # use std::io::Result;
384 /// # use std::fs::File;
385 /// # use aesstream::AesReader;
386 /// # fn foo() -> Result<()> {
387 /// let key: [u8; 16] = OsRng::new()?.gen();
388 /// let decryptor = AesSafe128Decryptor::new(&key);
389 /// let file = File::open("...")?;
390 /// let mut reader = AesReader::new(file, decryptor)?;
391 /// # Ok(())
392 /// # }
393 /// # fn main() { let _ = foo(); }
394 /// ```
395 ///
396 /// [bd]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockDecryptor.html
397 pub fn new(mut reader: R, dec: D) -> Result<AesReader<D, R>> {
398 let mut iv = vec![0u8; dec.block_size()];
399 reader.read_exact(&mut iv)?;
400 Ok(AesReader {
401 reader: reader,
402 block_size: dec.block_size(),
403 dec: CbcDecryptor::new(dec, PkcsPadding, iv),
404 buffer: Vec::new(),
405 eof: false,
406 })
407 }
408
409 /// Reads at max BUFFER_SIZE bytes, handles potential eof and returns the buffer as Vec<u8>
410 fn fill_buf(&mut self) -> Result<Vec<u8>> {
411 let mut eof_buffer = vec![0u8; BUFFER_SIZE];
412 let read = self.reader.read(&mut eof_buffer)?;
413 self.eof = read == 0;
414 eof_buffer.truncate(read);
415 Ok(eof_buffer)
416 }
417
418 /// Reads and decrypts data from the underlying stream and writes it into the passed buffer.
419 ///
420 /// The CbcDecryptor has an internal output buffer, but not an input buffer.
421 /// Therefore, we need to take care of letfover input.
422 /// Additionally, we need to handle eof correctly, as CbcDecryptor needs to correctly interpret
423 /// padding.
424 /// Thus, we need to read 2 buffers. The first one is read as input for decryption and the second
425 /// one to determine if eof is reached.
426 /// The next time this function is called, the second buffer is passed as input into decryption
427 /// and the first buffer is filled to find out if we reached eof.
428 ///
429 /// # Parameters
430 ///
431 /// * **buf**: Buffer to write decrypted data into.
432 fn read_decrypt(&mut self, buf: &mut [u8]) -> Result<usize> {
433 // if this is the first iteration, fill internal buffer
434 if self.buffer.is_empty() && !self.eof {
435 self.buffer = self.fill_buf()?;
436 }
437
438 let buf_len = buf.len();
439 let mut write_buf = RefWriteBuffer::new(buf);
440 let res;
441 let remaining;
442 {
443 let mut read_buf = RefReadBuffer::new(&self.buffer);
444
445 // test if CbcDecryptor still has enough decrypted data or we have enough buffered
446 res = self.dec.decrypt(&mut read_buf, &mut write_buf, self.eof)
447 .map_err(|e| Error::new(ErrorKind::Other, format!("decryption error: {:?}", e)))?;
448 remaining = read_buf.remaining();
449 }
450 // keep remaining bytes
451 let len = self.buffer.len();
452 self.buffer.drain(..(len - remaining));
453 // if we were able to decrypt, return early
454 match res {
455 BufferResult::BufferOverflow => return Ok(buf_len),
456 BufferResult::BufferUnderflow if self.eof => return Ok(write_buf.position()),
457 _ => {}
458 }
459
460 // else read new buffer
461 let mut dec_len = 0;
462 // We must return something, if we have something.
463 // If the reader doesn't return enough so that we can decrypt a block, we need to continue
464 // reading until we have enough data to return one decrypted block, or until we reach eof.
465 // If we reach eof, we will be able to decrypt the final block because of padding.
466 while dec_len == 0 && !self.eof {
467 let eof_buffer = self.fill_buf()?;
468 let remaining;
469 {
470 let mut read_buf = RefReadBuffer::new(&self.buffer);
471 self.dec.decrypt(&mut read_buf, &mut write_buf, self.eof)
472 .map_err(|e| Error::new(ErrorKind::Other, format!("decryption error: {:?}", e)))?;
473 let mut dec = write_buf.take_read_buffer();
474 let dec = dec.take_remaining();
475 dec_len = dec.len();
476 remaining = read_buf.remaining();
477 }
478 // keep remaining bytes
479 let len = self.buffer.len();
480 self.buffer.drain(..(len - remaining));
481 // append newly read bytes
482 self.buffer.extend(eof_buffer);
483 }
484 Ok(dec_len)
485 }
486
487}
488impl<D: BlockDecryptor, R: Read + Seek> AesReader<D, R> {
489 /// Seeks to *offset* from the start of the file
490 fn seek_from_start(&mut self, offset: u64) -> Result<u64> {
491 let block_num = offset / self.block_size as u64;
492 let block_offset = offset % self.block_size as u64;
493 // reset CbcDecryptor
494 self.reader.seek(SeekFrom::Start((block_num - 1) * self.block_size as u64))?;
495 let mut iv = vec![0u8; self.block_size];
496 self.reader.read_exact(&mut iv)?;
497 self.dec.reset(&iv);
498 self.buffer = Vec::new();
499 self.eof = false;
500 let mut skip = vec![0u8; block_offset as usize];
501 self.read_exact(&mut skip)?;
502 // subtract IV
503 Ok(offset - 16)
504 }
505}
506
507impl<D: BlockDecryptor, R: Read> Read for AesReader<D, R> {
508 /// Reads encrypted data from the underlying reader, decrypts it and writes the result into the
509 /// passed buffer.
510 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
511 let read = self.read_decrypt(buf)?;
512 Ok(read)
513 }
514}
515
516impl<D: BlockDecryptor, R: Read + Seek> Seek for AesReader<D, R> {
517 /// Seek to an offset, in bytes, in a stream.
518 /// [Read more](https://doc.rust-lang.org/nightly/std/io/trait.Seek.html#tymethod.seek)
519 ///
520 /// When seeking, this reader takes care of reinitializing the CbcDecryptor with the correct IV.
521 /// The passed position does *not* need to be aligned to the blocksize.
522 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
523 match pos {
524 SeekFrom::Start(offset) => {
525 // +16 because first block is the iv
526 self.seek_from_start(offset + 16)
527 },
528 SeekFrom::End(_) | SeekFrom::Current(_) => {
529 let pos = self.reader.seek(pos)?;
530 self.seek_from_start(pos)
531 },
532 }
533 }
534}