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#[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 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 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]; 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: Option<W>,
257 pub enc: CbcEncryptor<E, EncPadding<PkcsPadding>>,
259 closed: bool,
261}
262
263impl<E: BlockEncryptor, W: Write> AesWriter<E, W> {
264 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 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 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 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 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 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 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: R,
373 pub dec: CbcDecryptor<D, DecPadding<PkcsPadding>>,
375 block_size: usize,
377 buffer: Vec<u8>,
379 eof: bool,
381}
382
383impl<D: BlockDecryptor, R: Read> AesReader<D, R> {
384 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 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 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 fn read_decrypt(&mut self, buf: &mut [u8]) -> Result<usize> {
469 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 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 let len = self.buffer.len();
488 self.buffer.drain(..(len - remaining));
489 match res {
491 BufferResult::BufferOverflow => return Ok(buf_len),
492 BufferResult::BufferUnderflow if self.eof => return Ok(write_buf.position()),
493 _ => {}
494 }
495
496 let mut dec_len = 0;
498 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 let len = self.buffer.len();
516 self.buffer.drain(..(len - remaining));
517 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 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 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 Ok(offset - 16)
544 }
545}
546
547impl<D: BlockDecryptor, R: Read> Read for AesReader<D, R> {
548 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 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
563 match pos {
564 SeekFrom::Start(offset) => {
565 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}