Read and encrypt whole file in-memory for now (due to lazy implementation problems)

This commit is contained in:
timvisee 2018-03-05 18:04:19 +01:00
parent 5d45cce720
commit 9753f1e3cc
No known key found for this signature in database
GPG key ID: 109CBA0BF74036C2

View file

@ -12,7 +12,6 @@ use std::fmt;
use std::fs::File; use std::fs::File;
use std::io::{self, Cursor, Read}; use std::io::{self, Cursor, Read};
use std::path::Path; use std::path::Path;
use std::sync::{Arc, Mutex};
use crypto::aead::AeadEncryptor; use crypto::aead::AeadEncryptor;
use crypto::aes::KeySize; use crypto::aes::KeySize;
@ -101,72 +100,56 @@ const TAG_LEN: usize = 16;
/// the raw cipher tag. /// the raw cipher tag.
/// ///
/// This reader is lazy, and reads/encrypts the file on the fly. /// This reader is lazy, and reads/encrypts the file on the fly.
struct EncryptedFileReaderTagged<'a> { ///
/// The file that is being read. /// TODO: the current implementation is not lazy
file: File, struct EncryptedFileReaderTagged {
/// A cursor that reads encrypted file data.
data: Cursor<Vec<u8>>,
/// The cipher to use. /// A tag cursor that reads the tag to append.
cipher: Arc<Mutex<AesGcm<'a>>>, tag: Cursor<Vec<u8>>,
/// The crypto tag.
tag: [u8; TAG_LEN],
/// A tag cursor, used as reader for the appended tag.
tag_cursor: Option<Cursor<Vec<u8>>>,
} }
impl<'a: 'static> EncryptedFileReaderTagged<'a> { impl EncryptedFileReaderTagged {
/// Construct a new reader. /// Construct a new reader.
// TODO: try to borrow here pub fn new(mut file: File, mut cipher: AesGcm<'static>) -> Self {
pub fn new(file: File, cipher: AesGcm<'a>) -> Self { // Get the file length
let len = file.metadata().unwrap().len() as usize;
// Create a file data buffer and an encrypted buffer
let mut data = Vec::with_capacity(len);
file.read_to_end(&mut data).unwrap();
let mut encrypted = vec![0u8; data.len()];
// Encrypt the data, get the tag
let mut tag = vec![0u8; TAG_LEN];
cipher.encrypt(&data, &mut encrypted, &mut tag);
// Construct the reader and return
EncryptedFileReaderTagged { EncryptedFileReaderTagged {
file, data: Cursor::new(encrypted),
cipher: Arc::new(Mutex::new(cipher)), tag: Cursor::new(tag),
tag: [0u8; TAG_LEN],
tag_cursor: None,
} }
} }
/// Get the length.
pub fn len(&self) -> Result<u64, io::Error> {
Ok(self.file.metadata()?.len() + TAG_LEN as u64)
}
} }
impl<'a: 'static> Read for EncryptedFileReaderTagged<'a> { impl Read for EncryptedFileReaderTagged {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> { fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
// Create a buffer with the same size, for the raw data // Read the data if we haven't started with the tag yet
let mut raw = vec![0u8; buf.len()]; if self.tag.position() == 0 {
// Read and return if something was read
// Read from the file let result = self.data.read(buf);
let len = self.file.read(&mut raw)?; match result {
Ok(len) if len > 0 => return result,
// Encrypt the read data _ => {},
if len > 0 {
// Lock the cipher mutex
let mut cipher = self.cipher.lock().unwrap();
// Encrypt the raw slice, put it into the user buffer
println!("DEBUG: Tag (from): {:?}", self.tag);
cipher.encrypt(&raw[..len], buf, &mut self.tag);
println!("DEBUG: Tag (to): {:?}", self.tag);
Ok(len)
} else {
// Initialise the tag cursor
if self.tag_cursor.is_none() {
self.tag_cursor = Some(Cursor::new(self.tag.to_vec()));
} }
// Read from the tag cursor
self.tag_cursor.as_mut().unwrap().read(buf)
} }
// Read the tag if it's empty
self.tag.read(buf)
} }
} }
// TODO: do not implement, make the reader send!
unsafe impl<'a: 'static> ::std::marker::Send for EncryptedFileReaderTagged<'a> {}
#[derive(Clone)] #[derive(Clone)]
struct XFileMetadata { struct XFileMetadata {
/// The metadata, as a base64 encoded string. /// The metadata, as a base64 encoded string.
@ -190,7 +173,7 @@ impl Header for XFileMetadata {
"X-File-Metadata" "X-File-Metadata"
} }
fn parse_header(raw: &Raw) -> Result<Self, HyperError> { fn parse_header(_raw: &Raw) -> Result<Self, HyperError> {
// TODO: implement this some time // TODO: implement this some time
unimplemented!(); unimplemented!();
} }