work in progress
This commit is contained in:
		
							parent
							
								
									482292551b
								
							
						
					
					
						commit
						734652d913
					
				@ -425,17 +425,17 @@ enum KeyFileLoadError {
 | 
				
			|||||||
pub struct KeyDirectory {
 | 
					pub struct KeyDirectory {
 | 
				
			||||||
	/// Directory path for key management.
 | 
						/// Directory path for key management.
 | 
				
			||||||
	path: String,
 | 
						path: String,
 | 
				
			||||||
	cache: HashMap<Uuid, KeyFileContent>,
 | 
						cache: RefCell<HashMap<Uuid, KeyFileContent>>,
 | 
				
			||||||
	cache_usage: VecDeque<Uuid>,
 | 
						cache_usage: RefCell<VecDeque<Uuid>>,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl KeyDirectory {
 | 
					impl KeyDirectory {
 | 
				
			||||||
	/// Initializes new cache directory context with a given `path`
 | 
						/// Initializes new cache directory context with a given `path`
 | 
				
			||||||
	pub fn new(path: &Path) -> KeyDirectory {
 | 
						pub fn new(path: &Path) -> KeyDirectory {
 | 
				
			||||||
		KeyDirectory {
 | 
							KeyDirectory {
 | 
				
			||||||
			cache: HashMap::new(),
 | 
								cache: RefCell::new(HashMap::new()),
 | 
				
			||||||
			path: path.to_str().expect("Initialized key directory with empty path").to_owned(),
 | 
								path: path.to_str().expect("Initialized key directory with empty path").to_owned(),
 | 
				
			||||||
			cache_usage: VecDeque::new(),
 | 
								cache_usage: RefCell::new(VecDeque::new()),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -448,25 +448,34 @@ impl KeyDirectory {
 | 
				
			|||||||
			let json_bytes = json_text.into_bytes();
 | 
								let json_bytes = json_text.into_bytes();
 | 
				
			||||||
			try!(file.write(&json_bytes));
 | 
								try!(file.write(&json_bytes));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							let mut cache = self.cache.borrow_mut();
 | 
				
			||||||
		let id = key_file.id.clone();
 | 
							let id = key_file.id.clone();
 | 
				
			||||||
		self.cache.insert(id.clone(), key_file);
 | 
							cache.insert(id.clone(), key_file);
 | 
				
			||||||
		Ok(id.clone())
 | 
							Ok(id.clone())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Returns key given by id if corresponding file exists and no load error occured.
 | 
						/// Returns key given by id if corresponding file exists and no load error occured.
 | 
				
			||||||
	/// Warns if any error occured during the key loading
 | 
						/// Warns if any error occured during the key loading
 | 
				
			||||||
	pub fn get(&mut self, id: &Uuid) -> Option<&KeyFileContent> {
 | 
						pub fn get(&self, id: &Uuid) -> Option<Ref<KeyFileContent>> {
 | 
				
			||||||
		let path = self.key_path(id);
 | 
							let path = self.key_path(id);
 | 
				
			||||||
		self.cache_usage.push_back(id.clone());
 | 
							{
 | 
				
			||||||
		Some(self.cache.entry(id.to_owned()).or_insert(
 | 
								let mut usage = self.cache_usage.borrow_mut();
 | 
				
			||||||
 | 
								usage.push_back(id.clone());
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !self.cache.borrow().contains_key(id) {
 | 
				
			||||||
			match KeyDirectory::load_key(&path) {
 | 
								match KeyDirectory::load_key(&path) {
 | 
				
			||||||
				Ok(loaded_key) => loaded_key,
 | 
									Ok(loaded_key) => {
 | 
				
			||||||
 | 
										self.cache.borrow_mut().insert(id.to_owned(), loaded_key);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
				Err(error) => {
 | 
									Err(error) => {
 | 
				
			||||||
					warn!(target: "sstore", "error loading key {:?}: {:?}", id, error);
 | 
										warn!(target: "sstore", "error loading key {:?}: {:?}", id, error);
 | 
				
			||||||
					return None;
 | 
										return None;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		))
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Some(Ref::map(self.cache.borrow(), |c| c.get(id).expect("should be they key, we have just inserted or checked it")))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Returns current path to the directory with keys
 | 
						/// Returns current path to the directory with keys
 | 
				
			||||||
@ -476,29 +485,32 @@ impl KeyDirectory {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	/// Removes keys that never been requested during last `MAX_USAGE_TRACK` times
 | 
						/// Removes keys that never been requested during last `MAX_USAGE_TRACK` times
 | 
				
			||||||
	pub fn collect_garbage(&mut self) {
 | 
						pub fn collect_garbage(&mut self) {
 | 
				
			||||||
		let total_usages = self.cache_usage.len();
 | 
							let mut cache_usage = self.cache_usage.borrow_mut();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let total_usages = cache_usage.len();
 | 
				
			||||||
		let untracked_usages = max(total_usages as i64 - MAX_CACHE_USAGE_TRACK as i64, 0) as usize;
 | 
							let untracked_usages = max(total_usages as i64 - MAX_CACHE_USAGE_TRACK as i64, 0) as usize;
 | 
				
			||||||
		if untracked_usages > 0 {
 | 
							if untracked_usages > 0 {
 | 
				
			||||||
			self.cache_usage.drain(..untracked_usages);
 | 
								cache_usage.drain(..untracked_usages);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if self.cache.len() <= MAX_CACHE_USAGE_TRACK { return; }
 | 
							let mut cache = self.cache.borrow_mut();
 | 
				
			||||||
 | 
							if cache.len() <= MAX_CACHE_USAGE_TRACK { return; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		let uniqs: HashSet<&Uuid> = self.cache_usage.iter().collect();
 | 
							let uniqs: HashSet<&Uuid> = cache_usage.iter().collect();
 | 
				
			||||||
		let mut removes = HashSet::new();
 | 
							let mut removes = HashSet::new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for key in self.cache.keys() {
 | 
							for key in cache.keys() {
 | 
				
			||||||
			if !uniqs.contains(key) {
 | 
								if !uniqs.contains(key) {
 | 
				
			||||||
				removes.insert(key.clone());
 | 
									removes.insert(key.clone());
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		for removed_key in removes { self.cache.remove(&removed_key); }
 | 
							for removed_key in removes { cache.remove(&removed_key); }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/// Reports how many keys are currently cached.
 | 
						/// Reports how many keys are currently cached.
 | 
				
			||||||
	pub fn cache_size(&self) -> usize {
 | 
						pub fn cache_size(&self) -> usize {
 | 
				
			||||||
		self.cache.len()
 | 
							self.cache.borrow().len()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fn key_path(&self, id: &Uuid) -> PathBuf {
 | 
						fn key_path(&self, id: &Uuid) -> PathBuf {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										65
									
								
								util/src/keys/encryptor.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								util/src/keys/encryptor.rs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					// Copyright 2015, 2016 Ethcore (UK) Ltd.
 | 
				
			||||||
 | 
					// This file is part of Parity.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parity is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Parity is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//! Generic Encryptor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use keys::directory::*;
 | 
				
			||||||
 | 
					use common::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub trait EncryptedHashMap<Key: Hash + Eq> {
 | 
				
			||||||
 | 
						// Returns existing value for the key, if any
 | 
				
			||||||
 | 
						fn get<Value: Populatable + Default>(&self, key: &Key, password: &str) -> Option<Value>;
 | 
				
			||||||
 | 
						// Insert new encrypted key-value and returns previous if there was any
 | 
				
			||||||
 | 
						fn insert<Value: Populatable + Default>(&mut self, key: Key, value: Value, password: &str) -> Option<Value>;
 | 
				
			||||||
 | 
						// Removes key-value by key and returns the removed one, if any exists and password was provided
 | 
				
			||||||
 | 
						fn remove<Value: Populatable + Default> (&mut self, key: &Key, password: Option<&str>) -> Option<Value>;
 | 
				
			||||||
 | 
						// Deletes key-value by key and returns if the key-value existed
 | 
				
			||||||
 | 
						fn delete(&mut self, key: &Key) -> bool {
 | 
				
			||||||
 | 
							self.remove::<()>(key, None).is_some()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub struct SecretStore {
 | 
				
			||||||
 | 
						directory: KeyDirectory
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl EncryptedHashMap<H128> for SecretStore {
 | 
				
			||||||
 | 
						fn get<Value: Populatable + Default>(&self, key: &H128, password: &str) -> Option<Value> {
 | 
				
			||||||
 | 
							match self.directory.get(key) {
 | 
				
			||||||
 | 
								Some(key_file) => {
 | 
				
			||||||
 | 
									let mut instance = Value::default();
 | 
				
			||||||
 | 
									instance.populate_raw(&key_file.crypto.cipher_text);
 | 
				
			||||||
 | 
									Some(instance)
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								None => None
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn insert<Value: Populatable + Default>(&mut self, key: H128, value: Value, password: &str) -> Option<Value>{
 | 
				
			||||||
 | 
							let previous = if let Some(key_file) = self.directory.get(&key) { self.get(&key, password) } else { None };
 | 
				
			||||||
 | 
							previous
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fn remove<Value: Populatable + Default>(&mut self, key: &H128, password: Option<&str>) -> Option<Value> {
 | 
				
			||||||
 | 
							let previous = match (self.directory.get(&key), password) {
 | 
				
			||||||
 | 
								(Some(key_file), Some(pass)) => self.get(&key, pass),
 | 
				
			||||||
 | 
								(_, _) => None
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							previous
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -17,3 +17,5 @@
 | 
				
			|||||||
//! Key management module
 | 
					//! Key management module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod directory;
 | 
					pub mod directory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mod encryptor;
 | 
				
			||||||
 | 
				
			|||||||
@ -20,6 +20,7 @@
 | 
				
			|||||||
#![feature(associated_consts)]
 | 
					#![feature(associated_consts)]
 | 
				
			||||||
#![feature(plugin)]
 | 
					#![feature(plugin)]
 | 
				
			||||||
#![feature(catch_panic)]
 | 
					#![feature(catch_panic)]
 | 
				
			||||||
 | 
					#![feature(cell_extras)]
 | 
				
			||||||
// Clippy settings
 | 
					// Clippy settings
 | 
				
			||||||
#![plugin(clippy)]
 | 
					#![plugin(clippy)]
 | 
				
			||||||
// TODO [todr] not really sure
 | 
					// TODO [todr] not really sure
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user