redseat_crypto/
lib.rs

1
2
3
4use std::io::{Read, Write, Seek, SeekFrom, Result, Error, ErrorKind};
5
6use crypto::hmac::Hmac;
7use crypto::pbkdf2;
8use crypto::sha1::Sha1;
9use crypto::symmetriccipher::{BlockDecryptor, BlockEncryptor, Encryptor, Decryptor};
10use crypto::blockmodes::{PkcsPadding, CbcEncryptor, CbcDecryptor, EncPadding, DecPadding};
11use crypto::buffer::{RefReadBuffer, RefWriteBuffer, BufferResult, WriteBuffer, ReadBuffer};
12use rand::rngs::OsRng;
13use rand::RngCore;
14#[cfg(feature="serde")]
15use serde::{Deserialize, Serialize};
16
17pub use crypto::aessafe;
18
19
20const KEY_SIZE: usize = 32;
21const BUFFER_SIZE: usize = 8192;
22
23
24/// Added as header in the encrypted file (just after the IV)
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26#[derive(Debug, Clone, PartialEq)]
27pub struct CryptoInfo{
28    pub thumb: Option<Vec<u8>>,
29    pub mime: Option<String>,
30    pub thumb_mime: Option<String>,
31    pub info: Option<String>,
32}
33
34impl CryptoInfo {
35    pub fn encrypted_thumb_size(&self) -> u32 {
36        self.thumb.as_ref().and_then(|s| Some(get_encrypted_size(s.len() as u64))).unwrap_or(0) as u32
37    }
38
39    pub fn encrypted_info_size(&self) -> u32 {
40        self.info.as_ref().and_then(|s| Some(get_encrypted_size(s.as_bytes().len() as u64))).unwrap_or(0) as u32
41    }
42
43    pub fn data_size(&self) -> u64 {
44        self.encrypted_thumb_size() as u64 + self.encrypted_info_size() as u64
45    } 
46
47    pub fn size(&self) -> u64 {
48        Self::header_size() + self.data_size()
49    } 
50
51    pub fn size_with_iv(&self) -> u64 {
52        16 + self.size()
53    } 
54
55    pub fn header_size() -> u64 {
56        4 + 4 + 32 + 256
57    }
58
59    pub fn mime_as_bytes(&self) -> Vec<u8>{
60        format!("{:width$}", self.mime.clone().unwrap_or("".to_owned()), width=256).as_bytes().to_vec()
61    }
62
63    pub fn thumb_mime_as_bytes(&self) -> Vec<u8>{
64        format!("{:width$}", self.thumb_mime.clone().unwrap_or("".to_owned()), width=32).as_bytes().to_vec()
65    }
66
67    
68    pub fn write<E: BlockEncryptor, W: Write>(&self, writer: &mut AesWriter<E, W>, iv: &Vec<u8>) -> Result<usize> {
69        //4 to store encrypted thumb size = T (can be 0)
70        //4 to store encrypted Info size = I (can be 0)
71        //32 to store thumb mimetype
72        //256 to store file mimetype
73        //T Bytes for the encrypted thumb
74        //I Bytes for the encrypted info
75        let mut writen = 0;
76        writen += writer.write_direct(&self.encrypted_thumb_size().to_be_bytes())?;
77        writen += writer.write_direct(&self.encrypted_info_size().to_be_bytes())?;
78
79        writen += writer.write_direct(&self.thumb_mime_as_bytes())?;
80        writen += writer.write_direct(&self.mime_as_bytes())?;
81
82        if let Some(thumb) = &self.thumb {
83            let mut read_buffer = RefReadBuffer::new(thumb);
84            let mut out = [0; 16];
85            let mut write_buffer = RefWriteBuffer::new(&mut out);
86            
87            loop {
88                let result = writer.enc.encrypt(&mut read_buffer, &mut write_buffer, true) .map_err(|e| Error::new(ErrorKind::Other, format!("thumb encryption error: {:?}", e)))?;
89                let mut data = &write_buffer
90                .take_read_buffer()
91                .take_remaining()
92                .iter().map(|i| i.clone()).collect::<Vec<u8>>();
93                
94                writer.write_direct(&mut data)?;
95                match result {
96                    BufferResult::BufferUnderflow => break,
97                    BufferResult::BufferOverflow => {}
98                }
99            }           
100            writer.enc.reset(&iv)
101        }
102        if let Some(info) = &self.info {
103            let mut read_buffer = RefReadBuffer::new(info.as_bytes());
104            let mut out = [0; 16];
105            let mut write_buffer = RefWriteBuffer::new(&mut out);
106            
107            loop {
108                let result = writer.enc.encrypt(&mut read_buffer, &mut write_buffer, true) .map_err(|e| Error::new(ErrorKind::Other, format!("thumb encryption error: {:?}", e)))?;
109                let mut data = &write_buffer
110                .take_read_buffer()
111                .take_remaining()
112                .iter().map(|i| i.clone()).collect::<Vec<u8>>();
113                
114                writer.write_direct(&mut data)?;
115                match result {
116                    BufferResult::BufferUnderflow => break,
117                    BufferResult::BufferOverflow => {}
118                }
119            }           
120            writer.enc.reset(&iv)
121        }
122
123        Ok(writen) 
124    }
125
126    pub fn from_reader<D: BlockDecryptor, R: Read>(reader: &mut AesReader<D, R>, iv: &Vec<u8>) -> Result<CryptoInfo> {
127        //4 to store encrypted thumb size = T (can be 0)
128        //4 to store encrypted Info size = I (can be 0)
129        //32 to store thumb mimetype
130        //256 to store file mimetype
131        //T Bytes for the encrypted thumb
132        //I Bytes for the encrypted info
133        let mut buf = vec![0u8; 4];
134        reader.read_exact_raw(&mut buf)?;
135        let size_thumb = u32::from_be_bytes(buf[0..4].try_into().map_err(|_| std::io::ErrorKind::Other)?);
136
137        let mut buf = vec![0u8; 4];
138        reader.read_exact_raw(&mut buf)?;
139        let size_info = u32::from_be_bytes(buf[0..4].try_into().map_err(|_| std::io::ErrorKind::Other)?);
140
141
142        let mut buf = vec![0u8; 32];
143        reader.read_exact_raw(&mut buf)?;
144        let thumb_mime = String::from_utf8(buf).map_err(|_| std::io::ErrorKind::Other)?.trim_end().to_string();
145
146        let mut buf = vec![0u8; 256];
147        reader.read_exact_raw(&mut buf)?;
148        let file_mime = String::from_utf8(buf).map_err(|_| std::io::ErrorKind::Other)?.trim_end().to_string();
149
150
151        let thumb = if size_thumb == 0 {
152            None
153        } else {
154            let mut crypt_buf = vec![0u8; size_thumb as usize];
155            reader.read_exact_raw(&mut crypt_buf)?;
156            let mut read_buffer = RefReadBuffer::new(&crypt_buf);
157            let mut buffer = [0; 16];
158            let mut write_buffer = RefWriteBuffer::new(&mut buffer);
159            let mut decryted_thumb: Vec<u8> = vec![];
160            reader.dec.reset(&iv);
161            loop {
162                let result = reader.dec.decrypt(&mut read_buffer, &mut write_buffer, true) .map_err(|e| Error::new(ErrorKind::Other, format!("thumb decryption error: {:?}", e)))?;
163
164                decryted_thumb.append(
165                    &mut write_buffer
166                        .take_read_buffer()
167                        .take_remaining()
168                        .iter()
169                        .map(|&i| i.clone()).collect::<Vec<u8>>(),
170                );
171                match result {
172                    BufferResult::BufferUnderflow => break,
173                    BufferResult::BufferOverflow => {}
174                }
175            }
176            reader.dec.reset(&iv);
177            Some(decryted_thumb)
178        };
179
180        let info = if size_info == 0 {
181            None
182        } else {
183            let mut crypt_buf = vec![0u8; size_info as usize];
184            reader.read_exact_raw(&mut crypt_buf)?;
185            let mut read_buffer = RefReadBuffer::new(&crypt_buf);
186            let mut buffer = [0; 16];
187            let mut write_buffer = RefWriteBuffer::new(&mut buffer);
188            let mut decrypted_info: Vec<u8> = vec![];
189            loop {
190                let result = reader.dec.decrypt(&mut read_buffer, &mut write_buffer, true) .map_err(|e| Error::new(ErrorKind::Other, format!("info decryption error: {:?}", e)))?;
191
192                decrypted_info.append(
193                    &mut write_buffer
194                        .take_read_buffer()
195                        .take_remaining()
196                        .iter()
197                        .map(|&i| i.clone()).collect::<Vec<u8>>(),
198                );
199                match result {
200                    BufferResult::BufferUnderflow => break,
201                    BufferResult::BufferOverflow => {}
202                }
203            }
204            reader.dec.reset(&iv);
205            Some(String::from_utf8(decrypted_info).unwrap_or("".to_owned()))
206        };
207        
208
209
210
211        Ok(CryptoInfo {
212            thumb,
213            mime: if file_mime == "" {
214                None
215            } else {
216                Some(file_mime)
217            },
218            thumb_mime: if thumb_mime == "" {
219                None
220            } else {
221                Some(thumb_mime)
222            },
223            info,
224        })
225    }
226
227}
228
229
230pub fn get_encrypted_size(size: u64) -> u64 {
231    size + (16 - size % 16)
232} 
233
234
235pub fn random_iv(block_size: Option<usize>) -> Vec<u8> {
236    let mut iv = vec![0u8; block_size.unwrap_or(16)];
237    OsRng.fill_bytes(&mut iv);
238    iv
239} 
240
241pub fn random_iv_for_encryptor<E: BlockEncryptor>(enc: E) -> Vec<u8> {
242    let mut iv = vec![0u8; enc.block_size()];
243    OsRng.fill_bytes(&mut iv);
244    iv
245} 
246
247pub fn derive_key(password: &str, salt: &[u8]) -> [u8; KEY_SIZE] {
248    let mut dk = [0u8; KEY_SIZE]; // derived key
249    let mut mac = Hmac::new(Sha1::new(), password.as_bytes());
250    pbkdf2::pbkdf2(&mut mac, salt, 1000, &mut dk);
251    dk
252}
253
254pub struct AesWriter<E: BlockEncryptor, W: Write> {
255    /// Writer to write encrypted data to
256    writer: Option<W>,
257    /// Encryptor to encrypt data with
258    pub enc: CbcEncryptor<E, EncPadding<PkcsPadding>>,
259    /// Indicates weather the encryptor has done its final operation (inserting padding)
260    closed: bool,
261}
262
263impl<E: BlockEncryptor, W: Write> AesWriter<E, W> {
264    //! If you don't want the header you can use this initializer
265    pub fn new(iv: Vec<u8>, mut writer: W, enc: E) -> Result<AesWriter<E, W>> {
266        writer.write_all(&iv)?;
267        Ok(AesWriter {
268            writer: Some(writer),
269            enc: CbcEncryptor::new(enc, PkcsPadding, iv),
270            closed: false,
271        })
272    }
273
274    /// Initializer that will store info in the file. You muse use the AesReader::new_with_info to decrypt this kind of file
275    pub fn new_with_infos(iv: Vec<u8>, infos: CryptoInfo, mut writer: W, enc: E) -> Result<AesWriter<E, W>> {
276        writer.write_all(&iv)?;
277        
278        let mut aes_writer = AesWriter {
279            writer: Some(writer),
280            enc: CbcEncryptor::new(enc, PkcsPadding, iv.clone()),
281            closed: false,
282        };
283
284        infos.write(&mut aes_writer, &iv)?;
285
286
287        Ok(aes_writer)
288    }
289
290    /// Encrypts passed buffer and writes all resulting encrypted blocks to the underlying writer
291    ///
292    /// # Parameters
293    ///
294    /// * **buf**: Plaintext to encrypt and write
295    /// * **eof**: If the provided buf is the last one to come and therefore encryption should be
296    ///     finished and padding added.
297    fn encrypt_write(&mut self, buf: &[u8], eof: bool) -> Result<usize> {
298        let mut read_buf = RefReadBuffer::new(buf);
299        let mut out = [0u8; BUFFER_SIZE];
300        let mut write_buf = RefWriteBuffer::new(&mut out);
301        loop {
302            let res = self.enc.encrypt(&mut read_buf, &mut write_buf, eof)
303                .map_err(|e| Error::new(ErrorKind::Other, format!("encryption error: {:?}", e)))?;
304            let mut enc = write_buf.take_read_buffer();
305            let enc = enc.take_remaining();
306            self.writer.as_mut().unwrap().write_all(enc)?;
307            match res {
308                BufferResult::BufferUnderflow => break,
309                BufferResult::BufferOverflow if eof =>
310                    panic!("read_buf underflow during encryption with eof"),
311                BufferResult::BufferOverflow => {},
312            }
313        }
314        // CbcEncryptor has its own internal buffer and always consumes all input
315        assert_eq!(read_buf.remaining(), 0);
316        Ok(buf.len())
317    }
318
319    pub fn write_direct(&mut self, buf: &[u8]) -> Result<usize> {
320        let written = self.writer.as_mut().unwrap().write(buf)?;
321        Ok(written)
322    }
323}
324
325impl<E: BlockEncryptor, W: Write> Write for AesWriter<E, W> {
326    /// Encrypts the passed buffer and writes the result to the underlying writer.
327    ///
328    /// Due to the blocksize of CBC not all data will be written instantaneously.
329    /// For example if 17 bytes are passed, the first 16 will be encrypted as one block and written
330    /// the underlying writer, but the last byte won't be encrypted and written yet.
331    ///
332    /// If [`flush`](#method.flush) has been called, this method will always return an error.
333    fn write(&mut self, buf: &[u8]) -> Result<usize> {
334        if self.closed {
335            return Err(Error::new(ErrorKind::Other, "AesWriter is closed"));
336        }
337        let written = self.encrypt_write(buf, false)?;
338        Ok(written)
339    }
340
341    /// Flush this output stream, ensuring that all intermediately buffered contents reach their destination.
342    /// [Read more](https://doc.rust-lang.org/nightly/|_| std/io/trait.Write.html#tymethod.flush)
343    ///
344    /// **Warning**: When this method is called, the encryption will finish and insert final padding.
345    /// After calling `flush`, this writer cannot be written to anymore and will always return an
346    /// error.
347    fn flush(&mut self) -> Result<()> {
348        if self.closed {
349            return Ok(());
350        }
351        self.encrypt_write(&[], true)?;
352        self.closed = true;
353        self.writer.as_mut().unwrap().flush()
354    }
355}
356
357impl<E: BlockEncryptor, W: Write> Drop for AesWriter<E, W> {
358    /// Drops this AesWriter trying to finish encryption and to write everything to the underlying writer.
359    fn drop(&mut self) {
360        if self.writer.is_some() {
361            if !std::thread::panicking() {
362                self.flush().unwrap();
363            } else {
364                let _ = self.flush();
365            }
366        }
367    }
368}
369
370pub struct AesReader<D: BlockDecryptor, R: Read> {
371    /// Reader to read encrypted data from
372    reader: R,
373    /// Decryptor to decrypt data with
374    pub dec: CbcDecryptor<D, DecPadding<PkcsPadding>>,
375    /// Block size of BlockDecryptor, needed when seeking to correctly seek to the nearest block
376    block_size: usize,
377    /// Buffer used to store blob needed to find out if we reached eof
378    buffer: Vec<u8>,
379    /// Indicates wheather eof of the underlying buffer was reached
380    eof: bool,
381}
382
383impl<D: BlockDecryptor, R: Read> AesReader<D, R> {
384    /// Creates a new AesReader.
385    ///
386    /// Assumes that the first block of given reader is the IV.
387    ///
388    /// # Parameters
389    ///
390    /// * **reader**: Reader to read encrypted data from
391    /// * **dec**: [`BlockDecryptor`][bd] to use for decyrption
392    ///
393    /// # Examples
394    ///
395    /// ```no_run
396    /// # extern crate crypto;
397    /// # extern crate rand;
398    /// # extern crate aesstream;
399    /// # use crypto::aessafe::AesSafe128Decryptor;
400    /// # use rand::{OsRng, Rng};
401    /// # use |_| std::io::Result;
402    /// # use |_| std::fs::File;
403    /// # use aesstream::AesReader;
404    /// # fn foo() -> Result<()> {
405    /// let key: [u8; 16] = OsRng::new()?.gen();
406    /// let decryptor = AesSafe128Decryptor::new(&key);
407    /// let file = File::open("...")?;
408    /// let mut reader = AesReader::new(file, decryptor)?;
409    /// # Ok(())
410    /// # }
411    /// # fn main() { let _ = foo(); }
412    /// ```
413    ///
414    /// [bd]: https://docs.rs/rust-crypto/0.2.36/crypto/symmetriccipher/trait.BlockDecryptor.html
415    pub fn new(mut reader: R, dec: D) -> Result<AesReader<D, R>> {
416        let mut iv = vec![0u8; dec.block_size()];
417        reader.read_exact(&mut iv)?;
418        Ok(AesReader {
419            reader: reader,
420            block_size: dec.block_size(),
421            dec: CbcDecryptor::new(dec, PkcsPadding, iv),
422            buffer: Vec::new(),
423            eof: false,
424        })
425    }
426
427    /// Will give you the decrypted infos and a Reader with decrypted data
428    pub fn new_with_infos(mut reader: R, dec: D) -> Result<(CryptoInfo, AesReader<D, R>)> {
429        let mut iv = vec![0u8; dec.block_size()];
430        reader.read_exact(&mut iv)?;
431        
432        let mut aes_reader = AesReader {
433            reader,
434            block_size: dec.block_size(),
435            dec: CbcDecryptor::new(dec, PkcsPadding, iv.clone()),
436            buffer: Vec::new(),
437            eof: false,
438        };
439
440        let infos = CryptoInfo::from_reader(&mut aes_reader, &iv)?;
441
442        Ok((infos, aes_reader))
443    }
444
445    /// Reads at max BUFFER_SIZE bytes, handles potential eof and returns the buffer as Vec<u8>
446    fn fill_buf(&mut self) -> Result<Vec<u8>> {
447        let mut eof_buffer = vec![0u8; BUFFER_SIZE];
448        let read = self.reader.read(&mut eof_buffer)?;
449        self.eof = read == 0;
450        eof_buffer.truncate(read);
451        Ok(eof_buffer)
452    }
453
454    /// Reads and decrypts data from the underlying stream and writes it into the passed buffer.
455    ///
456    /// The CbcDecryptor has an internal output buffer, but not an input buffer.
457    /// Therefore, we need to take care of letfover input.
458    /// Additionally, we need to handle eof correctly, as CbcDecryptor needs to correctly interpret
459    /// padding.
460    /// Thus, we need to read 2 buffers. The first one is read as input for decryption and the second
461    /// one to determine if eof is reached.
462    /// The next time this function is called, the second buffer is passed as input into decryption
463    /// and the first buffer is filled to find out if we reached eof.
464    ///
465    /// # Parameters
466    ///
467    /// * **buf**: Buffer to write decrypted data into.
468    fn read_decrypt(&mut self, buf: &mut [u8]) -> Result<usize> {
469        // if this is the first iteration, fill internal buffer
470        if self.buffer.is_empty() && !self.eof {
471            self.buffer = self.fill_buf()?;
472        }
473
474        let buf_len = buf.len();
475        let mut write_buf = RefWriteBuffer::new(buf);
476        let res;
477        let remaining;
478        {
479            let mut read_buf = RefReadBuffer::new(&self.buffer);
480
481            // test if CbcDecryptor still has enough decrypted data or we have enough buffered
482            res = self.dec.decrypt(&mut read_buf, &mut write_buf, self.eof)
483                .map_err(|e| Error::new(ErrorKind::Other, format!("decryption error: {:?}", e)))?;
484            remaining = read_buf.remaining();
485        }
486        // keep remaining bytes
487        let len = self.buffer.len();
488        self.buffer.drain(..(len - remaining));
489        // if we were able to decrypt, return early
490        match res {
491            BufferResult::BufferOverflow => return Ok(buf_len),
492            BufferResult::BufferUnderflow if self.eof => return Ok(write_buf.position()),
493            _ => {}
494        }
495
496        // else read new buffer
497        let mut dec_len = 0;
498        // We must return something, if we have something.
499        // If the reader doesn't return enough so that we can decrypt a block, we need to continue
500        // reading until we have enough data to return one decrypted block, or until we reach eof.
501        // If we reach eof, we will be able to decrypt the final block because of padding.
502        while dec_len == 0 && !self.eof {
503            let eof_buffer = self.fill_buf()?;
504            let remaining;
505            {
506                let mut read_buf = RefReadBuffer::new(&self.buffer);
507                self.dec.decrypt(&mut read_buf, &mut write_buf, self.eof)
508                    .map_err(|e| Error::new(ErrorKind::Other, format!("decryption error: {:?}", e)))?;
509                let mut dec = write_buf.take_read_buffer();
510                let dec = dec.take_remaining();
511                dec_len = dec.len();
512                remaining = read_buf.remaining();
513            }
514            // keep remaining bytes
515            let len = self.buffer.len();
516            self.buffer.drain(..(len - remaining));
517            // append newly read bytes
518            self.buffer.extend(eof_buffer);
519        }
520        Ok(dec_len)
521    }
522
523    fn read_exact_raw(&mut self, mut buf: &mut [u8]) -> Result<()> {
524        self.reader.read_exact(&mut buf)
525    }
526
527}
528impl<D: BlockDecryptor, R: Read + Seek> AesReader<D, R> {
529    /// Seeks to *offset* from the start of the file
530    fn seek_from_start(&mut self, offset: u64) -> Result<u64> {
531        let block_num = offset / self.block_size as u64;
532        let block_offset = offset % self.block_size as u64;
533        // reset CbcDecryptor
534        self.reader.seek(SeekFrom::Start((block_num - 1) * self.block_size as u64))?;
535        let mut iv = vec![0u8; self.block_size];
536        self.reader.read_exact(&mut iv)?;
537        self.dec.reset(&iv);
538        self.buffer = Vec::new();
539        self.eof = false;
540        let mut skip = vec![0u8; block_offset as usize];
541        self.read_exact(&mut skip)?;
542        // subtract IV
543        Ok(offset - 16)
544    }
545}
546
547impl<D: BlockDecryptor, R: Read> Read for AesReader<D, R> {
548    /// Reads encrypted data from the underlying reader, decrypts it and writes the result into the
549    /// passed buffer.
550    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
551        let read = self.read_decrypt(buf)?;
552        Ok(read)
553    }
554}
555
556impl<D: BlockDecryptor, R: Read + Seek> Seek for AesReader<D, R> {
557    /// Seek to an offset, in bytes, in a stream.
558    /// [Read more](https://doc.rust-lang.org/nightly/|_| std/io/trait.Seek.html#tymethod.seek)
559    ///
560    /// When seeking, this reader takes care of reinitializing the CbcDecryptor with the correct IV.
561    /// The passed position does *not* need to be aligned to the blocksize.
562    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
563        match pos {
564            SeekFrom::Start(offset) => {
565                // +16 because first block is the iv
566                self.seek_from_start(offset + 16)
567            },
568            SeekFrom::End(_) | SeekFrom::Current(_) => {
569                let pos = self.reader.seek(pos)?;
570                self.seek_from_start(pos)
571            },
572        }
573    }
574}
575
576
577
578#[cfg(test)]
579mod tests {
580    use std::{fs::{remove_file, File}, io::copy, path::PathBuf, str::FromStr};
581
582    use crypto::aessafe::{AesSafe256Decryptor, AesSafe256Encryptor};
583    use base64::{engine::general_purpose::URL_SAFE, Engine as _};
584    use super::*;
585  
586
587    const SALT: &str = "e5709660b22ab0803630cb963f703b83";
588
589
590    #[test]
591    fn encrypted_size() {
592        let r = get_encrypted_size(8);
593        assert_eq!(r, 16);
594
595        let r = get_encrypted_size(29);
596        assert_eq!(r, 32);
597    }
598
599
600    #[test]
601    fn encrypted_info() {
602        let info = CryptoInfo {
603            thumb: Some(random_iv(Some(145))),
604            mime: Some("video/quicktime-mov".to_owned()),
605            thumb_mime: Some("image/jpeg".to_owned()),
606            info: Some("{JSONEXEMPLE====}".to_owned()),
607        };
608
609        assert_eq!(info.mime_as_bytes().len(), 256, "Mime must be 256 bytes");
610        assert_eq!(info.thumb_mime_as_bytes().len(), 32, "Thumb Mime must be 32 bytes");
611
612
613        let expected = 4 + 4 + 32 + 256 + 160 + 32;
614        assert_eq!(info.size(), expected);
615
616        let expected = 16 + 4 + 4 + 32 + 256 + 160 + 32;
617        assert_eq!(info.size_with_iv(), expected);
618
619        let expected = 160 + 32;
620        assert_eq!(info.data_size(), expected);
621
622    }
623
624    #[test]
625    fn encrypt() -> Result<()> {
626        let test_path = PathBuf::from_str("test_data/test").unwrap();
627        if test_path.exists() {
628            remove_file(&test_path)?;
629        }
630
631        let salt = URL_SAFE.decode(SALT).unwrap();
632        let key = derive_key("test password", &salt);
633        let iv = random_iv(None);
634
635        {
636            let writer = File::create(&test_path)?;
637            let encryptor = AesSafe256Encryptor::new(&key);
638            let mut aes_writer = AesWriter::new(iv, writer, encryptor)?;
639            aes_writer.encrypt_write("test encrypted".as_bytes(), true)?;
640        }
641        {
642            let reader = File::open(&test_path)?;
643            let decryptor = AesSafe256Decryptor::new(&key);
644    
645            let mut aes_reader = AesReader::new(reader, decryptor)?;
646            let mut decrypted = String::new();
647            aes_reader.read_to_string(&mut decrypted)?;
648
649            assert_eq!(decrypted, "test encrypted", "Decrypted different than encprypted");
650        }
651        Ok(())
652    }
653
654
655    #[test]
656    fn encrypt_with_infos() -> Result<()> {
657        let infos = CryptoInfo {
658            thumb: Some(random_iv(Some(145))),
659            mime: Some("video/quicktime-mov".to_owned()),
660            thumb_mime: Some("image/jpeg".to_owned()),
661            info: Some("{JSONEXEMPLE====}".to_owned()),
662        };
663
664
665        let test_path = PathBuf::from_str("test_data/test_infos").unwrap();
666        if test_path.exists() {
667            remove_file(&test_path)?;
668        }
669
670        let salt = URL_SAFE.decode(SALT).unwrap();
671        let key = derive_key("test password", &salt);
672        let iv = random_iv(None);
673
674        {
675            let writer = File::create(&test_path)?;
676            let encryptor = AesSafe256Encryptor::new(&key);
677            let mut aes_writer = AesWriter::new_with_infos(iv, infos.clone(), writer, encryptor)?;
678            aes_writer.encrypt_write("test encrypted".as_bytes(), true)?;
679        }
680        {
681            let reader = File::open(&test_path)?;
682            let decryptor = AesSafe256Decryptor::new(&key);
683    
684            let (dec_infos ,mut aes_reader) = AesReader::new_with_infos(reader, decryptor)?;
685            let mut decrypted = String::new();
686            assert_eq!(infos, dec_infos, "infos different than initial infos");
687            aes_reader.read_to_string(&mut decrypted)?;
688            assert_eq!(decrypted, "test encrypted", "Decrypted different than encprypted");
689        }
690        Ok(())
691    }
692
693/* 
694    #[test]
695    fn decrypt_file() -> Result<()> {
696        let test_path = PathBuf::from_str("test_data/file").unwrap();
697    
698        let reader = File::open(&test_path)?;
699        let salt = URL_SAFE.decode(SALT).unwrap();
700        let key = derive_key("XXXXXX", &salt);
701
702        let decryptor = AesSafe256Decryptor::new(&key);
703
704        let (dec_infos ,mut aes_reader) = AesReader::new_with_infos(reader, decryptor)?;
705        println!("INfos: {:?}", dec_infos);
706        
707        let output_path = PathBuf::from_str("test_data/file.heic").unwrap();
708        if output_path.exists() {
709            remove_file(&output_path)?;
710        }
711        let mut writer = File::create(output_path)?;
712
713        copy(&mut aes_reader, &mut writer)?;
714    
715        Ok(())
716    }
717    */
718}