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};