From 048a48873ab04b96172eae2724ca61a47ccea828 Mon Sep 17 00:00:00 2001 From: Dennis Schwerdel Date: Fri, 9 Mar 2018 23:56:18 +0100 Subject: [PATCH] Refactor crypto --- src/cli/algotest.rs | 2 +- src/repository/backup.rs | 8 ++++---- src/repository/bundledb/db.rs | 10 +++++----- src/repository/bundledb/reader.rs | 18 ++++++------------ src/repository/bundledb/writer.rs | 12 ++++++------ src/repository/mod.rs | 14 +++++++------- src/util/encryption.rs | 28 ++++++++++++++-------------- 7 files changed, 43 insertions(+), 49 deletions(-) diff --git a/src/cli/algotest.rs b/src/cli/algotest.rs index be88f6b..fa85d73 100644 --- a/src/cli/algotest.rs +++ b/src/cli/algotest.rs @@ -187,7 +187,7 @@ pub fn run( println!(); let (public, secret) = Crypto::gen_keypair(); - let mut crypto = Crypto::dummy(); + let crypto = Crypto::dummy(); crypto.add_secret_key(public, secret); let encryption = (EncryptionMethod::Sodium, public[..].to_vec().into()); diff --git a/src/repository/backup.rs b/src/repository/backup.rs index 49d5b94..264e817 100644 --- a/src/repository/backup.rs +++ b/src/repository/backup.rs @@ -42,7 +42,7 @@ pub enum DiffType { impl Repository { pub fn get_all_backups(&self) -> Result, RepositoryError> { Ok(try!(Backup::get_all_from( - &self.crypto.lock().unwrap(), + &self.crypto, self.layout.backups_path() ))) } @@ -52,7 +52,7 @@ impl Repository { path: P, ) -> Result, RepositoryError> { Ok(try!(Backup::get_all_from( - &self.crypto.lock().unwrap(), + &self.crypto, self.layout.backups_path().join(path) ))) } @@ -64,7 +64,7 @@ impl Repository { pub fn get_backup(&self, name: &str) -> Result { Ok(try!(Backup::read_from( - &self.crypto.lock().unwrap(), + &self.crypto, self.layout.backup_path(name) ))) } @@ -74,7 +74,7 @@ impl Repository { let path = self.layout.backup_path(name); try!(fs::create_dir_all(path.parent().unwrap())); try!(backup.save_to( - &self.crypto.lock().unwrap(), + &self.crypto, self.config.encryption.clone(), path )); diff --git a/src/repository/bundledb/db.rs b/src/repository/bundledb/db.rs index 9ebb258..f7c7b9b 100644 --- a/src/repository/bundledb/db.rs +++ b/src/repository/bundledb/db.rs @@ -4,7 +4,7 @@ use super::*; use std::path::{Path, PathBuf}; use std::collections::{HashMap, HashSet}; use std::fs; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::io; use std::mem; use std::cmp::min; @@ -62,7 +62,7 @@ fn load_bundles( path: &Path, base: &Path, bundles: &mut HashMap, - crypto: Arc>, + crypto: Arc, ) -> Result<(Vec, Vec), BundleDbError> { let mut paths = vec![path.to_path_buf()]; let mut bundle_paths = HashSet::new(); @@ -119,7 +119,7 @@ fn load_bundles( pub struct BundleDb { pub layout: Arc, uploader: Option>, - crypto: Arc>, + crypto: Arc, local_bundles: HashMap, remote_bundles: HashMap, bundle_cache: LruCache)> @@ -127,7 +127,7 @@ pub struct BundleDb { impl BundleDb { - fn new(layout: Arc, crypto: Arc>) -> Self { + fn new(layout: Arc, crypto: Arc) -> Self { BundleDb { layout, crypto, @@ -240,7 +240,7 @@ impl BundleDb { pub fn open( layout: Arc, - crypto: Arc>, + crypto: Arc, online: bool ) -> Result<(Self, Vec, Vec), BundleDbError> { let mut self_ = Self::new(layout, crypto); diff --git a/src/repository/bundledb/reader.rs b/src/repository/bundledb/reader.rs index 6eef761..f4d33f7 100644 --- a/src/repository/bundledb/reader.rs +++ b/src/repository/bundledb/reader.rs @@ -6,7 +6,7 @@ use std::fs::{self, File}; use std::io::{self, Read, Seek, SeekFrom, BufReader}; use std::cmp::max; use std::fmt::{self, Debug}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; quick_error!{ @@ -60,7 +60,7 @@ pub struct BundleReader { pub info: BundleInfo, pub version: u8, pub path: PathBuf, - crypto: Arc>, + crypto: Arc, pub content_start: usize, pub chunks: Option, pub chunk_positions: Option> @@ -71,7 +71,7 @@ impl BundleReader { path: PathBuf, version: u8, content_start: usize, - crypto: Arc>, + crypto: Arc, info: BundleInfo, ) -> Self { BundleReader { @@ -93,7 +93,7 @@ impl BundleReader { #[allow(needless_pass_by_value)] fn load_header>( path: P, - crypto: Arc>, + crypto: Arc, ) -> Result<(BundleInfo, u8, usize), BundleReaderError> { let path = path.as_ref(); let mut file = BufReader::new(try!(File::open(path).context(path))); @@ -116,8 +116,6 @@ impl BundleReader { if let Some(ref encryption) = header.encryption { info_data = try!( crypto - .lock() - .unwrap() .decrypt(encryption, &info_data) .context(path) ); @@ -133,13 +131,13 @@ impl BundleReader { #[inline] pub fn load_info>( path: P, - crypto: Arc>, + crypto: Arc, ) -> Result { Self::load_header(path, crypto).map(|b| b.0) } #[inline] - pub fn load(path: PathBuf, crypto: Arc>) -> Result { + pub fn load(path: PathBuf, crypto: Arc) -> Result { let (header, version, content_start) = try!(Self::load_header(&path, crypto.clone())); Ok(BundleReader::new( path, @@ -170,8 +168,6 @@ impl BundleReader { if let Some(ref encryption) = self.info.encryption { chunk_data = try!( self.crypto - .lock() - .unwrap() .decrypt(encryption, &chunk_data) .context(&self.path as &Path) ); @@ -212,8 +208,6 @@ impl BundleReader { if let Some(ref encryption) = self.info.encryption { data = try!( self.crypto - .lock() - .unwrap() .decrypt(encryption, &data) .context(&self.path as &Path) ); diff --git a/src/repository/bundledb/writer.rs b/src/repository/bundledb/writer.rs index 41cccaa..15a919b 100644 --- a/src/repository/bundledb/writer.rs +++ b/src/repository/bundledb/writer.rs @@ -4,7 +4,7 @@ use super::*; use std::path::{Path, PathBuf}; use std::fs::File; use std::io::{self, Write, BufWriter}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use chrono::prelude::*; @@ -51,7 +51,7 @@ pub struct BundleWriter { compression: Option, compression_stream: Option, encryption: Option, - crypto: Arc>, + crypto: Arc, raw_size: usize, chunk_count: usize, chunks: ChunkList @@ -63,7 +63,7 @@ impl BundleWriter { hash_method: HashMethod, compression: Option, encryption: Option, - crypto: Arc>, + crypto: Arc, ) -> Result { let compression_stream = match compression { Some(ref compression) => Some(try!(compression.compress_stream().map_err( @@ -106,14 +106,14 @@ impl BundleWriter { )) } if let Some(ref encryption) = self.encryption { - self.data = try!(self.crypto.lock().unwrap().encrypt(encryption, &self.data)); + self.data = try!(self.crypto.encrypt(encryption, &self.data)); } let encoded_size = self.data.len(); let mut chunk_data = Vec::with_capacity(self.chunks.encoded_size()); self.chunks.write_to(&mut chunk_data).unwrap(); let id = BundleId(self.hash_method.hash(&chunk_data)); if let Some(ref encryption) = self.encryption { - chunk_data = try!(self.crypto.lock().unwrap().encrypt(encryption, &chunk_data)); + chunk_data = try!(self.crypto.encrypt(encryption, &chunk_data)); } let mut path = db.layout.temp_bundle_path(); let mut file = BufWriter::new(try!(File::create(&path).context(&path as &Path))); @@ -133,7 +133,7 @@ impl BundleWriter { }; 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)); + info_data = try!(self.crypto.encrypt(encryption, &info_data)); } let header = BundleHeader { encryption: self.encryption, diff --git a/src/repository/mod.rs b/src/repository/mod.rs index dcd793f..e2d02eb 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -20,7 +20,7 @@ use std::mem; use std::cmp::max; use std::path::Path; use std::fs::{self, File}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use std::os::unix::fs::symlink; use std::io::Write; @@ -74,10 +74,10 @@ impl index::Key for Hash { } pub struct Repository { - pub layout: Arc, + layout: Arc, pub config: Config, index: Index, - crypto: Arc>, + crypto: Arc, bundle_map: BundleMap, next_data_bundle: u32, next_meta_bundle: u32, @@ -133,7 +133,7 @@ impl Repository { try!(fs::create_dir_all(layout.local_locks_path())); // Added after v0.1.0 let local_locks = LockFolder::new(layout.local_locks_path()); let lock = try!(local_locks.lock(false)); - let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_path())))); + let crypto = Arc::new(try!(Crypto::open(layout.keys_path()))); let (bundles, new, gone) = try!(BundleDb::open(layout.clone(), crypto.clone(), online)); let (index, mut rebuild_index) = match unsafe { Index::open(layout.index_path(), &INDEX_MAGIC, INDEX_VERSION) } { @@ -225,7 +225,7 @@ impl Repository { ) -> Result { let mut repo = try!(Repository::create(layout.clone(), &Config::default(), remote)); for file in key_files { - try!(repo.crypto.lock().unwrap().register_keyfile(file)); + try!(repo.crypto.register_keyfile(file)); } repo = try!(Repository::open(layout, true)); let mut backups: Vec<(String, Backup)> = try!(repo.get_all_backups()).into_iter().collect(); @@ -249,7 +249,7 @@ impl Repository { secret: SecretKey, ) -> Result<(), RepositoryError> { try!(self.write_mode()); - try!(self.crypto.lock().unwrap().register_secret_key( + try!(self.crypto.register_secret_key( public, secret )); @@ -266,7 +266,7 @@ impl Repository { #[inline] pub fn set_encryption(&mut self, public: Option<&PublicKey>) { if let Some(key) = public { - if !self.crypto.lock().unwrap().contains_secret_key(key) { + if !self.crypto.contains_secret_key(key) { tr_warn!("The secret key for that public key is not stored in the repository.") } let mut key_bytes = Vec::new(); diff --git a/src/util/encryption.rs b/src/util/encryption.rs index 391f8a9..c3c25a1 100644 --- a/src/util/encryption.rs +++ b/src/util/encryption.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use std::io; use std::fs::{self, File}; -use std::sync::{Once, ONCE_INIT}; +use std::sync::{RwLock, Once, ONCE_INIT}; use serde_yaml; use serde_bytes::ByteBuf; @@ -116,7 +116,7 @@ impl KeyfileYaml { pub struct Crypto { path: Option, - keys: HashMap + keys: RwLock> } impl Crypto { @@ -125,7 +125,7 @@ impl Crypto { sodium_init(); Crypto { path: None, - keys: HashMap::new() + keys: RwLock::new(HashMap::new()) } } @@ -152,17 +152,17 @@ impl Crypto { } Ok(Crypto { path: Some(path), - keys + keys: RwLock::new(keys) }) } #[inline] - pub fn add_secret_key(&mut self, public: PublicKey, secret: SecretKey) { - self.keys.insert(public, secret); + pub fn add_secret_key(&self, public: PublicKey, secret: SecretKey) { + self.keys.write().expect("Lock poisoned").insert(public, secret); } #[inline] - pub fn register_keyfile>(&mut self, path: P) -> Result<(), EncryptionError> { + pub fn register_keyfile>(&self, path: P) -> Result<(), EncryptionError> { let (public, secret) = try!(Self::load_keypair_from_file(path)); self.register_secret_key(public, secret) } @@ -211,7 +211,7 @@ impl Crypto { #[inline] pub fn register_secret_key( - &mut self, + &self, public: PublicKey, secret: SecretKey, ) -> Result<(), EncryptionError> { @@ -219,17 +219,17 @@ impl Crypto { let path = path.join(to_hex(&public[..]) + ".yaml"); try!(Self::save_keypair_to_file(&public, &secret, path)); } - self.keys.insert(public, secret); + self.keys.write().expect("Lock poisoned").insert(public, secret); Ok(()) } #[inline] - pub fn contains_secret_key(&mut self, public: &PublicKey) -> bool { - self.keys.contains_key(public) + pub fn contains_secret_key(&self, public: &PublicKey) -> bool { + self.keys.read().expect("Lock poisoned").contains_key(public) } - fn get_secret_key(&self, public: &PublicKey) -> Result<&SecretKey, EncryptionError> { - self.keys.get(public).ok_or_else( + fn get_secret_key(&self, public: &PublicKey) -> Result { + self.keys.read().expect("Lock poisoned").get(public).cloned().ok_or_else( || EncryptionError::MissingKey(*public) ) } @@ -254,7 +254,7 @@ impl Crypto { let secret = try!(self.get_secret_key(&public)); match *method { EncryptionMethod::Sodium => { - sealedbox::open(data, &public, secret).map_err(|_| { + sealedbox::open(data, &public, &secret).map_err(|_| { EncryptionError::Operation(tr!("Decryption failed")) }) }