From 2e3fb103abbc55d209fb4afbece9e933a54b1a7d Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 4 Mar 2016 20:08:42 +0300 Subject: [PATCH 1/2] extended secret store operations --- util/src/keys/store.rs | 47 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/util/src/keys/store.rs b/util/src/keys/store.rs index f05b8dec4..bfb8e6c79 100644 --- a/util/src/keys/store.rs +++ b/util/src/keys/store.rs @@ -56,6 +56,17 @@ pub enum EncryptedHashMapError { InvalidValueFormat(FromBytesError), } +/// Error retrieving value from encrypted hashmap +#[derive(Debug)] +pub enum SigningError { + /// Account passed does not exist + NoAccount, + /// Account passed is not unlocked + AccountNotUnlocked, + /// Invalid secret in store + InvalidSecret +} + /// Represent service for storing encrypted arbitrary data pub struct SecretStore { directory: KeyDirectory, @@ -159,6 +170,26 @@ impl SecretStore { try!(self.directory.save(key_file)); Ok(address) } + + /// Signs message with unlocked account + pub fn sign(&self, account: &Address, message: &H256) -> Result { + let read_lock = self.unlocks.read().unwrap(); + let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked)); + match crypto::KeyPair::from_secret(unlock.secret) { + Ok(pair) => match pair.sign(message) { + Ok(signature) => Ok(signature), + Err(_) => Err(SigningError::InvalidSecret) + }, + Err(_) => Err(SigningError::InvalidSecret) + } + } + + /// Returns secret for unlocked account + pub fn account_secret(&self, account: &Address) -> Result { + let read_lock = self.unlocks.read().unwrap(); + let unlock = try!(read_lock.get(account).ok_or(SigningError::AccountNotUnlocked)); + Ok(unlock.secret as crypto::Secret) + } } fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) { @@ -423,6 +454,22 @@ mod tests { assert!(secret.is_ok()); } + #[test] + fn can_sign_data() { + let temp = RandomTempPath::create_dir(); + let address = { + let mut sstore = SecretStore::new_test(&temp); + sstore.new_account("334").unwrap() + }; + let signature = { + let sstore = SecretStore::new_test(&temp); + sstore.unlock_account(&address, "334").unwrap(); + sstore.sign(&address, &H256::random()).unwrap() + }; + + assert!(signature != x!(0)); + } + #[test] fn can_import_account() { use keys::directory::{KeyFileContent, KeyFileCrypto}; From c72c27b47ebb3bf5f4be3b4fb862f3f0ef29ff7f Mon Sep 17 00:00:00 2001 From: Nikolay Volf Date: Fri, 4 Mar 2016 20:09:21 +0300 Subject: [PATCH 2/2] client integration --- ethcore/src/client.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/ethcore/src/client.rs b/ethcore/src/client.rs index 6ae628f8b..070513c0a 100644 --- a/ethcore/src/client.rs +++ b/ethcore/src/client.rs @@ -36,6 +36,7 @@ use transaction::LocalizedTransaction; use extras::TransactionAddress; use filter::Filter; use log_entry::LocalizedLogEntry; +use util::keys::store::SecretStore; pub use block_queue::{BlockQueueConfig, BlockQueueInfo}; pub use blockchain::{TreeRoute, BlockChainConfig, CacheSize as BlockChainCacheSize}; @@ -202,7 +203,8 @@ pub struct Client where V: Verifier { sealing_block: Mutex>, author: RwLock
, extra_data: RwLock, - verifier: PhantomData + verifier: PhantomData, + secret_store: Arc>, } const HISTORY: u64 = 1000; @@ -238,6 +240,9 @@ impl Client where V: Verifier { let panic_handler = PanicHandler::new_in_arc(); panic_handler.forward_from(&block_queue); + let secret_store = Arc::new(RwLock::new(SecretStore::new())); + secret_store.write().unwrap().try_import_existing(); + Ok(Arc::new(Client { chain: chain, engine: engine, @@ -249,7 +254,8 @@ impl Client where V: Verifier { sealing_block: Mutex::new(None), author: RwLock::new(Address::new()), extra_data: RwLock::new(Vec::new()), - verifier: PhantomData + verifier: PhantomData, + secret_store: secret_store, })) } @@ -274,6 +280,11 @@ impl Client where V: Verifier { last_hashes } + /// Secret store (key manager) + pub fn secret_store(&self) -> &Arc> { + &self.secret_store + } + fn check_and_close_block(&self, block: &PreverifiedBlock) -> Result { let engine = self.engine.deref().deref(); let header = &block.header;