Refactor crypto

This commit is contained in:
Dennis Schwerdel 2018-03-09 23:56:18 +01:00
parent ca1916145f
commit 048a48873a
7 changed files with 43 additions and 49 deletions

View File

@ -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());

View File

@ -42,7 +42,7 @@ pub enum DiffType {
impl Repository {
pub fn get_all_backups(&self) -> Result<HashMap<String, Backup>, 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<HashMap<String, Backup>, 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<Backup, RepositoryError> {
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
));

View File

@ -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<BundleId, StoredBundle>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
) -> Result<(Vec<StoredBundle>, Vec<StoredBundle>), 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<ChunkRepositoryLayout>,
uploader: Option<Arc<BundleUploader>>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
local_bundles: HashMap<BundleId, StoredBundle>,
remote_bundles: HashMap<BundleId, StoredBundle>,
bundle_cache: LruCache<BundleId, (BundleReader, Vec<u8>)>
@ -127,7 +127,7 @@ pub struct BundleDb {
impl BundleDb {
fn new(layout: Arc<ChunkRepositoryLayout>, crypto: Arc<Mutex<Crypto>>) -> Self {
fn new(layout: Arc<ChunkRepositoryLayout>, crypto: Arc<Crypto>) -> Self {
BundleDb {
layout,
crypto,
@ -240,7 +240,7 @@ impl BundleDb {
pub fn open(
layout: Arc<ChunkRepositoryLayout>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
online: bool
) -> Result<(Self, Vec<BundleInfo>, Vec<BundleInfo>), BundleDbError> {
let mut self_ = Self::new(layout, crypto);

View File

@ -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<Mutex<Crypto>>,
crypto: Arc<Crypto>,
pub content_start: usize,
pub chunks: Option<ChunkList>,
pub chunk_positions: Option<Vec<usize>>
@ -71,7 +71,7 @@ impl BundleReader {
path: PathBuf,
version: u8,
content_start: usize,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
info: BundleInfo,
) -> Self {
BundleReader {
@ -93,7 +93,7 @@ impl BundleReader {
#[allow(needless_pass_by_value)]
fn load_header<P: AsRef<Path>>(
path: P,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
) -> 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<P: AsRef<Path>>(
path: P,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<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> {
pub fn load(path: PathBuf, crypto: Arc<Crypto>) -> Result<Self, BundleReaderError> {
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)
);

View File

@ -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>,
compression_stream: Option<CompressionStream>,
encryption: Option<Encryption>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
raw_size: usize,
chunk_count: usize,
chunks: ChunkList
@ -63,7 +63,7 @@ impl BundleWriter {
hash_method: HashMethod,
compression: Option<Compression>,
encryption: Option<Encryption>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
) -> Result<Self, BundleWriterError> {
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,

View File

@ -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<ChunkRepositoryLayout>,
layout: Arc<ChunkRepositoryLayout>,
pub config: Config,
index: Index<Hash, Location>,
crypto: Arc<Mutex<Crypto>>,
crypto: Arc<Crypto>,
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<Self, RepositoryError> {
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();

View File

@ -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<PathBuf>,
keys: HashMap<PublicKey, SecretKey>
keys: RwLock<HashMap<PublicKey, SecretKey>>
}
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<P: AsRef<Path>>(&mut self, path: P) -> Result<(), EncryptionError> {
pub fn register_keyfile<P: AsRef<Path>>(&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<SecretKey, EncryptionError> {
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"))
})
}