From 883c4c1c248aef4ed0c1baf9c2927ca808c044dc Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Mon, 3 Apr 2017 07:57:58 +0200 Subject: [PATCH] Encrypted bundle info --- README.md | 4 ---- src/bundledb/db.rs | 8 ++++---- src/bundledb/mod.rs | 13 ++++++++++++- src/bundledb/reader.rs | 24 ++++++++++++++++-------- src/bundledb/writer.rs | 15 ++++++++++++--- 5 files changed, 44 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 54fd034..8d3a494 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/src/bundledb/db.rs b/src/bundledb/db.rs index ab56f22..fe66537 100644 --- a/src/bundledb/db.rs +++ b/src/bundledb/db.rs @@ -66,7 +66,7 @@ pub fn bundle_path(bundle: &BundleId, mut folder: PathBuf, mut count: usize) -> (folder, file.into()) } -pub fn load_bundles>(path: P, bundles: &mut HashMap) -> Result<(Vec, Vec), BundleDbError> { +pub fn load_bundles>(path: P, bundles: &mut HashMap, crypto: Arc>) -> Result<(Vec, Vec), 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>(path: P, bundles: &mut HashMap = 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)); diff --git a/src/bundledb/mod.rs b/src/bundledb/mod.rs index ebe15c2..c48c046 100644 --- a/src/bundledb/mod.rs +++ b/src/bundledb/mod.rs @@ -71,6 +71,17 @@ serde_impl!(BundleMode(u8) { }); +#[derive(Default, Debug, Clone)] +pub struct BundleHeader { + pub encryption: Option, + pub info_size: usize +} +serde_impl!(BundleHeader(u8) { + encryption: Option => 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 => 2, - encryption: Option => 3, + //encryption: already in the header hash_method: HashMethod => 4, raw_size: usize => 6, encoded_size: usize => 7, diff --git a/src/bundledb/reader.rs b/src/bundledb/reader.rs index de2162d..98dcbfd 100644 --- a/src/bundledb/reader.rs +++ b/src/bundledb/reader.rs @@ -84,7 +84,7 @@ impl BundleReader { self.info.id.clone() } - fn load_header>(path: P) -> Result<(BundleInfo, u8, usize), BundleReaderError> { + fn load_header>(path: P, crypto: Arc>) -> 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>(path: P) -> Result { - Self::load_header(path).map(|b| b.0) + pub fn load_info>(path: P, crypto: Arc>) -> Result { + Self::load_header(path, crypto).map(|b| b.0) } #[inline] pub fn load(path: PathBuf, crypto: Arc>) -> Result { - 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)) } diff --git a/src/bundledb/writer.rs b/src/bundledb/writer.rs index 8f3b07b..86ea5df 100644 --- a/src/bundledb/writer.rs +++ b/src/bundledb/writer.rs @@ -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]