Merge pull request #586 from ethcore/secret-store-ext
Secret store integration with client
This commit is contained in:
commit
316e48e3b5
@ -36,6 +36,7 @@ use transaction::LocalizedTransaction;
|
|||||||
use extras::TransactionAddress;
|
use extras::TransactionAddress;
|
||||||
use filter::Filter;
|
use filter::Filter;
|
||||||
use log_entry::LocalizedLogEntry;
|
use log_entry::LocalizedLogEntry;
|
||||||
|
use util::keys::store::SecretStore;
|
||||||
pub use block_queue::{BlockQueueConfig, BlockQueueInfo};
|
pub use block_queue::{BlockQueueConfig, BlockQueueInfo};
|
||||||
pub use blockchain::{TreeRoute, BlockChainConfig, CacheSize as BlockChainCacheSize};
|
pub use blockchain::{TreeRoute, BlockChainConfig, CacheSize as BlockChainCacheSize};
|
||||||
|
|
||||||
@ -202,7 +203,8 @@ pub struct Client<V = CanonVerifier> where V: Verifier {
|
|||||||
sealing_block: Mutex<Option<ClosedBlock>>,
|
sealing_block: Mutex<Option<ClosedBlock>>,
|
||||||
author: RwLock<Address>,
|
author: RwLock<Address>,
|
||||||
extra_data: RwLock<Bytes>,
|
extra_data: RwLock<Bytes>,
|
||||||
verifier: PhantomData<V>
|
verifier: PhantomData<V>,
|
||||||
|
secret_store: Arc<RwLock<SecretStore>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const HISTORY: u64 = 1000;
|
const HISTORY: u64 = 1000;
|
||||||
@ -238,6 +240,9 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
let panic_handler = PanicHandler::new_in_arc();
|
let panic_handler = PanicHandler::new_in_arc();
|
||||||
panic_handler.forward_from(&block_queue);
|
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 {
|
Ok(Arc::new(Client {
|
||||||
chain: chain,
|
chain: chain,
|
||||||
engine: engine,
|
engine: engine,
|
||||||
@ -249,7 +254,8 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
sealing_block: Mutex::new(None),
|
sealing_block: Mutex::new(None),
|
||||||
author: RwLock::new(Address::new()),
|
author: RwLock::new(Address::new()),
|
||||||
extra_data: RwLock::new(Vec::new()),
|
extra_data: RwLock::new(Vec::new()),
|
||||||
verifier: PhantomData
|
verifier: PhantomData,
|
||||||
|
secret_store: secret_store,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,6 +280,11 @@ impl<V> Client<V> where V: Verifier {
|
|||||||
last_hashes
|
last_hashes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Secret store (key manager)
|
||||||
|
pub fn secret_store(&self) -> &Arc<RwLock<SecretStore>> {
|
||||||
|
&self.secret_store
|
||||||
|
}
|
||||||
|
|
||||||
fn check_and_close_block(&self, block: &PreverifiedBlock) -> Result<ClosedBlock, ()> {
|
fn check_and_close_block(&self, block: &PreverifiedBlock) -> Result<ClosedBlock, ()> {
|
||||||
let engine = self.engine.deref().deref();
|
let engine = self.engine.deref().deref();
|
||||||
let header = &block.header;
|
let header = &block.header;
|
||||||
|
@ -56,6 +56,17 @@ pub enum EncryptedHashMapError {
|
|||||||
InvalidValueFormat(FromBytesError),
|
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
|
/// Represent service for storing encrypted arbitrary data
|
||||||
pub struct SecretStore {
|
pub struct SecretStore {
|
||||||
directory: KeyDirectory,
|
directory: KeyDirectory,
|
||||||
@ -159,6 +170,26 @@ impl SecretStore {
|
|||||||
try!(self.directory.save(key_file));
|
try!(self.directory.save(key_file));
|
||||||
Ok(address)
|
Ok(address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Signs message with unlocked account
|
||||||
|
pub fn sign(&self, account: &Address, message: &H256) -> Result<crypto::Signature, SigningError> {
|
||||||
|
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<crypto::Secret, SigningError> {
|
||||||
|
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) {
|
fn derive_key_iterations(password: &str, salt: &H256, c: u32) -> (Bytes, Bytes) {
|
||||||
@ -423,6 +454,22 @@ mod tests {
|
|||||||
assert!(secret.is_ok());
|
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]
|
#[test]
|
||||||
fn can_import_account() {
|
fn can_import_account() {
|
||||||
use keys::directory::{KeyFileContent, KeyFileCrypto};
|
use keys::directory::{KeyFileContent, KeyFileCrypto};
|
||||||
|
Loading…
Reference in New Issue
Block a user