Encrypted bundle info

This commit is contained in:
Dennis Schwerdel 2017-04-03 07:57:58 +02:00
parent 014c456fd0
commit 883c4c1c24
5 changed files with 44 additions and 20 deletions

View File

@ -103,10 +103,6 @@ Recommended: Brotli/2-7
- File attributes
- xattrs https://crates.io/crates/xattr
### Formats
- Bundles
- Encrypted bundle header
### CLI functionality
- list --tree

View File

@ -66,7 +66,7 @@ pub fn bundle_path(bundle: &BundleId, mut folder: PathBuf, mut count: usize) ->
(folder, file.into())
}
pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, StoredBundle>) -> Result<(Vec<StoredBundle>, Vec<StoredBundle>), BundleDbError> {
pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, StoredBundle>, crypto: Arc<Mutex<Crypto>>) -> Result<(Vec<StoredBundle>, Vec<StoredBundle>), BundleDbError> {
let mut paths = vec![path.as_ref().to_path_buf()];
let mut bundle_paths = HashSet::new();
while let Some(path) = paths.pop() {
@ -91,7 +91,7 @@ pub fn load_bundles<P: AsRef<Path>>(path: P, bundles: &mut HashMap<BundleId, Sto
let mut new = vec![];
for path in bundle_paths {
let bundle = StoredBundle {
info: try!(BundleReader::load_info(&path)),
info: try!(BundleReader::load_info(&path, crypto.clone())),
path: path
};
let id = bundle.info.id.clone();
@ -149,12 +149,12 @@ impl BundleDb {
self.remote_bundles.insert(bundle.id(), bundle);
}
}
let (new, gone) = try!(load_bundles(&self.local_bundles_path, &mut self.local_bundles));
let (new, gone) = try!(load_bundles(&self.local_bundles_path, &mut self.local_bundles, self.crypto.clone()));
if !new.is_empty() || !gone.is_empty() {
let bundles: Vec<_> = self.local_bundles.values().cloned().collect();
try!(StoredBundle::save_list_to(&bundles, &local_cache_path));
}
let (new, gone) = try!(load_bundles(&self.remote_path, &mut self.remote_bundles));
let (new, gone) = try!(load_bundles(&self.remote_path, &mut self.remote_bundles, self.crypto.clone()));
if !new.is_empty() || !gone.is_empty() {
let bundles: Vec<_> = self.remote_bundles.values().cloned().collect();
try!(StoredBundle::save_list_to(&bundles, &remote_cache_path));

View File

@ -71,6 +71,17 @@ serde_impl!(BundleMode(u8) {
});
#[derive(Default, Debug, Clone)]
pub struct BundleHeader {
pub encryption: Option<Encryption>,
pub info_size: usize
}
serde_impl!(BundleHeader(u8) {
encryption: Option<Encryption> => 0,
info_size: usize => 1
});
#[derive(Clone)]
pub struct BundleInfo {
pub id: BundleId,
@ -87,7 +98,7 @@ serde_impl!(BundleInfo(u64?) {
id: BundleId => 0,
mode: BundleMode => 1,
compression: Option<Compression> => 2,
encryption: Option<Encryption> => 3,
//encryption: already in the header
hash_method: HashMethod => 4,
raw_size: usize => 6,
encoded_size: usize => 7,

View File

@ -84,7 +84,7 @@ impl BundleReader {
self.info.id.clone()
}
fn load_header<P: AsRef<Path>>(path: P) -> Result<(BundleInfo, u8, usize), BundleReaderError> {
fn load_header<P: AsRef<Path>>(path: P, crypto: Arc<Mutex<Crypto>>) -> Result<(BundleInfo, u8, usize), BundleReaderError> {
let path = path.as_ref();
let mut file = BufReader::new(try!(File::open(path).context(path)));
let mut header = [0u8; 8];
@ -96,20 +96,28 @@ impl BundleReader {
if version != HEADER_VERSION {
return Err(BundleReaderError::UnsupportedVersion(path.to_path_buf(), version))
}
let header: BundleInfo = try!(msgpack::decode_from_stream(&mut file).context(path));
debug!("Load bundle {}", header.id);
let content_start = file.seek(SeekFrom::Current(0)).unwrap() as usize + header.chunk_info_size;
Ok((header, version, content_start))
let header: BundleHeader = try!(msgpack::decode_from_stream(&mut file).context(path));
let mut info_data = Vec::with_capacity(header.info_size);
info_data.resize(header.info_size, 0);
try!(file.read_exact(&mut info_data).context(path));
if let Some(ref encryption) = header.encryption {
info_data = try!(crypto.lock().unwrap().decrypt(&encryption, &info_data).context(path));
}
let mut info: BundleInfo = try!(msgpack::decode(&info_data).context(path));
info.encryption = header.encryption;
debug!("Load bundle {}", info.id);
let content_start = file.seek(SeekFrom::Current(0)).unwrap() as usize + info.chunk_info_size;
Ok((info, version, content_start))
}
#[inline]
pub fn load_info<P: AsRef<Path>>(path: P) -> Result<BundleInfo, BundleReaderError> {
Self::load_header(path).map(|b| b.0)
pub fn load_info<P: AsRef<Path>>(path: P, crypto: Arc<Mutex<Crypto>>) -> Result<BundleInfo, BundleReaderError> {
Self::load_header(path, crypto).map(|b| b.0)
}
#[inline]
pub fn load(path: PathBuf, crypto: Arc<Mutex<Crypto>>) -> Result<Self, BundleReaderError> {
let (header, version, content_start) = try!(Self::load_header(&path));
let (header, version, content_start) = try!(Self::load_header(&path, crypto.clone()));
Ok(BundleReader::new(path, version, content_start, crypto, header))
}

View File

@ -105,21 +105,30 @@ impl BundleWriter {
let mut file = BufWriter::new(try!(File::create(&path).context(&path as &Path)));
try!(file.write_all(&HEADER_STRING).context(&path as &Path));
try!(file.write_all(&[HEADER_VERSION]).context(&path as &Path));
let header = BundleInfo {
let info = BundleInfo {
mode: self.mode,
hash_method: self.hash_method,
compression: self.compression,
encryption: self.encryption,
encryption: self.encryption.clone(),
chunk_count: self.chunk_count,
id: id.clone(),
raw_size: self.raw_size,
encoded_size: encoded_size,
chunk_info_size: chunk_data.len()
};
let mut info_data = try!(msgpack::encode(&info).context(&path as &Path));
if let Some(ref encryption) = self.encryption {
info_data = try!(self.crypto.lock().unwrap().encrypt(&encryption, &info_data));
}
let header = BundleHeader {
encryption: self.encryption,
info_size: info_data.len()
};
try!(msgpack::encode_to_stream(&header, &mut file).context(&path as &Path));
try!(file.write_all(&info_data).context(&path as &Path));
try!(file.write_all(&chunk_data).context(&path as &Path));
try!(file.write_all(&self.data).context(&path as &Path));
Ok(StoredBundle { path: path, info: header })
Ok(StoredBundle { path: path, info: info })
}
#[inline]