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}