Read and encrypt whole file in-memory for now (due to lazy implementation problems)
This commit is contained in:
parent
5d45cce720
commit
9753f1e3cc
1 changed files with 36 additions and 53 deletions
89
src/main.rs
89
src/main.rs
|
@ -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!();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue