From 41348dead458a02c2f066d318790d0d53005efa1 Mon Sep 17 00:00:00 2001 From: Toralf Wittner Date: Fri, 22 Jun 2018 15:09:15 +0200 Subject: [PATCH] Add type for passwords. (#8920) * Add type for passwords. * Fix test. * Simplify `Drop` impls of `Password` and `Memzero`. * Spaces to tabs. * Custom `Drop` impl for `Password`. --- Cargo.lock | 2 + ethcore/crypto/src/lib.rs | 4 +- ethcore/crypto/src/scrypt.rs | 4 +- ethcore/private-tx/src/encryptor.rs | 4 +- ethcore/private-tx/src/lib.rs | 7 +- ethcore/private-tx/tests/private_contract.rs | 6 +- ethcore/src/account_provider/mod.rs | 76 +++--- ethcore/src/engines/authority_round/mod.rs | 26 +- ethcore/src/engines/basic_authority.rs | 8 +- ethcore/src/engines/mod.rs | 4 +- ethcore/src/engines/signer.rs | 6 +- ethcore/src/engines/tendermint/message.rs | 2 +- ethcore/src/engines/tendermint/mod.rs | 6 +- ethcore/src/engines/validator_set/contract.rs | 2 +- ethcore/src/engines/validator_set/multi.rs | 4 +- .../engines/validator_set/safe_contract.rs | 4 +- ethcore/src/miner/miner.rs | 9 +- ethcore/src/miner/mod.rs | 3 +- .../src/snapshot/tests/proof_of_authority.rs | 2 +- ethcore/sync/src/tests/consensus.rs | 10 +- ethcore/sync/src/tests/private.rs | 6 +- ethkey/Cargo.toml | 2 + ethkey/src/lib.rs | 5 + ethkey/src/password.rs | 60 +++++ ethstore/cli/src/crack.rs | 8 +- ethstore/cli/src/main.rs | 8 +- ethstore/src/account/crypto.rs | 42 ++-- ethstore/src/account/safe_account.rs | 42 ++-- ethstore/src/accounts_dir/disk.rs | 22 +- ethstore/src/accounts_dir/mod.rs | 9 +- ethstore/src/accounts_dir/vault.rs | 16 +- ethstore/src/ethstore.rs | 230 +++++++++--------- ethstore/src/presale.rs | 8 +- ethstore/src/secret_store.rs | 40 +-- ethstore/tests/api.rs | 30 +-- parity/account.rs | 2 +- parity/helpers.rs | 22 +- parity/presale.rs | 2 +- parity/run.rs | 5 +- parity/secretstore.rs | 3 +- rpc/src/v1/helpers/dispatch.rs | 11 +- rpc/src/v1/impls/parity_accounts.rs | 27 +- rpc/src/v1/impls/parity_set.rs | 2 +- rpc/src/v1/impls/personal.rs | 14 +- rpc/src/v1/impls/secretstore.rs | 15 +- rpc/src/v1/impls/signer.rs | 4 +- rpc/src/v1/tests/eth.rs | 2 +- rpc/src/v1/tests/helpers/miner_service.rs | 7 +- rpc/src/v1/tests/mocked/eth.rs | 18 +- rpc/src/v1/tests/mocked/parity.rs | 4 +- rpc/src/v1/tests/mocked/parity_accounts.rs | 44 ++-- rpc/src/v1/tests/mocked/parity_set.rs | 2 +- rpc/src/v1/tests/mocked/personal.rs | 16 +- rpc/src/v1/tests/mocked/secretstore.rs | 8 +- rpc/src/v1/tests/mocked/signer.rs | 18 +- rpc/src/v1/tests/mocked/signing.rs | 8 +- rpc/src/v1/traits/parity_accounts.rs | 27 +- rpc/src/v1/traits/secretstore.rs | 11 +- rpc/src/v1/types/confirmations.rs | 5 +- secret_store/src/node_key_pair.rs | 5 +- util/mem/src/lib.rs | 8 +- 61 files changed, 550 insertions(+), 457 deletions(-) create mode 100644 ethkey/src/password.rs diff --git a/Cargo.lock b/Cargo.lock index 3b9f1f29c..80c31ce33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -958,6 +958,8 @@ dependencies = [ "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ethcore/crypto/src/lib.rs b/ethcore/crypto/src/lib.rs index 459c79031..1958067f9 100644 --- a/ethcore/crypto/src/lib.rs +++ b/ethcore/crypto/src/lib.rs @@ -56,9 +56,9 @@ impl Keccak256<[u8; 32]> for T where T: AsRef<[u8]> { } } -pub fn derive_key_iterations(password: &str, salt: &[u8; 32], c: u32) -> (Vec, Vec) { +pub fn derive_key_iterations(password: &[u8], salt: &[u8; 32], c: u32) -> (Vec, Vec) { let mut derived_key = [0u8; KEY_LENGTH]; - pbkdf2::sha256(c, pbkdf2::Salt(salt), pbkdf2::Secret(password.as_bytes()), &mut derived_key); + pbkdf2::sha256(c, pbkdf2::Salt(salt), pbkdf2::Secret(password), &mut derived_key); let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; (derived_right_bits.to_vec(), derived_left_bits.to_vec()) diff --git a/ethcore/crypto/src/scrypt.rs b/ethcore/crypto/src/scrypt.rs index de3cd5555..11c258155 100644 --- a/ethcore/crypto/src/scrypt.rs +++ b/ethcore/crypto/src/scrypt.rs @@ -18,7 +18,7 @@ use error::ScryptError; use rcrypto::scrypt::{scrypt, ScryptParams}; use super::{KEY_LENGTH_AES, KEY_LENGTH}; -pub fn derive_key(pass: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), ScryptError> { +pub fn derive_key(pass: &[u8], salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec, Vec), ScryptError> { // sanity checks let log_n = (32 - n.leading_zeros() - 1) as u8; if log_n as u32 >= r * 16 { @@ -31,7 +31,7 @@ pub fn derive_key(pass: &str, salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result let mut derived_key = vec![0u8; KEY_LENGTH]; let scrypt_params = ScryptParams::new(log_n, r, p); - scrypt(pass.as_bytes(), salt, &scrypt_params, &mut derived_key); + scrypt(pass, salt, &scrypt_params, &mut derived_key); let derived_right_bits = &derived_key[0..KEY_LENGTH_AES]; let derived_left_bits = &derived_key[KEY_LENGTH_AES..KEY_LENGTH]; Ok((derived_right_bits.to_vec(), derived_left_bits.to_vec())) diff --git a/ethcore/private-tx/src/encryptor.rs b/ethcore/private-tx/src/encryptor.rs index e171e3e60..e64917add 100644 --- a/ethcore/private-tx/src/encryptor.rs +++ b/ethcore/private-tx/src/encryptor.rs @@ -26,7 +26,7 @@ use parking_lot::Mutex; use ethcore::account_provider::AccountProvider; use ethereum_types::{H128, H256, Address}; use ethjson; -use ethkey::{Signature, Public}; +use ethkey::{Signature, Password, Public}; use crypto; use futures::Future; use fetch::{Fetch, Client as FetchClient, Method, BodyReader, Request}; @@ -71,7 +71,7 @@ pub struct EncryptorConfig { /// Account used for signing requests to key server pub key_server_account: Option
, /// Passwords used to unlock accounts - pub passwords: Vec, + pub passwords: Vec, } struct EncryptionSession { diff --git a/ethcore/private-tx/src/lib.rs b/ethcore/private-tx/src/lib.rs index 31abdb1ec..38285ed85 100644 --- a/ethcore/private-tx/src/lib.rs +++ b/ethcore/private-tx/src/lib.rs @@ -85,6 +85,7 @@ use ethcore::account_provider::AccountProvider; use ethcore::miner::{self, Miner, MinerService}; use ethcore::trace::{Tracer, VMTracer}; use rustc_hex::FromHex; +use ethkey::Password; // Source avaiable at https://github.com/parity-contracts/private-tx/blob/master/contracts/PrivateContract.sol const DEFAULT_STUB_CONTRACT: &'static str = include_str!("../res/private.evm"); @@ -102,7 +103,7 @@ pub struct ProviderConfig { /// Account used for signing public transactions created from private transactions pub signer_account: Option
, /// Passwords used to unlock accounts - pub passwords: Vec, + pub passwords: Vec, } #[derive(Debug)] @@ -121,7 +122,7 @@ pub struct Provider { encryptor: Box, validator_accounts: HashSet
, signer_account: Option
, - passwords: Vec, + passwords: Vec, notify: RwLock>>, transactions_for_signing: Mutex, // TODO [ToDr] Move the Mutex/RwLock inside `VerificationStore` after refactored to `drain`. @@ -670,7 +671,7 @@ impl Importer for Arc { } /// Try to unlock account using stored password, return found password if any -fn find_account_password(passwords: &Vec, account_provider: &AccountProvider, account: &Address) -> Option { +fn find_account_password(passwords: &Vec, account_provider: &AccountProvider, account: &Address) -> Option { for password in passwords { if let Ok(true) = account_provider.test_password(account, password) { return Some(password.clone()); diff --git a/ethcore/private-tx/tests/private_contract.rs b/ethcore/private-tx/tests/private_contract.rs index bc678b1ab..b2c08ace2 100644 --- a/ethcore/private-tx/tests/private_contract.rs +++ b/ethcore/private-tx/tests/private_contract.rs @@ -55,9 +55,9 @@ fn private_contract() { let key3 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000013")).unwrap(); let key4 = KeyPair::from_secret(Secret::from("0000000000000000000000000000000000000000000000000000000000000014")).unwrap(); let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(key1.secret().clone(), "").unwrap(); - ap.insert_account(key3.secret().clone(), "").unwrap(); - ap.insert_account(key4.secret().clone(), "").unwrap(); + ap.insert_account(key1.secret().clone(), &"".into()).unwrap(); + ap.insert_account(key3.secret().clone(), &"".into()).unwrap(); + ap.insert_account(key4.secret().clone(), &"".into()).unwrap(); let config = ProviderConfig{ validator_accounts: vec![key3.address(), key4.address()], diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index d05d3425d..a12aec867 100644 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -29,7 +29,7 @@ use ethstore::{ random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret, }; use ethstore::accounts_dir::MemoryDirectory; -use ethstore::ethkey::{Address, Message, Public, Secret, Random, Generator}; +use ethstore::ethkey::{Address, Message, Public, Secret, Password, Random, Generator}; use ethjson::misc::AccountMeta; use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; use super::transaction::{Action, Transaction}; @@ -52,7 +52,7 @@ enum Unlock { #[derive(Clone)] struct AccountData { unlock: Unlock, - password: String, + password: Password, } /// Signing error @@ -112,7 +112,7 @@ fn transient_sstore() -> EthMultiStore { EthMultiStore::open(Box::new(MemoryDirectory::default())).expect("MemoryDirectory load always succeeds; qed") } -type AccountToken = String; +type AccountToken = Password; /// Account management. /// Responsible for unlocking accounts. @@ -217,12 +217,12 @@ impl AccountProvider { } /// Creates new random account. - pub fn new_account(&self, password: &str) -> Result { + pub fn new_account(&self, password: &Password) -> Result { self.new_account_and_public(password).map(|d| d.0) } /// Creates new random account and returns address and public key - pub fn new_account_and_public(&self, password: &str) -> Result<(Address, Public), Error> { + pub fn new_account_and_public(&self, password: &Password) -> Result<(Address, Public), Error> { let acc = Random.generate().expect("secp context has generation capabilities; qed"); let public = acc.public().clone(); let secret = acc.secret().clone(); @@ -232,7 +232,7 @@ impl AccountProvider { /// Inserts new account into underlying store. /// Does not unlock account! - pub fn insert_account(&self, secret: Secret, password: &str) -> Result { + pub fn insert_account(&self, secret: Secret, password: &Password) -> Result { let account = self.sstore.insert_account(SecretVaultRef::Root, secret, password)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; @@ -244,7 +244,7 @@ impl AccountProvider { /// Generates new derived account based on the existing one /// If password is not provided, account must be unlocked /// New account will be created with the same password (if save: true) - pub fn derive_account(&self, address: &Address, password: Option, derivation: Derivation, save: bool) + pub fn derive_account(&self, address: &Address, password: Option, derivation: Derivation, save: bool) -> Result { let account = self.sstore.account_ref(&address)?; @@ -256,13 +256,13 @@ impl AccountProvider { } /// Import a new presale wallet. - pub fn import_presale(&self, presale_json: &[u8], password: &str) -> Result { + pub fn import_presale(&self, presale_json: &[u8], password: &Password) -> Result { let account = self.sstore.import_presale(SecretVaultRef::Root, presale_json, password)?; Ok(Address::from(account.address).into()) } /// Import a new wallet. - pub fn import_wallet(&self, json: &[u8], password: &str, gen_id: bool) -> Result { + pub fn import_wallet(&self, json: &[u8], password: &Password, gen_id: bool) -> Result { let account = self.sstore.import_wallet(SecretVaultRef::Root, json, password, gen_id)?; if self.blacklisted_accounts.contains(&account.address) { self.sstore.remove_account(&account, password)?; @@ -543,7 +543,7 @@ impl AccountProvider { } /// Returns account public key. - pub fn account_public(&self, address: Address, password: &str) -> Result { + pub fn account_public(&self, address: Address, password: &Password) -> Result { self.sstore.public(&self.sstore.account_ref(&address)?, password) } @@ -560,29 +560,29 @@ impl AccountProvider { } /// Returns `true` if the password for `account` is `password`. `false` if not. - pub fn test_password(&self, address: &Address, password: &str) -> Result { + pub fn test_password(&self, address: &Address, password: &Password) -> Result { self.sstore.test_password(&self.sstore.account_ref(&address)?, password) .map_err(Into::into) } /// Permanently removes an account. - pub fn kill_account(&self, address: &Address, password: &str) -> Result<(), Error> { + pub fn kill_account(&self, address: &Address, password: &Password) -> Result<(), Error> { self.sstore.remove_account(&self.sstore.account_ref(&address)?, &password)?; Ok(()) } /// Changes the password of `account` from `password` to `new_password`. Fails if incorrect `password` given. - pub fn change_password(&self, address: &Address, password: String, new_password: String) -> Result<(), Error> { + pub fn change_password(&self, address: &Address, password: Password, new_password: Password) -> Result<(), Error> { self.sstore.change_password(&self.sstore.account_ref(address)?, &password, &new_password) } /// Exports an account for given address. - pub fn export_account(&self, address: &Address, password: String) -> Result { + pub fn export_account(&self, address: &Address, password: Password) -> Result { self.sstore.export_account(&self.sstore.account_ref(address)?, &password) } /// Helper method used for unlocking accounts. - fn unlock_account(&self, address: Address, password: String, unlock: Unlock) -> Result<(), Error> { + fn unlock_account(&self, address: Address, password: Password, unlock: Unlock) -> Result<(), Error> { let account = self.sstore.account_ref(&address)?; // check if account is already unlocked permanently, if it is, do nothing @@ -612,7 +612,7 @@ impl AccountProvider { Ok(()) } - fn password(&self, account: &StoreAccountRef) -> Result { + fn password(&self, account: &StoreAccountRef) -> Result { let mut unlocked = self.unlocked.write(); let data = unlocked.get(account).ok_or(SignError::NotUnlocked)?.clone(); if let Unlock::OneTime = data.unlock { @@ -624,21 +624,21 @@ impl AccountProvider { return Err(SignError::NotUnlocked); } } - Ok(data.password.clone()) + Ok(data.password) } /// Unlocks account permanently. - pub fn unlock_account_permanently(&self, account: Address, password: String) -> Result<(), Error> { + pub fn unlock_account_permanently(&self, account: Address, password: Password) -> Result<(), Error> { self.unlock_account(account, password, Unlock::Perm) } /// Unlocks account temporarily (for one signing). - pub fn unlock_account_temporarily(&self, account: Address, password: String) -> Result<(), Error> { + pub fn unlock_account_temporarily(&self, account: Address, password: Password) -> Result<(), Error> { self.unlock_account(account, password, Unlock::OneTime) } /// Unlocks account temporarily with a timeout. - pub fn unlock_account_timed(&self, account: Address, password: String, duration: Duration) -> Result<(), Error> { + pub fn unlock_account_timed(&self, account: Address, password: Password, duration: Duration) -> Result<(), Error> { self.unlock_account(account, password, Unlock::Timed(Instant::now() + duration)) } @@ -660,7 +660,7 @@ impl AccountProvider { } /// Signs the message. If password is not provided the account must be unlocked. - pub fn sign(&self, address: Address, password: Option, message: Message) -> Result { + pub fn sign(&self, address: Address, password: Option, message: Message) -> Result { let account = self.sstore.account_ref(&address)?; match self.unlocked_secrets.read().get(&account) { Some(secret) => { @@ -674,7 +674,7 @@ impl AccountProvider { } /// Signs message using the derived secret. If password is not provided the account must be unlocked. - pub fn sign_derived(&self, address: &Address, password: Option, derivation: Derivation, message: Message) + pub fn sign_derived(&self, address: &Address, password: Option, derivation: Derivation, message: Message) -> Result { let account = self.sstore.account_ref(address)?; @@ -687,7 +687,7 @@ impl AccountProvider { let account = self.sstore.account_ref(&address)?; let is_std_password = self.sstore.test_password(&account, &token)?; - let new_token = random_string(16); + let new_token = Password::from(random_string(16)); let signature = if is_std_password { // Insert to transient store self.sstore.copy_account(&self.transient_sstore, SecretVaultRef::Root, &account, &token, &new_token)?; @@ -710,7 +710,7 @@ impl AccountProvider { let account = self.sstore.account_ref(&address)?; let is_std_password = self.sstore.test_password(&account, &token)?; - let new_token = random_string(16); + let new_token = Password::from(random_string(16)); let message = if is_std_password { // Insert to transient store self.sstore.copy_account(&self.transient_sstore, SecretVaultRef::Root, &account, &token, &new_token)?; @@ -727,14 +727,14 @@ impl AccountProvider { } /// Decrypts a message. If password is not provided the account must be unlocked. - pub fn decrypt(&self, address: Address, password: Option, shared_mac: &[u8], message: &[u8]) -> Result, SignError> { + pub fn decrypt(&self, address: Address, password: Option, shared_mac: &[u8], message: &[u8]) -> Result, SignError> { let account = self.sstore.account_ref(&address)?; let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; Ok(self.sstore.decrypt(&account, &password, shared_mac, message)?) } /// Agree on shared key. - pub fn agree(&self, address: Address, password: Option, other_public: &Public) -> Result { + pub fn agree(&self, address: Address, password: Option, other_public: &Public) -> Result { let account = self.sstore.account_ref(&address)?; let password = password.map(Ok).unwrap_or_else(|| self.password(&account))?; Ok(self.sstore.agree(&account, &password, other_public)?) @@ -753,13 +753,13 @@ impl AccountProvider { } /// Create new vault. - pub fn create_vault(&self, name: &str, password: &str) -> Result<(), Error> { + pub fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error> { self.sstore.create_vault(name, password) .map_err(Into::into) } /// Open existing vault. - pub fn open_vault(&self, name: &str, password: &str) -> Result<(), Error> { + pub fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error> { self.sstore.open_vault(name, password) .map_err(Into::into) } @@ -783,7 +783,7 @@ impl AccountProvider { } /// Change vault password. - pub fn change_vault_password(&self, name: &str, new_password: &str) -> Result<(), Error> { + pub fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error> { self.sstore.change_vault_password(name, new_password) .map_err(Into::into) } @@ -852,7 +852,7 @@ mod tests { fn unlock_account_temp() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"test".into()).is_ok()); assert!(ap.unlock_account_temporarily(kp.address(), "test1".into()).is_err()); assert!(ap.unlock_account_temporarily(kp.address(), "test".into()).is_ok()); assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); @@ -863,7 +863,7 @@ mod tests { fn derived_account_nosave() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "base").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"base".into()).is_ok()); assert!(ap.unlock_account_permanently(kp.address(), "base".into()).is_ok()); let derived_addr = ap.derive_account( @@ -881,7 +881,7 @@ mod tests { fn derived_account_save() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "base").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"base".into()).is_ok()); assert!(ap.unlock_account_permanently(kp.address(), "base".into()).is_ok()); let derived_addr = ap.derive_account( @@ -902,7 +902,7 @@ mod tests { fn derived_account_sign() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "base").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"base".into()).is_ok()); assert!(ap.unlock_account_permanently(kp.address(), "base".into()).is_ok()); let derived_addr = ap.derive_account( @@ -932,7 +932,7 @@ mod tests { fn unlock_account_perm() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"test".into()).is_ok()); assert!(ap.unlock_account_permanently(kp.address(), "test1".into()).is_err()); assert!(ap.unlock_account_permanently(kp.address(), "test".into()).is_ok()); assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); @@ -946,7 +946,7 @@ mod tests { fn unlock_account_timer() { let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"test".into()).is_ok()); assert!(ap.unlock_account_timed(kp.address(), "test1".into(), Duration::from_secs(60)).is_err()); assert!(ap.unlock_account_timed(kp.address(), "test".into(), Duration::from_secs(60)).is_ok()); assert!(ap.sign(kp.address(), None, Default::default()).is_ok()); @@ -959,7 +959,7 @@ mod tests { // given let kp = Random.generate().unwrap(); let ap = AccountProvider::transient_provider(); - assert!(ap.insert_account(kp.secret().clone(), "test").is_ok()); + assert!(ap.insert_account(kp.secret().clone(), &"test".into()).is_ok()); // when let (_signature, token) = ap.sign_with_token(kp.address(), "test".into(), Default::default()).unwrap(); @@ -1027,7 +1027,7 @@ mod tests { // default_account should be always available assert_eq!(ap.new_dapps_default_address().unwrap(), 0.into()); - let address = ap.new_account("test").unwrap(); + let address = ap.new_account(&"test".into()).unwrap(); ap.set_address_name(1.into(), "1".into()); // Default account set to first account by default @@ -1064,7 +1064,7 @@ mod tests { fn should_not_return_blacklisted_account() { // given let mut ap = AccountProvider::transient_provider(); - let acc = ap.new_account("test").unwrap(); + let acc = ap.new_account(&"test".into()).unwrap(); ap.blacklisted_accounts = vec![acc]; // then diff --git a/ethcore/src/engines/authority_round/mod.rs b/ethcore/src/engines/authority_round/mod.rs index cc5c6e0b1..dee9c7602 100644 --- a/ethcore/src/engines/authority_round/mod.rs +++ b/ethcore/src/engines/authority_round/mod.rs @@ -40,7 +40,7 @@ use super::validator_set::{ValidatorSet, SimpleList, new_validator_set}; use self::finality::RollingFinality; -use ethkey::{self, Signature}; +use ethkey::{self, Password, Signature}; use io::{IoContext, IoHandler, TimerToken, IoService}; use itertools::{self, Itertools}; use rlp::{encode, Decodable, DecoderError, Encodable, RlpStream, Rlp}; @@ -1345,7 +1345,7 @@ impl Engine for AuthorityRound { self.validators.register_client(client); } - fn set_signer(&self, ap: Arc, address: Address, password: String) { + fn set_signer(&self, ap: Arc, address: Address, password: Password) { self.signer.write().set(ap, address, password); } @@ -1414,8 +1414,8 @@ mod tests { #[test] fn generates_seal_and_does_not_double_propose() { let tap = Arc::new(AccountProvider::transient_provider()); - let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); - let addr2 = tap.insert_account(keccak("2").into(), "2").unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + let addr2 = tap.insert_account(keccak("2").into(), &"2".into()).unwrap(); let spec = Spec::new_test_round(); let engine = &*spec.engine; @@ -1446,8 +1446,8 @@ mod tests { #[test] fn checks_difficulty_in_generate_seal() { let tap = Arc::new(AccountProvider::transient_provider()); - let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); - let addr2 = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + let addr2 = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); let spec = Spec::new_test_round(); let engine = &*spec.engine; @@ -1480,7 +1480,7 @@ mod tests { #[test] fn proposer_switching() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&0usize).into_vec()]); parent_header.set_gas_limit("222222".parse::().unwrap()); @@ -1505,7 +1505,7 @@ mod tests { #[test] fn rejects_future_block() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&0usize).into_vec()]); @@ -1530,7 +1530,7 @@ mod tests { #[test] fn rejects_step_backwards() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); let mut parent_header: Header = Header::default(); parent_header.set_seal(vec![encode(&4usize).into_vec()]); @@ -1589,7 +1589,7 @@ mod tests { assert!(aura.verify_block_family(&header, &parent_header).is_ok()); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 0); - aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), Default::default()); + aura.set_signer(Arc::new(AccountProvider::transient_provider()), Default::default(), "".into()); assert!(aura.verify_block_family(&header, &parent_header).is_ok()); assert_eq!(last_benign.load(AtomicOrdering::SeqCst), 1); @@ -1680,8 +1680,8 @@ mod tests { let spec = Spec::new_test_round_empty_steps(); let tap = Arc::new(AccountProvider::transient_provider()); - let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); - let addr2 = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); + let addr2 = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); let accounts = vec![addr1, addr2]; @@ -1951,7 +1951,7 @@ mod tests { let spec = Spec::new_test_round_block_reward_contract(); let tap = Arc::new(AccountProvider::transient_provider()); - let addr1 = tap.insert_account(keccak("1").into(), "1").unwrap(); + let addr1 = tap.insert_account(keccak("1").into(), &"1".into()).unwrap(); let engine = &*spec.engine; let genesis_header = spec.genesis_header(); diff --git a/ethcore/src/engines/basic_authority.rs b/ethcore/src/engines/basic_authority.rs index dde0af2d9..f535399e5 100644 --- a/ethcore/src/engines/basic_authority.rs +++ b/ethcore/src/engines/basic_authority.rs @@ -19,7 +19,7 @@ use std::sync::{Weak, Arc}; use ethereum_types::{H256, H520, Address}; use parking_lot::RwLock; -use ethkey::{self, Signature}; +use ethkey::{self, Password, Signature}; use account_provider::AccountProvider; use block::*; use engines::{Engine, Seal, ConstructedVerifier, EngineError}; @@ -180,7 +180,7 @@ impl Engine for BasicAuthority { self.validators.register_client(client); } - fn set_signer(&self, ap: Arc, address: Address, password: String) { + fn set_signer(&self, ap: Arc, address: Address, password: Password) { self.signer.write().set(ap, address, password); } @@ -243,7 +243,7 @@ mod tests { #[test] fn can_generate_seal() { let tap = AccountProvider::transient_provider(); - let addr = tap.insert_account(keccak("").into(), "").unwrap(); + let addr = tap.insert_account(keccak("").into(), &"".into()).unwrap(); let spec = new_test_authority(); let engine = &*spec.engine; @@ -261,7 +261,7 @@ mod tests { #[test] fn seals_internally() { let tap = AccountProvider::transient_provider(); - let authority = tap.insert_account(keccak("").into(), "").unwrap(); + let authority = tap.insert_account(keccak("").into(), &"".into()).unwrap(); let engine = new_test_authority().engine; assert!(!engine.seals_internally().unwrap()); diff --git a/ethcore/src/engines/mod.rs b/ethcore/src/engines/mod.rs index 54a9dde2e..8f67a039f 100644 --- a/ethcore/src/engines/mod.rs +++ b/ethcore/src/engines/mod.rs @@ -51,7 +51,7 @@ use snapshot::SnapshotComponents; use spec::CommonParams; use transaction::{self, UnverifiedTransaction, SignedTransaction}; -use ethkey::Signature; +use ethkey::{Password, Signature}; use parity_machine::{Machine, LocalizedMachine as Localized, TotalScoredHeader}; use ethereum_types::{H256, U256, Address}; use unexpected::{Mismatch, OutOfBounds}; @@ -322,7 +322,7 @@ pub trait Engine: Sync + Send { fn is_proposal(&self, _verified_header: &M::Header) -> bool { false } /// Register an account which signs consensus messages. - fn set_signer(&self, _account_provider: Arc, _address: Address, _password: String) {} + fn set_signer(&self, _account_provider: Arc, _address: Address, _password: Password) {} /// Sign using the EngineSigner, to be used for consensus tx signing. fn sign(&self, _hash: H256) -> Result { unimplemented!() } diff --git a/ethcore/src/engines/signer.rs b/ethcore/src/engines/signer.rs index 965b619c7..670c0959c 100644 --- a/ethcore/src/engines/signer.rs +++ b/ethcore/src/engines/signer.rs @@ -18,14 +18,14 @@ use std::sync::Arc; use ethereum_types::{H256, Address}; -use ethkey::Signature; +use ethkey::{Password, Signature}; use account_provider::{self, AccountProvider}; /// Everything that an Engine needs to sign messages. pub struct EngineSigner { account_provider: Arc, address: Option
, - password: Option, + password: Option, } impl Default for EngineSigner { @@ -40,7 +40,7 @@ impl Default for EngineSigner { impl EngineSigner { /// Set up the signer to sign with given address and password. - pub fn set(&mut self, ap: Arc, address: Address, password: String) { + pub fn set(&mut self, ap: Arc, address: Address, password: Password) { self.account_provider = ap; self.address = Some(address); self.password = Some(password); diff --git a/ethcore/src/engines/tendermint/message.rs b/ethcore/src/engines/tendermint/message.rs index ba8e4390e..d7a08b303 100644 --- a/ethcore/src/engines/tendermint/message.rs +++ b/ethcore/src/engines/tendermint/message.rs @@ -252,7 +252,7 @@ mod tests { #[test] fn generate_and_verify() { let tap = Arc::new(AccountProvider::transient_provider()); - let addr = tap.insert_account(keccak("0").into(), "0").unwrap(); + let addr = tap.insert_account(keccak("0").into(), &"0".into()).unwrap(); tap.unlock_account_permanently(addr, "0".into()).unwrap(); let mi = message_info_rlp(&VoteStep::new(123, 2, Step::Precommit), Some(H256::default())); diff --git a/ethcore/src/engines/tendermint/mod.rs b/ethcore/src/engines/tendermint/mod.rs index 967ef482a..26b1cfd98 100644 --- a/ethcore/src/engines/tendermint/mod.rs +++ b/ethcore/src/engines/tendermint/mod.rs @@ -37,7 +37,7 @@ use bytes::Bytes; use error::{Error, BlockError}; use header::{Header, BlockNumber, ExtendedHeader}; use rlp::Rlp; -use ethkey::{self, Message, Signature}; +use ethkey::{self, Password, Message, Signature}; use account_provider::AccountProvider; use block::*; use engines::{Engine, Seal, EngineError, ConstructedVerifier}; @@ -677,7 +677,7 @@ impl Engine for Tendermint { } } - fn set_signer(&self, ap: Arc, address: Address, password: String) { + fn set_signer(&self, ap: Arc, address: Address, password: Password) { { self.signer.write().set(ap, address, password); } @@ -831,7 +831,7 @@ mod tests { } fn insert_and_unlock(tap: &Arc, acc: &str) -> Address { - let addr = tap.insert_account(keccak(acc).into(), acc).unwrap(); + let addr = tap.insert_account(keccak(acc).into(), &acc.into()).unwrap(); tap.unlock_account_permanently(addr, acc.into()).unwrap(); addr } diff --git a/ethcore/src/engines/validator_set/contract.rs b/ethcore/src/engines/validator_set/contract.rs index c44f2ab30..e4fcc83cb 100644 --- a/ethcore/src/engines/validator_set/contract.rs +++ b/ethcore/src/engines/validator_set/contract.rs @@ -163,7 +163,7 @@ mod tests { #[test] fn reports_validators() { let tap = Arc::new(AccountProvider::transient_provider()); - let v1 = tap.insert_account(keccak("1").into(), "").unwrap(); + let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_contract, Some(tap.clone())); client.engine().register_client(Arc::downgrade(&client) as _); let validator_contract = "0000000000000000000000000000000000000005".parse::
().unwrap(); diff --git a/ethcore/src/engines/validator_set/multi.rs b/ethcore/src/engines/validator_set/multi.rs index 3ac58cd4d..a23208cd2 100644 --- a/ethcore/src/engines/validator_set/multi.rs +++ b/ethcore/src/engines/validator_set/multi.rs @@ -165,8 +165,8 @@ mod tests { fn uses_current_set() { let tap = Arc::new(AccountProvider::transient_provider()); let s0: Secret = keccak("0").into(); - let v0 = tap.insert_account(s0.clone(), "").unwrap(); - let v1 = tap.insert_account(keccak("1").into(), "").unwrap(); + let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap(); + let v1 = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_multi, Some(tap)); client.engine().register_client(Arc::downgrade(&client) as _); diff --git a/ethcore/src/engines/validator_set/safe_contract.rs b/ethcore/src/engines/validator_set/safe_contract.rs index e55a0e3e3..2cecac8bd 100644 --- a/ethcore/src/engines/validator_set/safe_contract.rs +++ b/ethcore/src/engines/validator_set/safe_contract.rs @@ -477,8 +477,8 @@ mod tests { fn knows_validators() { let tap = Arc::new(AccountProvider::transient_provider()); let s0: Secret = keccak("1").into(); - let v0 = tap.insert_account(s0.clone(), "").unwrap(); - let v1 = tap.insert_account(keccak("0").into(), "").unwrap(); + let v0 = tap.insert_account(s0.clone(), &"".into()).unwrap(); + let v1 = tap.insert_account(keccak("0").into(), &"".into()).unwrap(); let chain_id = Spec::new_validator_safe_contract().chain_id(); let client = generate_dummy_client_with_spec_and_accounts(Spec::new_validator_safe_contract, Some(tap)); client.engine().register_client(Arc::downgrade(&client) as _); diff --git a/ethcore/src/miner/miner.rs b/ethcore/src/miner/miner.rs index af03b2d1e..db496e40d 100644 --- a/ethcore/src/miner/miner.rs +++ b/ethcore/src/miner/miner.rs @@ -50,6 +50,7 @@ use miner::pool_client::{PoolClient, CachedNonceClient}; use receipt::{Receipt, RichReceipt}; use spec::Spec; use state::State; +use ethkey::Password; /// Different possible definitions for pending transaction set. #[derive(Debug, PartialEq)] @@ -736,12 +737,12 @@ impl miner::MinerService for Miner { self.params.write().extra_data = extra_data; } - fn set_author(&self, address: Address, password: Option) -> Result<(), AccountError> { + fn set_author(&self, address: Address, password: Option) -> Result<(), AccountError> { self.params.write().author = address; if self.engine.seals_internally().is_some() && password.is_some() { if let Some(ref ap) = self.accounts { - let password = password.unwrap_or_default(); + let password = password.unwrap_or_else(|| Password::from(String::new())); // Sign test message ap.sign(address.clone(), Some(password.clone()), Default::default())?; // Enable sealing @@ -1285,7 +1286,7 @@ mod tests { let keypair = Random.generate().unwrap(); let client = TestBlockChainClient::default(); let account_provider = AccountProvider::transient_provider(); - account_provider.insert_account(keypair.secret().clone(), "").expect("can add accounts to the provider we just created"); + account_provider.insert_account(keypair.secret().clone(), &"".into()).expect("can add accounts to the provider we just created"); let miner = Miner::new( MinerOptions { @@ -1366,7 +1367,7 @@ mod tests { fn should_fail_setting_engine_signer_without_account_provider() { let spec = Spec::new_instant; let tap = Arc::new(AccountProvider::transient_provider()); - let addr = tap.insert_account(keccak("1").into(), "").unwrap(); + let addr = tap.insert_account(keccak("1").into(), &"".into()).unwrap(); let client = generate_dummy_client_with_spec_and_accounts(spec, None); assert!(match client.miner().set_author(addr, Some("".into())) { Err(AccountError::NotFound) => true, _ => false }); } diff --git a/ethcore/src/miner/mod.rs b/ethcore/src/miner/mod.rs index 1d7b9613b..44d9ecf71 100644 --- a/ethcore/src/miner/mod.rs +++ b/ethcore/src/miner/mod.rs @@ -46,6 +46,7 @@ use header::{BlockNumber, Header}; use receipt::{RichReceipt, Receipt}; use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}; use state::StateInfo; +use ethkey::Password; /// Provides methods to verify incoming external transactions pub trait TransactionVerifierClient: Send + Sync @@ -124,7 +125,7 @@ pub trait MinerService : Send + Sync { /// Set info necessary to sign consensus messages and block authoring. /// /// On PoW password is optional. - fn set_author(&self, address: Address, password: Option) -> Result<(), ::account_provider::SignError>; + fn set_author(&self, address: Address, password: Option) -> Result<(), ::account_provider::SignError>; // Transaction Pool diff --git a/ethcore/src/snapshot/tests/proof_of_authority.rs b/ethcore/src/snapshot/tests/proof_of_authority.rs index f8f6bc6c8..aefb3d2f9 100644 --- a/ethcore/src/snapshot/tests/proof_of_authority.rs +++ b/ethcore/src/snapshot/tests/proof_of_authority.rs @@ -71,7 +71,7 @@ fn make_accounts(secrets: &[Secret]) -> (Arc, Vec
) { let addrs = secrets.iter() .cloned() - .map(|s| provider.insert_account(s, PASS).unwrap()) + .map(|s| provider.insert_account(s, &PASS.into()).unwrap()) .collect(); (Arc::new(provider), addrs) diff --git a/ethcore/sync/src/tests/consensus.rs b/ethcore/sync/src/tests/consensus.rs index 6b2502f4a..40a4edef3 100644 --- a/ethcore/sync/src/tests/consensus.rs +++ b/ethcore/sync/src/tests/consensus.rs @@ -44,8 +44,8 @@ fn authority_round() { let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(s0.secret().clone(), "").unwrap(); - ap.insert_account(s1.secret().clone(), "").unwrap(); + ap.insert_account(s0.secret().clone(), &"".into()).unwrap(); + ap.insert_account(s1.secret().clone(), &"".into()).unwrap(); let chain_id = Spec::new_test_round().chain_id(); let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_round, Some(ap)); @@ -53,7 +53,7 @@ fn authority_round() { let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); // Push transaction to both clients. Only one of them gets lucky to produce a block. net.peer(0).miner.set_author(s0.address(), Some("".into())).unwrap(); - net.peer(1).miner.set_author(s1.address(), Some("".to_owned())).unwrap(); + net.peer(1).miner.set_author(s1.address(), Some("".into())).unwrap(); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler1))); @@ -131,8 +131,8 @@ fn tendermint() { let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(s0.secret().clone(), "").unwrap(); - ap.insert_account(s1.secret().clone(), "").unwrap(); + ap.insert_account(s0.secret().clone(), &"".into()).unwrap(); + ap.insert_account(s1.secret().clone(), &"".into()).unwrap(); let chain_id = Spec::new_test_tendermint().chain_id(); let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), Spec::new_test_tendermint, Some(ap)); diff --git a/ethcore/sync/src/tests/private.rs b/ethcore/sync/src/tests/private.rs index 120dc8fc9..04b414b94 100644 --- a/ethcore/sync/src/tests/private.rs +++ b/ethcore/sync/src/tests/private.rs @@ -42,8 +42,8 @@ fn send_private_transaction() { let s0 = KeyPair::from_secret_slice(&keccak("1")).unwrap(); let s1 = KeyPair::from_secret_slice(&keccak("0")).unwrap(); let ap = Arc::new(AccountProvider::transient_provider()); - ap.insert_account(s0.secret().clone(), "").unwrap(); - ap.insert_account(s1.secret().clone(), "").unwrap(); + ap.insert_account(s0.secret().clone(), &"".into()).unwrap(); + ap.insert_account(s1.secret().clone(), &"".into()).unwrap(); let mut net = TestNet::with_spec_and_accounts(2, SyncConfig::default(), seal_spec, Some(ap.clone())); let client0 = net.peer(0).chain.clone(); @@ -52,7 +52,7 @@ fn send_private_transaction() { let io_handler1: Arc> = Arc::new(TestIoHandler::new(net.peer(1).chain.clone())); net.peer(0).miner.set_author(s0.address(), Some("".into())).unwrap(); - net.peer(1).miner.set_author(s1.address(), Some("".to_owned())).unwrap(); + net.peer(1).miner.set_author(s1.address(), Some("".into())).unwrap(); net.peer(0).chain.engine().register_client(Arc::downgrade(&net.peer(0).chain) as _); net.peer(1).chain.engine().register_client(Arc::downgrade(&net.peer(1).chain) as _); net.peer(0).chain.set_io_channel(IoChannel::to_handler(Arc::downgrade(&io_handler0))); diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index 952354739..c93af468c 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -16,4 +16,6 @@ parity-wordlist = "1.2" quick-error = "1.2" rand = "0.4" rustc-hex = "1.0" +serde = "1.0" +serde_derive = "1.0" tiny-keccak = "1.4" diff --git a/ethkey/src/lib.rs b/ethkey/src/lib.rs index 7aec015c4..af13f5a1e 100644 --- a/ethkey/src/lib.rs +++ b/ethkey/src/lib.rs @@ -27,18 +27,22 @@ extern crate quick_error; extern crate rand; extern crate rustc_hex; extern crate secp256k1; +extern crate serde; extern crate tiny_keccak; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; +#[macro_use] +extern crate serde_derive; mod brain; mod brain_prefix; mod error; mod keypair; mod keccak; +mod password; mod prefix; mod random; mod signature; @@ -55,6 +59,7 @@ pub use self::brain_prefix::BrainPrefix; pub use self::error::Error; pub use self::keypair::{KeyPair, public_to_address}; pub use self::math::public_is_valid; +pub use self::password::Password; pub use self::prefix::Prefix; pub use self::random::Random; pub use self::signature::{sign, verify_public, verify_address, recover, Signature}; diff --git a/ethkey/src/password.rs b/ethkey/src/password.rs new file mode 100644 index 000000000..d34966373 --- /dev/null +++ b/ethkey/src/password.rs @@ -0,0 +1,60 @@ +// Copyright 2018 Parity Technologies (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 . + +use std::{fmt, ptr}; + +#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct Password(String); + +impl fmt::Debug for Password { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "Password(******)") + } +} + +impl Password { + pub fn as_bytes(&self) -> &[u8] { + self.0.as_bytes() + } + + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + +// Custom drop impl to zero out memory. +impl Drop for Password { + fn drop(&mut self) { + unsafe { + for byte_ref in self.0.as_mut_vec() { + ptr::write_volatile(byte_ref, 0) + } + } + } +} + +impl From for Password { + fn from(s: String) -> Password { + Password(s) + } +} + +impl<'a> From<&'a str> for Password { + fn from(s: &'a str) -> Password { + Password::from(String::from(s)) + } +} + diff --git a/ethstore/cli/src/crack.rs b/ethstore/cli/src/crack.rs index 3e767a608..00844b7f0 100644 --- a/ethstore/cli/src/crack.rs +++ b/ethstore/cli/src/crack.rs @@ -19,10 +19,10 @@ use std::sync::Arc; use std::collections::VecDeque; use parking_lot::Mutex; -use ethstore::{PresaleWallet, Error}; +use ethstore::{ethkey::Password, PresaleWallet, Error}; use num_cpus; -pub fn run(passwords: VecDeque, wallet_path: &str) -> Result<(), Error> { +pub fn run(passwords: VecDeque, wallet_path: &str) -> Result<(), Error> { let passwords = Arc::new(Mutex::new(passwords)); let mut handles = Vec::new(); @@ -42,7 +42,7 @@ pub fn run(passwords: VecDeque, wallet_path: &str) -> Result<(), Error> Ok(()) } -fn look_for_password(passwords: Arc>>, wallet: PresaleWallet) { +fn look_for_password(passwords: Arc>>, wallet: PresaleWallet) { let mut counter = 0; while !passwords.lock().is_empty() { let package = { @@ -54,7 +54,7 @@ fn look_for_password(passwords: Arc>>, wallet: PresaleWal counter += 1; match wallet.decrypt(&pass) { Ok(_) => { - println!("Found password: {}", &pass); + println!("Found password: {}", pass.as_str()); passwords.lock().clear(); return; }, diff --git a/ethstore/cli/src/main.rs b/ethstore/cli/src/main.rs index 922d85714..6a88f0da2 100644 --- a/ethstore/cli/src/main.rs +++ b/ethstore/cli/src/main.rs @@ -32,7 +32,7 @@ use std::{env, process, fs, fmt}; use docopt::Docopt; use ethstore::accounts_dir::{KeyDirectory, RootDiskDirectory}; -use ethstore::ethkey::Address; +use ethstore::ethkey::{Address, Password}; use ethstore::{EthStore, SimpleSecretStore, SecretStore, import_accounts, PresaleWallet, SecretVaultRef, StoreAccountRef}; mod crack; @@ -201,13 +201,13 @@ fn format_vaults(vaults: &[String]) -> String { vaults.join("\n") } -fn load_password(path: &str) -> Result { +fn load_password(path: &str) -> Result { let mut file = fs::File::open(path).map_err(|e| ethstore::Error::Custom(format!("Error opening password file {}: {}", path, e)))?; let mut password = String::new(); file.read_to_string(&mut password).map_err(|e| ethstore::Error::Custom(format!("Error reading password file {}: {}", path, e)))?; // drop EOF let _ = password.pop(); - Ok(password) + Ok(password.into()) } fn execute(command: I) -> Result where I: IntoIterator, S: AsRef { @@ -252,7 +252,7 @@ fn execute(command: I) -> Result where I: IntoIterator>(); + let passwords = passwords.as_str().lines().map(|line| str::to_owned(line).into()).collect::>(); crack::run(passwords, &args.arg_path)?; Ok(format!("Password not found.")) } else if args.cmd_remove { diff --git a/ethstore/src/account/crypto.rs b/ethstore/src/account/crypto.rs index 3143958a1..07f84af7f 100644 --- a/ethstore/src/account/crypto.rs +++ b/ethstore/src/account/crypto.rs @@ -15,7 +15,7 @@ // along with Parity. If not, see . use std::str; -use ethkey::Secret; +use ethkey::{Password, Secret}; use {json, Error, crypto}; use crypto::Keccak256; use random::Random; @@ -73,18 +73,18 @@ impl From for String { impl Crypto { /// Encrypt account secret - pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Result { + pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result { Crypto::with_plain(&*secret, password, iterations) } /// Encrypt custom plain data - pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Result { + pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result { let salt: [u8; 32] = Random::random(); let iv: [u8; 16] = Random::random(); // two parts of derived key // DK = [ DK[0..15] DK[16..31] ] = [derived_left_bits, derived_right_bits] - let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password, &salt, iterations); + let (derived_left_bits, derived_right_bits) = crypto::derive_key_iterations(password.as_bytes(), &salt, iterations); // preallocated (on-stack in case of `Secret`) buffer to hold cipher // length = length(plain) as we are using CTR-approach @@ -113,7 +113,7 @@ impl Crypto { } /// Try to decrypt and convert result to account secret - pub fn secret(&self, password: &str) -> Result { + pub fn secret(&self, password: &Password) -> Result { if self.ciphertext.len() > 32 { return Err(Error::InvalidSecret); } @@ -123,15 +123,15 @@ impl Crypto { } /// Try to decrypt and return result as is - pub fn decrypt(&self, password: &str) -> Result, Error> { + pub fn decrypt(&self, password: &Password) -> Result, Error> { let expected_len = self.ciphertext.len(); self.do_decrypt(password, expected_len) } - fn do_decrypt(&self, password: &str, expected_len: usize) -> Result, Error> { + fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result, Error> { let (derived_left_bits, derived_right_bits) = match self.kdf { - Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password, ¶ms.salt, params.c), - Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password, ¶ms.salt, params.n, params.p, params.r)?, + Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password.as_bytes(), ¶ms.salt, params.c), + Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password.as_bytes(), ¶ms.salt, params.n, params.p, params.r)?, }; let mac = crypto::derive_mac(&derived_right_bits, &self.ciphertext).keccak256(); @@ -163,39 +163,43 @@ mod tests { #[test] fn crypto_with_secret_create() { let keypair = Random.generate().unwrap(); - let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240).unwrap(); - let secret = crypto.secret("this is sparta").unwrap(); + let passwd = "this is sparta".into(); + let crypto = Crypto::with_secret(keypair.secret(), &passwd, 10240).unwrap(); + let secret = crypto.secret(&passwd).unwrap(); assert_eq!(keypair.secret(), &secret); } #[test] fn crypto_with_secret_invalid_password() { let keypair = Random.generate().unwrap(); - let crypto = Crypto::with_secret(keypair.secret(), "this is sparta", 10240).unwrap(); - assert_matches!(crypto.secret("this is sparta!"), Err(Error::InvalidPassword)) + let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), 10240).unwrap(); + assert_matches!(crypto.secret(&"this is sparta!".into()), Err(Error::InvalidPassword)) } #[test] fn crypto_with_null_plain_data() { let original_data = b""; - let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240).unwrap(); - let decrypted_data = crypto.decrypt("this is sparta").unwrap(); + let passwd = "this is sparta".into(); + let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap(); + let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(original_data[..], *decrypted_data); } #[test] fn crypto_with_tiny_plain_data() { let original_data = b"{}"; - let crypto = Crypto::with_plain(&original_data[..], "this is sparta", 10240).unwrap(); - let decrypted_data = crypto.decrypt("this is sparta").unwrap(); + let passwd = "this is sparta".into(); + let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap(); + let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(original_data[..], *decrypted_data); } #[test] fn crypto_with_huge_plain_data() { let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect(); - let crypto = Crypto::with_plain(&original_data, "this is sparta", 10240).unwrap(); - let decrypted_data = crypto.decrypt("this is sparta").unwrap(); + let passwd = "this is sparta".into(); + let crypto = Crypto::with_plain(&original_data, &passwd, 10240).unwrap(); + let decrypted_data = crypto.decrypt(&passwd).unwrap(); assert_eq!(&original_data, &decrypted_data); } } diff --git a/ethstore/src/account/safe_account.rs b/ethstore/src/account/safe_account.rs index 0bda99d02..849dafab1 100644 --- a/ethstore/src/account/safe_account.rs +++ b/ethstore/src/account/safe_account.rs @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -use ethkey::{self, KeyPair, sign, Address, Signature, Message, Public, Secret}; +use ethkey::{self, KeyPair, sign, Address, Password, Signature, Message, Public, Secret}; use ethkey::crypto::ecdh::agree; use {json, Error}; use account::Version; @@ -58,7 +58,7 @@ impl SafeAccount { pub fn create( keypair: &KeyPair, id: [u8; 16], - password: &str, + password: &Password, iterations: u32, name: String, meta: String @@ -92,7 +92,7 @@ impl SafeAccount { /// Create a new `SafeAccount` from the given vault `json`; if it was read from a /// file, the `filename` should be `Some` name. If it is as yet anonymous, then it /// can be left `None`. - pub fn from_vault_file(password: &str, json: json::VaultKeyFile, filename: Option) -> Result { + pub fn from_vault_file(password: &Password, json: json::VaultKeyFile, filename: Option) -> Result { let meta_crypto: Crypto = json.metacrypto.into(); let meta_plain = meta_crypto.decrypt(password)?; let meta_plain = json::VaultKeyMeta::load(&meta_plain).map_err(|e| Error::Custom(format!("{:?}", e)))?; @@ -108,7 +108,7 @@ impl SafeAccount { } /// Create a new `VaultKeyFile` from the given `self` - pub fn into_vault_file(self, iterations: u32, password: &str) -> Result { + pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result { let meta_plain = json::VaultKeyMeta { address: self.address.into(), name: Some(self.name), @@ -126,31 +126,31 @@ impl SafeAccount { } /// Sign a message. - pub fn sign(&self, password: &str, message: &Message) -> Result { + pub fn sign(&self, password: &Password, message: &Message) -> Result { let secret = self.crypto.secret(password)?; sign(&secret, message).map_err(From::from) } /// Decrypt a message. - pub fn decrypt(&self, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error> { + pub fn decrypt(&self, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result, Error> { let secret = self.crypto.secret(password)?; ethkey::crypto::ecies::decrypt(&secret, shared_mac, message).map_err(From::from) } /// Agree on shared key. - pub fn agree(&self, password: &str, other: &Public) -> Result { + pub fn agree(&self, password: &Password, other: &Public) -> Result { let secret = self.crypto.secret(password)?; agree(&secret, other).map_err(From::from) } /// Derive public key. - pub fn public(&self, password: &str) -> Result { + pub fn public(&self, password: &Password) -> Result { let secret = self.crypto.secret(password)?; Ok(KeyPair::from_secret(secret)?.public().clone()) } /// Change account's password. - pub fn change_password(&self, old_password: &str, new_password: &str, iterations: u32) -> Result { + pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result { let secret = self.crypto.secret(old_password)?; let result = SafeAccount { id: self.id.clone(), @@ -165,7 +165,7 @@ impl SafeAccount { } /// Check if password matches the account. - pub fn check_password(&self, password: &str) -> bool { + pub fn check_password(&self, password: &Password) -> bool { self.crypto.secret(password).is_ok() } } @@ -178,25 +178,25 @@ mod tests { #[test] fn sign_and_verify_public() { let keypair = Random.generate().unwrap(); - let password = "hello world"; + let password = "hello world".into(); let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], password, 10240, "Test".to_owned(), "{}".to_owned()); - let signature = account.unwrap().sign(password, &message).unwrap(); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned()); + let signature = account.unwrap().sign(&password, &message).unwrap(); assert!(verify_public(keypair.public(), &signature, &message).unwrap()); } #[test] fn change_password() { let keypair = Random.generate().unwrap(); - let first_password = "hello world"; - let sec_password = "this is sparta"; + let first_password = "hello world".into(); + let sec_password = "this is sparta".into(); let i = 10240; let message = Message::default(); - let account = SafeAccount::create(&keypair, [0u8; 16], first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); - let new_account = account.change_password(first_password, sec_password, i).unwrap(); - assert!(account.sign(first_password, &message).is_ok()); - assert!(account.sign(sec_password, &message).is_err()); - assert!(new_account.sign(first_password, &message).is_err()); - assert!(new_account.sign(sec_password, &message).is_ok()); + let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, i, "Test".to_owned(), "{}".to_owned()).unwrap(); + let new_account = account.change_password(&first_password, &sec_password, i).unwrap(); + assert!(account.sign(&first_password, &message).is_ok()); + assert!(account.sign(&sec_password, &message).is_err()); + assert!(new_account.sign(&first_password, &message).is_err()); + assert!(new_account.sign(&sec_password, &message).is_ok()); } } diff --git a/ethstore/src/accounts_dir/disk.rs b/ethstore/src/accounts_dir/disk.rs index 220f58d54..cf4841e74 100644 --- a/ethstore/src/accounts_dir/disk.rs +++ b/ethstore/src/accounts_dir/disk.rs @@ -357,11 +357,11 @@ mod test { let mut dir = env::temp_dir(); dir.push("ethstore_should_create_new_account"); let keypair = Random.generate().unwrap(); - let password = "hello world"; + let password = "hello world".into(); let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); let res = directory.insert(account.unwrap()); // then @@ -378,11 +378,11 @@ mod test { let mut dir = env::temp_dir(); dir.push("ethstore_should_handle_duplicate_filenames"); let keypair = Random.generate().unwrap(); - let password = "hello world"; + let password = "hello world".into(); let directory = RootDiskDirectory::create(dir.clone()).unwrap(); // when - let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()).unwrap(); let filename = "test".to_string(); let dedup = true; @@ -411,14 +411,14 @@ mod test { dir.push("should_create_new_vault"); let directory = RootDiskDirectory::create(dir.clone()).unwrap(); let vault_name = "vault"; - let password = "password"; + let password = "password".into(); // then assert!(directory.as_vault_provider().is_some()); // and when let before_root_items_count = fs::read_dir(&dir).unwrap().count(); - let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(password, 1024)); + let vault = directory.as_vault_provider().unwrap().create(vault_name, VaultKey::new(&password, 1024)); // then assert!(vault.is_ok()); @@ -426,7 +426,7 @@ mod test { assert!(after_root_items_count > before_root_items_count); // and when - let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(password, 1024)); + let vault = directory.as_vault_provider().unwrap().open(vault_name, VaultKey::new(&password, 1024)); // then assert!(vault.is_ok()); @@ -443,8 +443,8 @@ mod test { let temp_path = TempDir::new("").unwrap(); let directory = RootDiskDirectory::create(&temp_path).unwrap(); let vault_provider = directory.as_vault_provider().unwrap(); - vault_provider.create("vault1", VaultKey::new("password1", 1)).unwrap(); - vault_provider.create("vault2", VaultKey::new("password2", 1)).unwrap(); + vault_provider.create("vault1", VaultKey::new(&"password1".into(), 1)).unwrap(); + vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap(); // then let vaults = vault_provider.list_vaults().unwrap(); @@ -465,8 +465,8 @@ mod test { ); let keypair = Random.generate().unwrap(); - let password = "test pass"; - let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned()); + let password = "test pass".into(); + let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned()); directory.insert(account.unwrap()).expect("Account should be inserted ok"); let new_hash = directory.files_hash().expect("New files hash should be calculated ok"); diff --git a/ethstore/src/accounts_dir/mod.rs b/ethstore/src/accounts_dir/mod.rs index b8dd313d2..1191a73d2 100644 --- a/ethstore/src/accounts_dir/mod.rs +++ b/ethstore/src/accounts_dir/mod.rs @@ -16,6 +16,7 @@ //! Accounts Directory +use ethkey::Password; use std::path::{PathBuf}; use {SafeAccount, Error}; @@ -35,10 +36,10 @@ pub enum SetKeyError { } /// Vault key -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Clone, PartialEq, Eq)] pub struct VaultKey { /// Vault password - pub password: String, + pub password: Password, /// Number of iterations to produce a derived key from password pub iterations: u32, } @@ -95,9 +96,9 @@ pub use self::vault::VaultDiskDirectory; impl VaultKey { /// Create new vault key - pub fn new(password: &str, iterations: u32) -> Self { + pub fn new(password: &Password, iterations: u32) -> Self { VaultKey { - password: password.to_owned(), + password: password.clone(), iterations: iterations, } } diff --git a/ethstore/src/accounts_dir/vault.rs b/ethstore/src/accounts_dir/vault.rs index 631376dc9..249a9c6dc 100644 --- a/ethstore/src/accounts_dir/vault.rs +++ b/ethstore/src/accounts_dir/vault.rs @@ -234,7 +234,7 @@ fn check_vault_name(name: &str) -> bool { /// Vault can be empty, but still must be pluggable => we store vault password in separate file fn create_vault_file

(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef { - let password_hash = key.password.keccak256(); + let password_hash = key.password.as_bytes().keccak256(); let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations)?; let vault_file_path = vault_dir_path.as_ref().join(VAULT_FILE_NAME); @@ -267,7 +267,7 @@ fn read_vault_file

(vault_dir_path: P, key: Option<&VaultKey>) -> Result Result { + fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result { self.store.insert_account(vault, secret, password) } - fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) + fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result { self.store.insert_derived(vault, account_ref, password, derivation) } - fn generate_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) -> Result { + fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result { self.store.generate_derived(account_ref, password, derivation) } @@ -86,42 +86,42 @@ impl SimpleSecretStore for EthStore { self.store.accounts() } - fn change_password(&self, account: &StoreAccountRef, old_password: &str, new_password: &str) -> Result<(), Error> { + fn change_password(&self, account: &StoreAccountRef, old_password: &Password, new_password: &Password) -> Result<(), Error> { self.store.change_password(account, old_password, new_password) } - fn export_account(&self, account: &StoreAccountRef, password: &str) -> Result { + fn export_account(&self, account: &StoreAccountRef, password: &Password) -> Result { self.store.export_account(account, password) } - fn remove_account(&self, account: &StoreAccountRef, password: &str) -> Result<(), Error> { + fn remove_account(&self, account: &StoreAccountRef, password: &Password) -> Result<(), Error> { self.store.remove_account(account, password) } - fn sign(&self, account: &StoreAccountRef, password: &str, message: &Message) -> Result { + fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result { self.get(account)?.sign(password, message) } - fn sign_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation, message: &Message) + fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result { self.store.sign_derived(account_ref, password, derivation, message) } - fn agree(&self, account: &StoreAccountRef, password: &str, other: &Public) -> Result { + fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result { self.store.agree(account, password, other) } - fn decrypt(&self, account: &StoreAccountRef, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error> { + fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result, Error> { let account = self.get(account)?; account.decrypt(password, shared_mac, message) } - fn create_vault(&self, name: &str, password: &str) -> Result<(), Error> { + fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error> { self.store.create_vault(name, password) } - fn open_vault(&self, name: &str, password: &str) -> Result<(), Error> { + fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error> { self.store.open_vault(name, password) } @@ -137,7 +137,7 @@ impl SimpleSecretStore for EthStore { self.store.list_opened_vaults() } - fn change_vault_password(&self, name: &str, new_password: &str) -> Result<(), Error> { + fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error> { self.store.change_vault_password(name, new_password) } @@ -155,18 +155,18 @@ impl SimpleSecretStore for EthStore { } impl SecretStore for EthStore { - fn raw_secret(&self, account: &StoreAccountRef, password: &str) -> Result { + fn raw_secret(&self, account: &StoreAccountRef, password: &Password) -> Result { Ok(OpaqueSecret(self.get(account)?.crypto.secret(password)?)) } - fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result { + fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &Password) -> Result { let json_wallet = json::PresaleWallet::load(json).map_err(|_| Error::InvalidKeyFile("Invalid JSON format".to_owned()))?; let wallet = PresaleWallet::from(json_wallet); let keypair = wallet.decrypt(password).map_err(|_| Error::InvalidPassword)?; self.insert_account(vault, keypair.secret().clone(), password) } - fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str, gen_id: bool) -> Result { + fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &Password, gen_id: bool) -> Result { let json_keyfile = json::KeyFile::load(json).map_err(|_| Error::InvalidKeyFile("Invalid JSON format".to_owned()))?; let mut safe_account = SafeAccount::from_file(json_keyfile, None); @@ -179,19 +179,19 @@ impl SecretStore for EthStore { self.store.import(vault, safe_account) } - fn test_password(&self, account: &StoreAccountRef, password: &str) -> Result { + fn test_password(&self, account: &StoreAccountRef, password: &Password) -> Result { let account = self.get(account)?; Ok(account.check_password(password)) } - fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &str, new_password: &str) -> Result<(), Error> { + fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error> { let account = self.get(account)?; let secret = account.crypto.secret(password)?; new_store.insert_account(new_vault, secret, new_password)?; Ok(()) } - fn public(&self, account: &StoreAccountRef, password: &str) -> Result { + fn public(&self, account: &StoreAccountRef, password: &Password) -> Result { let account = self.get(account)?; account.public(password) } @@ -365,7 +365,7 @@ impl EthMultiStore { } } - fn get_matching(&self, account: &StoreAccountRef, password: &str) -> Result, Error> { + fn get_matching(&self, account: &StoreAccountRef, password: &Password) -> Result, Error> { let accounts = self.get_accounts(account)?; Ok(accounts.into_iter() @@ -455,14 +455,14 @@ impl EthMultiStore { } impl SimpleSecretStore for EthMultiStore { - fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &str) -> Result { + fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result { let keypair = KeyPair::from_secret(secret).map_err(|_| Error::CreationFailed)?; let id: [u8; 16] = Random::random(); let account = SafeAccount::create(&keypair, id, password, self.iterations, "".to_owned(), "{}".to_owned())?; self.import(vault, account) } - fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) + fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result { let accounts = self.get_matching(account_ref, password)?; @@ -473,7 +473,7 @@ impl SimpleSecretStore for EthMultiStore { Err(Error::InvalidPassword) } - fn generate_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) + fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result { let accounts = self.get_matching(&account_ref, password)?; @@ -484,7 +484,7 @@ impl SimpleSecretStore for EthMultiStore { Err(Error::InvalidPassword) } - fn sign_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation, message: &Message) + fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result { let accounts = self.get_matching(&account_ref, password)?; @@ -518,7 +518,7 @@ impl SimpleSecretStore for EthMultiStore { Ok(self.cache.read().keys().cloned().collect()) } - fn remove_account(&self, account_ref: &StoreAccountRef, password: &str) -> Result<(), Error> { + fn remove_account(&self, account_ref: &StoreAccountRef, password: &Password) -> Result<(), Error> { let accounts = self.get_matching(account_ref, password)?; for account in accounts { @@ -528,7 +528,7 @@ impl SimpleSecretStore for EthMultiStore { Err(Error::InvalidPassword) } - fn change_password(&self, account_ref: &StoreAccountRef, old_password: &str, new_password: &str) -> Result<(), Error> { + fn change_password(&self, account_ref: &StoreAccountRef, old_password: &Password, new_password: &Password) -> Result<(), Error> { let accounts = self.get_matching(account_ref, old_password)?; if accounts.is_empty() { @@ -544,11 +544,11 @@ impl SimpleSecretStore for EthMultiStore { Ok(()) } - fn export_account(&self, account_ref: &StoreAccountRef, password: &str) -> Result { + fn export_account(&self, account_ref: &StoreAccountRef, password: &Password) -> Result { self.get_matching(account_ref, password)?.into_iter().nth(0).map(Into::into).ok_or(Error::InvalidPassword) } - fn sign(&self, account: &StoreAccountRef, password: &str, message: &Message) -> Result { + fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result { let accounts = self.get_matching(account, password)?; match accounts.first() { Some(ref account) => account.sign(password, message), @@ -556,7 +556,7 @@ impl SimpleSecretStore for EthMultiStore { } } - fn decrypt(&self, account: &StoreAccountRef, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error> { + fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result, Error> { let accounts = self.get_matching(account, password)?; match accounts.first() { Some(ref account) => account.decrypt(password, shared_mac, message), @@ -564,7 +564,7 @@ impl SimpleSecretStore for EthMultiStore { } } - fn agree(&self, account: &StoreAccountRef, password: &str, other: &Public) -> Result { + fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result { let accounts = self.get_matching(account, password)?; match accounts.first() { Some(ref account) => account.agree(password, other), @@ -572,7 +572,7 @@ impl SimpleSecretStore for EthMultiStore { } } - fn create_vault(&self, name: &str, password: &str) -> Result<(), Error> { + fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error> { let is_vault_created = { // lock border let mut vaults = self.vaults.lock(); if !vaults.contains_key(&name.to_owned()) { @@ -592,7 +592,7 @@ impl SimpleSecretStore for EthMultiStore { Ok(()) } - fn open_vault(&self, name: &str, password: &str) -> Result<(), Error> { + fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error> { let is_vault_opened = { // lock border let mut vaults = self.vaults.lock(); if !vaults.contains_key(&name.to_owned()) { @@ -629,7 +629,7 @@ impl SimpleSecretStore for EthMultiStore { Ok(self.vaults.lock().keys().cloned().collect()) } - fn change_vault_password(&self, name: &str, new_password: &str) -> Result<(), Error> { + fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error> { let old_key = self.vaults.lock().get(name).map(|v| v.key()).ok_or(Error::VaultNotFound)?; let vault_provider = self.dir.as_vault_provider().ok_or(Error::VaultsAreNotSupported)?; let vault = vault_provider.open(name, old_key)?; @@ -732,7 +732,8 @@ mod tests { let keypair = keypair(); // when - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let passwd = "test".into(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd).unwrap(); // then assert_eq!(address, StoreAccountRef::root(keypair.address())); @@ -745,7 +746,8 @@ mod tests { // given let store = store(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let passwd = "test".into(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd).unwrap(); assert_eq!(&store.meta(&address).unwrap(), "{}"); assert_eq!(&store.name(&address).unwrap(), ""); @@ -763,11 +765,12 @@ mod tests { fn should_remove_account() { // given let store = store(); + let passwd = "test".into(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd).unwrap(); // when - store.remove_account(&address, "test").unwrap(); + store.remove_account(&address, &passwd).unwrap(); // then assert_eq!(store.accounts().unwrap().len(), 0, "Should remove account."); @@ -777,12 +780,13 @@ mod tests { fn should_return_true_if_password_is_correct() { // given let store = store(); + let passwd = "test".into(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd).unwrap(); // when - let res1 = store.test_password(&address, "x").unwrap(); - let res2 = store.test_password(&address, "test").unwrap(); + let res1 = store.test_password(&address, &"x".into()).unwrap(); + let res2 = store.test_password(&address, &passwd).unwrap(); assert!(!res1, "First password should be invalid."); assert!(res2, "Second password should be correct."); @@ -792,16 +796,18 @@ mod tests { fn multistore_should_be_able_to_have_the_same_account_twice() { // given let store = multi_store(); + let passwd1 = "test".into(); + let passwd2 = "xyz".into(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); - let address2 = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "xyz").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd1).unwrap(); + let address2 = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd2).unwrap(); assert_eq!(address, address2); // when - assert!(store.remove_account(&address, "test").is_ok(), "First password should work."); + assert!(store.remove_account(&address, &passwd1).is_ok(), "First password should work."); assert_eq!(store.accounts().unwrap().len(), 1); - assert!(store.remove_account(&address, "xyz").is_ok(), "Second password should work too."); + assert!(store.remove_account(&address, &passwd2).is_ok(), "Second password should work too."); assert_eq!(store.accounts().unwrap().len(), 0); } @@ -809,17 +815,19 @@ mod tests { fn should_copy_account() { // given let store = store(); + let passwd1 = "test".into(); + let passwd2 = "xzy".into(); let multi_store = multi_store(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &passwd1).unwrap(); assert_eq!(multi_store.accounts().unwrap().len(), 0); // when - store.copy_account(&multi_store, SecretVaultRef::Root, &address, "test", "xyz").unwrap(); + store.copy_account(&multi_store, SecretVaultRef::Root, &address, &passwd1, &passwd2).unwrap(); // then - assert!(store.test_password(&address, "test").unwrap(), "First password should work for store."); - assert!(multi_store.sign(&address, "xyz", &Default::default()).is_ok(), "Second password should work for second store."); + assert!(store.test_password(&address, &passwd1).unwrap(), "First password should work for store."); + assert!(multi_store.sign(&address, &passwd2, &Default::default()).is_ok(), "Second password should work for second store."); assert_eq!(multi_store.accounts().unwrap().len(), 1); } @@ -828,23 +836,23 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; - let name2 = "vault2"; let password2 = "password2"; + let name1 = "vault1"; let password1 = "password1".into(); + let name2 = "vault2"; let password2 = "password2".into(); let keypair1 = keypair(); let keypair2 = keypair(); - let keypair3 = keypair(); let password3 = "password3"; + let keypair3 = keypair(); let password3 = "password3".into(); // when - store.create_vault(name1, password1).unwrap(); - store.create_vault(name2, password2).unwrap(); + store.create_vault(name1, &password1).unwrap(); + store.create_vault(name2, &password2).unwrap(); // then [can create vaults] ^^^ // and when - store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), password1).unwrap(); - store.insert_account(SecretVaultRef::Vault(name2.to_owned()), keypair2.secret().clone(), password2).unwrap(); - store.insert_account(SecretVaultRef::Root, keypair3.secret().clone(), password3).unwrap(); - store.insert_account(SecretVaultRef::Vault("vault3".to_owned()), keypair1.secret().clone(), password3).unwrap_err(); + store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), &password1).unwrap(); + store.insert_account(SecretVaultRef::Vault(name2.to_owned()), keypair2.secret().clone(), &password2).unwrap(); + store.insert_account(SecretVaultRef::Root, keypair3.secret().clone(), &password3).unwrap(); + store.insert_account(SecretVaultRef::Vault("vault3".to_owned()), keypair1.secret().clone(), &password3).unwrap_err(); let accounts = store.accounts().unwrap(); // then [can create accounts in vaults] @@ -864,10 +872,10 @@ mod tests { assert!(accounts.iter().any(|a| a.vault == SecretVaultRef::Root)); // and when - store.open_vault(name1, password2).unwrap_err(); - store.open_vault(name2, password1).unwrap_err(); - store.open_vault(name1, password1).unwrap(); - store.open_vault(name2, password2).unwrap(); + store.open_vault(name1, &password2).unwrap_err(); + store.open_vault(name2, &password1).unwrap_err(); + store.open_vault(name1, &password1).unwrap(); + store.open_vault(name2, &password2).unwrap(); let accounts = store.accounts().unwrap(); // then [can check vaults on open + can reopen vaults + accounts from vaults appear] @@ -882,19 +890,19 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; - let name2 = "vault2"; let password2 = "password2"; - let password3 = "password3"; + let name1 = "vault1"; let password1 = "password1".into(); + let name2 = "vault2"; let password2 = "password2".into(); + let password3 = "password3".into(); let keypair1 = keypair(); let keypair2 = keypair(); let keypair3 = keypair(); // when - store.create_vault(name1, password1).unwrap(); - store.create_vault(name2, password2).unwrap(); - let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), password1).unwrap(); - let account2 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair2.secret().clone(), password1).unwrap(); - let account3 = store.insert_account(SecretVaultRef::Root, keypair3.secret().clone(), password3).unwrap(); + store.create_vault(name1, &password1).unwrap(); + store.create_vault(name2, &password2).unwrap(); + let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), &password1).unwrap(); + let account2 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair2.secret().clone(), &password1).unwrap(); + let account3 = store.insert_account(SecretVaultRef::Root, keypair3.secret().clone(), &password3).unwrap(); // then let account1 = store.change_account_vault(SecretVaultRef::Root, account1.clone()).unwrap(); @@ -917,11 +925,11 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let password1 = "password1"; + let password1 = "password1".into(); let keypair1 = keypair(); // when - let account1 = store.insert_account(SecretVaultRef::Root, keypair1.secret().clone(), password1).unwrap(); + let account1 = store.insert_account(SecretVaultRef::Root, keypair1.secret().clone(), &password1).unwrap(); store.change_account_vault(SecretVaultRef::Root, account1).unwrap(); // then @@ -934,16 +942,16 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; + let name1 = "vault1"; let password1 = "password1".into(); let keypair1 = keypair(); // when - store.create_vault(name1, password1).unwrap(); - let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), password1).unwrap(); + store.create_vault(name1, &password1).unwrap(); + let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), &password1).unwrap(); assert_eq!(store.accounts().unwrap().len(), 1); // then - store.remove_account(&account1, password1).unwrap(); + store.remove_account(&account1, &password1).unwrap(); assert_eq!(store.accounts().unwrap().len(), 0); } @@ -952,17 +960,17 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; - let password2 = "password2"; + let name1 = "vault1"; let password1 = "password1".into(); + let password2 = "password2".into(); let keypair1 = keypair(); // when - store.create_vault(name1, password1).unwrap(); - let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), password1).unwrap(); + store.create_vault(name1, &password1).unwrap(); + let account1 = store.insert_account(SecretVaultRef::Vault(name1.to_owned()), keypair1.secret().clone(), &password1).unwrap(); assert_eq!(store.accounts().unwrap().len(), 1); // then - store.remove_account(&account1, password2).unwrap_err(); + store.remove_account(&account1, &password2).unwrap_err(); assert_eq!(store.accounts().unwrap().len(), 1); } @@ -971,24 +979,24 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name = "vault"; let password = "password"; + let name = "vault"; let password = "password".into(); let keypair = keypair(); // when - store.create_vault(name, password).unwrap(); - store.insert_account(SecretVaultRef::Vault(name.to_owned()), keypair.secret().clone(), password).unwrap(); + store.create_vault(name, &password).unwrap(); + store.insert_account(SecretVaultRef::Vault(name.to_owned()), keypair.secret().clone(), &password).unwrap(); // then assert_eq!(store.accounts().unwrap().len(), 1); - let new_password = "new_password"; - store.change_vault_password(name, new_password).unwrap(); + let new_password = "new_password".into(); + store.change_vault_password(name, &new_password).unwrap(); assert_eq!(store.accounts().unwrap().len(), 1); // and when store.close_vault(name).unwrap(); // then - store.open_vault(name, new_password).unwrap(); + store.open_vault(name, &new_password).unwrap(); assert_eq!(store.accounts().unwrap().len(), 1); } @@ -997,18 +1005,18 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name = "vault"; let password = "password"; - let secret_password = "sec_password"; + let name = "vault"; let password = "password".into(); + let secret_password = "sec_password".into(); let keypair = keypair(); // when - store.create_vault(name, password).unwrap(); - let account_ref = store.insert_account(SecretVaultRef::Vault(name.to_owned()), keypair.secret().clone(), secret_password).unwrap(); + store.create_vault(name, &password).unwrap(); + let account_ref = store.insert_account(SecretVaultRef::Vault(name.to_owned()), keypair.secret().clone(), &secret_password).unwrap(); // then assert_eq!(store.accounts().unwrap().len(), 1); - let new_secret_password = "new_sec_password"; - store.change_password(&account_ref, secret_password, new_secret_password).unwrap(); + let new_secret_password = "new_sec_password".into(); + store.change_password(&account_ref, &secret_password, &new_secret_password).unwrap(); assert_eq!(store.accounts().unwrap().len(), 1); } @@ -1017,14 +1025,14 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; - let name2 = "vault2"; let password2 = "password2"; - let name3 = "vault3"; let password3 = "password3"; + let name1 = "vault1"; let password1 = "password1".into(); + let name2 = "vault2"; let password2 = "password2".into(); + let name3 = "vault3"; let password3 = "password3".into(); // when - store.create_vault(name1, password1).unwrap(); - store.create_vault(name2, password2).unwrap(); - store.create_vault(name3, password3).unwrap(); + store.create_vault(name1, &password1).unwrap(); + store.create_vault(name2, &password2).unwrap(); + store.create_vault(name3, &password3).unwrap(); store.close_vault(name2).unwrap(); // then @@ -1039,10 +1047,10 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name1 = "vault1"; let password1 = "password1"; + let name1 = "vault1"; let password1 = "password1".into(); // when - store.create_vault(name1, password1).unwrap(); + store.create_vault(name1, &password1).unwrap(); // then assert_eq!(store.get_vault_meta(name1).unwrap(), "{}".to_owned()); @@ -1051,7 +1059,7 @@ mod tests { // and when store.close_vault(name1).unwrap(); - store.open_vault(name1, password1).unwrap(); + store.open_vault(name1, &password1).unwrap(); // then assert_eq!(store.get_vault_meta(name1).unwrap(), "Hello, world!!!".to_owned()); @@ -1069,13 +1077,13 @@ mod tests { // given we have one account in the store let store = store(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &"test".into()).unwrap(); // when we deriving from that account let derived = store.insert_derived( SecretVaultRef::Root, &address, - "test", + &"test".into(), Derivation::HardHash(H256::from(0)), ).unwrap(); @@ -1084,7 +1092,7 @@ mod tests { assert_eq!(accounts.len(), 2); // and we can sign with the derived contract - assert!(store.sign(&derived, "test", &Default::default()).is_ok(), "Second password should work for second store."); + assert!(store.sign(&derived, &"test".into(), &Default::default()).is_ok(), "Second password should work for second store."); } #[test] @@ -1092,13 +1100,13 @@ mod tests { // given let mut dir = RootDiskDirectoryGuard::new(); let store = EthStore::open(dir.key_dir.take().unwrap()).unwrap(); - let name = "vault"; let password = "password1"; - let new_password = "password2"; + let name = "vault"; let password = "password1".into(); + let new_password = "password2".into(); // when - store.create_vault(name, password).unwrap(); + store.create_vault(name, &password).unwrap(); store.set_vault_meta(name, "OldMeta").unwrap(); - store.change_vault_password(name, new_password).unwrap(); + store.change_vault_password(name, &new_password).unwrap(); // then assert_eq!(store.get_vault_meta(name).unwrap(), "OldMeta".to_owned()); @@ -1109,10 +1117,10 @@ mod tests { // given let store = store(); let keypair = keypair(); - let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), "test").unwrap(); + let address = store.insert_account(SecretVaultRef::Root, keypair.secret().clone(), &"test".into()).unwrap(); // when - let exported = store.export_account(&address, "test"); + let exported = store.export_account(&address, &"test".into()); // then assert!(exported.is_ok(), "Should export single account: {:?}", exported); diff --git a/ethstore/src/presale.rs b/ethstore/src/presale.rs index d7b80d240..7ffde7973 100644 --- a/ethstore/src/presale.rs +++ b/ethstore/src/presale.rs @@ -17,7 +17,7 @@ use std::fs; use std::path::Path; use json; -use ethkey::{Address, Secret, KeyPair}; +use ethkey::{Address, Secret, KeyPair, Password}; use crypto::{Keccak256, pbkdf2}; use {crypto, Error}; @@ -54,7 +54,7 @@ impl PresaleWallet { } /// Decrypt the wallet. - pub fn decrypt(&self, password: &str) -> Result { + pub fn decrypt(&self, password: &Password) -> Result { let mut derived_key = [0u8; 32]; let salt = pbkdf2::Salt(password.as_bytes()); let sec = pbkdf2::Secret(password.as_bytes()); @@ -93,7 +93,7 @@ mod tests { let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap(); let wallet = PresaleWallet::from(wallet); - assert!(wallet.decrypt("123").is_ok()); - assert!(wallet.decrypt("124").is_err()); + assert!(wallet.decrypt(&"123".into()).is_ok()); + assert!(wallet.decrypt(&"124".into()).is_err()); } } diff --git a/ethstore/src/secret_store.rs b/ethstore/src/secret_store.rs index fd37267a7..b8417bc61 100644 --- a/ethstore/src/secret_store.rs +++ b/ethstore/src/secret_store.rs @@ -17,7 +17,7 @@ use std::hash::{Hash, Hasher}; use std::path::PathBuf; use std::cmp::Ordering; -use ethkey::{Address, Message, Signature, Secret, Public}; +use ethkey::{Address, Message, Signature, Secret, Password, Public}; use Error; use json::{Uuid, OpaqueKeyFile}; use ethereum_types::H256; @@ -56,25 +56,25 @@ impl ::std::borrow::Borrow

for StoreAccountRef { /// Simple Secret Store API pub trait SimpleSecretStore: Send + Sync { /// Inserts new accounts to the store (or vault) with given password. - fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &str) -> Result; + fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result; /// Inserts new derived account to the store (or vault) with given password. - fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) -> Result; + fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result; /// Changes accounts password. - fn change_password(&self, account: &StoreAccountRef, old_password: &str, new_password: &str) -> Result<(), Error>; + fn change_password(&self, account: &StoreAccountRef, old_password: &Password, new_password: &Password) -> Result<(), Error>; /// Exports key details for account. - fn export_account(&self, account: &StoreAccountRef, password: &str) -> Result; + fn export_account(&self, account: &StoreAccountRef, password: &Password) -> Result; /// Entirely removes account from the store and underlying storage. - fn remove_account(&self, account: &StoreAccountRef, password: &str) -> Result<(), Error>; + fn remove_account(&self, account: &StoreAccountRef, password: &Password) -> Result<(), Error>; /// Generates new derived account. - fn generate_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) -> Result; + fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result; /// Sign a message with given account. - fn sign(&self, account: &StoreAccountRef, password: &str, message: &Message) -> Result; + fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result; /// Sign a message with derived account. - fn sign_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation, message: &Message) -> Result; + fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result; /// Decrypt a messages with given account. - fn decrypt(&self, account: &StoreAccountRef, password: &str, shared_mac: &[u8], message: &[u8]) -> Result, Error>; + fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result, Error>; /// Agree on shared key. - fn agree(&self, account: &StoreAccountRef, password: &str, other: &Public) -> Result; + fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result; /// Returns all accounts in this secret store. fn accounts(&self) -> Result, Error>; @@ -83,9 +83,9 @@ pub trait SimpleSecretStore: Send + Sync { fn account_ref(&self, address: &Address) -> Result; /// Create new vault with given password - fn create_vault(&self, name: &str, password: &str) -> Result<(), Error>; + fn create_vault(&self, name: &str, password: &Password) -> Result<(), Error>; /// Open vault with given password - fn open_vault(&self, name: &str, password: &str) -> Result<(), Error>; + fn open_vault(&self, name: &str, password: &Password) -> Result<(), Error>; /// Close vault fn close_vault(&self, name: &str) -> Result<(), Error>; /// List all vaults @@ -93,7 +93,7 @@ pub trait SimpleSecretStore: Send + Sync { /// List all currently opened vaults fn list_opened_vaults(&self) -> Result, Error>; /// Change vault password - fn change_vault_password(&self, name: &str, new_password: &str) -> Result<(), Error>; + fn change_vault_password(&self, name: &str, new_password: &Password) -> Result<(), Error>; /// Cnage account' vault fn change_account_vault(&self, vault: SecretVaultRef, account: StoreAccountRef) -> Result; /// Get vault metadata string. @@ -106,7 +106,7 @@ pub trait SimpleSecretStore: Send + Sync { pub trait SecretStore: SimpleSecretStore { /// Returns a raw opaque Secret that can be later used to sign a message. - fn raw_secret(&self, account: &StoreAccountRef, password: &str) -> Result; + fn raw_secret(&self, account: &StoreAccountRef, password: &Password) -> Result; /// Signs a message with raw secret. fn sign_with_secret(&self, secret: &OpaqueSecret, message: &Message) -> Result { @@ -114,16 +114,16 @@ pub trait SecretStore: SimpleSecretStore { } /// Imports presale wallet - fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result; + fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &Password) -> Result; /// Imports existing JSON wallet - fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str, gen_id: bool) -> Result; + fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &Password, gen_id: bool) -> Result; /// Copies account between stores and vaults. - fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &str, new_password: &str) -> Result<(), Error>; + fn copy_account(&self, new_store: &SimpleSecretStore, new_vault: SecretVaultRef, account: &StoreAccountRef, password: &Password, new_password: &Password) -> Result<(), Error>; /// Checks if password matches given account. - fn test_password(&self, account: &StoreAccountRef, password: &str) -> Result; + fn test_password(&self, account: &StoreAccountRef, password: &Password) -> Result; /// Returns a public key for given account. - fn public(&self, account: &StoreAccountRef, password: &str) -> Result; + fn public(&self, account: &StoreAccountRef, password: &Password) -> Result; /// Returns uuid of an account. fn uuid(&self, account: &StoreAccountRef) -> Result; diff --git a/ethstore/tests/api.rs b/ethstore/tests/api.rs index 5e4eaab81..11ab4f8ed 100644 --- a/ethstore/tests/api.rs +++ b/ethstore/tests/api.rs @@ -46,9 +46,9 @@ fn secret_store_create_account() { let dir = TransientDir::create().unwrap(); let store = EthStore::open(Box::new(dir)).unwrap(); assert_eq!(store.accounts().unwrap().len(), 0); - assert!(store.insert_account(SecretVaultRef::Root, random_secret(), "").is_ok()); + assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok()); assert_eq!(store.accounts().unwrap().len(), 1); - assert!(store.insert_account(SecretVaultRef::Root, random_secret(), "").is_ok()); + assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok()); assert_eq!(store.accounts().unwrap().len(), 2); } @@ -56,36 +56,36 @@ fn secret_store_create_account() { fn secret_store_sign() { let dir = TransientDir::create().unwrap(); let store = EthStore::open(Box::new(dir)).unwrap(); - assert!(store.insert_account(SecretVaultRef::Root, random_secret(), "").is_ok()); + assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok()); let accounts = store.accounts().unwrap(); assert_eq!(accounts.len(), 1); - assert!(store.sign(&accounts[0], "", &Default::default()).is_ok()); - assert!(store.sign(&accounts[0], "1", &Default::default()).is_err()); + assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_ok()); + assert!(store.sign(&accounts[0], &"1".into(), &Default::default()).is_err()); } #[test] fn secret_store_change_password() { let dir = TransientDir::create().unwrap(); let store = EthStore::open(Box::new(dir)).unwrap(); - assert!(store.insert_account(SecretVaultRef::Root, random_secret(), "").is_ok()); + assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok()); let accounts = store.accounts().unwrap(); assert_eq!(accounts.len(), 1); - assert!(store.sign(&accounts[0], "", &Default::default()).is_ok()); - assert!(store.change_password(&accounts[0], "", "1").is_ok()); - assert!(store.sign(&accounts[0], "", &Default::default()).is_err()); - assert!(store.sign(&accounts[0], "1", &Default::default()).is_ok()); + assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_ok()); + assert!(store.change_password(&accounts[0], &"".into(), &"1".into()).is_ok()); + assert!(store.sign(&accounts[0], &"".into(), &Default::default()).is_err()); + assert!(store.sign(&accounts[0], &"1".into(), &Default::default()).is_ok()); } #[test] fn secret_store_remove_account() { let dir = TransientDir::create().unwrap(); let store = EthStore::open(Box::new(dir)).unwrap(); - assert!(store.insert_account(SecretVaultRef::Root, random_secret(), "").is_ok()); + assert!(store.insert_account(SecretVaultRef::Root, random_secret(), &"".into()).is_ok()); let accounts = store.accounts().unwrap(); assert_eq!(accounts.len(), 1); - assert!(store.remove_account(&accounts[0], "").is_ok()); + assert!(store.remove_account(&accounts[0], &"".into()).is_ok()); assert_eq!(store.accounts().unwrap().len(), 0); - assert!(store.remove_account(&accounts[0], "").is_err()); + assert!(store.remove_account(&accounts[0], &"".into()).is_err()); } fn test_path() -> &'static str { @@ -146,8 +146,8 @@ fn test_decrypting_files_with_short_ciphertext() { let message = Default::default(); - let s1 = store.sign(&accounts[0], "foo", &message).unwrap(); - let s2 = store.sign(&accounts[1], "foo", &message).unwrap(); + let s1 = store.sign(&accounts[0], &"foo".into(), &message).unwrap(); + let s2 = store.sign(&accounts[1], &"foo".into(), &message).unwrap(); assert!(verify_address(&accounts[0].address, &s1, &message).unwrap()); assert!(verify_address(&kp1.address(), &s1, &message).unwrap()); assert!(verify_address(&kp2.address(), &s2, &message).unwrap()); diff --git a/parity/account.rs b/parity/account.rs index c2f15546e..e09667379 100644 --- a/parity/account.rs +++ b/parity/account.rs @@ -85,7 +85,7 @@ fn secret_store(dir: Box, iterations: Option) -> Result< } fn new(n: NewAccount) -> Result { - let password: String = match n.password_file { + let password = match n.password_file { Some(file) => password_from_file(file)?, None => password_prompt()?, }; diff --git a/parity/helpers.rs b/parity/helpers.rs index 8de3728c3..7362403ee 100644 --- a/parity/helpers.rs +++ b/parity/helpers.rs @@ -30,6 +30,7 @@ use upgrade::{upgrade, upgrade_data_paths}; use sync::{validate_node_url, self}; use db::migrate; use path; +use ethkey::Password; pub fn to_duration(s: &str) -> Result { to_seconds(s).map(Duration::from_secs) @@ -277,7 +278,7 @@ pub fn execute_upgrades( } /// Prompts user asking for password. -pub fn password_prompt() -> Result { +pub fn password_prompt() -> Result { use rpassword::read_password; const STDIN_ERROR: &'static str = "Unable to ask for password on non-interactive terminal."; @@ -285,12 +286,12 @@ pub fn password_prompt() -> Result { print!("Type password: "); flush_stdout(); - let password = read_password().map_err(|_| STDIN_ERROR.to_owned())?; + let password = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into(); print!("Repeat password: "); flush_stdout(); - let password_repeat = read_password().map_err(|_| STDIN_ERROR.to_owned())?; + let password_repeat = read_password().map_err(|_| STDIN_ERROR.to_owned())?.into(); if password != password_repeat { return Err("Passwords do not match!".into()); @@ -300,24 +301,24 @@ pub fn password_prompt() -> Result { } /// Read a password from password file. -pub fn password_from_file(path: String) -> Result { +pub fn password_from_file(path: String) -> Result { let passwords = passwords_from_files(&[path])?; // use only first password from the file - passwords.get(0).map(String::to_owned) + passwords.get(0).map(Password::clone) .ok_or_else(|| "Password file seems to be empty.".to_owned()) } /// Reads passwords from files. Treats each line as a separate password. -pub fn passwords_from_files(files: &[String]) -> Result, String> { +pub fn passwords_from_files(files: &[String]) -> Result, String> { let passwords = files.iter().map(|filename| { let file = File::open(filename).map_err(|_| format!("{} Unable to read password file. Ensure it exists and permissions are correct.", filename))?; let reader = BufReader::new(&file); let lines = reader.lines() .filter_map(|l| l.ok()) - .map(|pwd| pwd.trim().to_owned()) - .collect::>(); + .map(|pwd| pwd.trim().to_owned().into()) + .collect::>(); Ok(lines) - }).collect::>, String>>(); + }).collect::>, String>>(); Ok(passwords?.into_iter().flat_map(|x| x).collect()) } @@ -330,6 +331,7 @@ mod tests { use ethereum_types::U256; use ethcore::client::{Mode, BlockId}; use ethcore::miner::PendingSet; + use ethkey::Password; use super::{to_duration, to_mode, to_block_id, to_u256, to_pending_set, to_address, to_addresses, to_price, geth_ipc_path, to_bootnodes, password_from_file}; #[test] @@ -435,7 +437,7 @@ ignored but the first password is trimmed "#).unwrap(); - assert_eq!(&password_from_file(path.to_str().unwrap().into()).unwrap(), "password with trailing whitespace"); + assert_eq!(password_from_file(path.to_str().unwrap().into()).unwrap(), Password::from("password with trailing whitespace")); } #[test] diff --git a/parity/presale.rs b/parity/presale.rs index 4106ad899..16af2fb82 100644 --- a/parity/presale.rs +++ b/parity/presale.rs @@ -30,7 +30,7 @@ pub struct ImportWallet { } pub fn execute(cmd: ImportWallet) -> Result { - let password: String = match cmd.password_file { + let password = match cmd.password_file { Some(file) => password_from_file(file)?, None => password_prompt()?, }; diff --git a/parity/run.rs b/parity/run.rs index 98fd8bfd4..da7a715bd 100644 --- a/parity/run.rs +++ b/parity/run.rs @@ -63,6 +63,7 @@ use rpc_apis; use secretstore; use signer; use db; +use ethkey::Password; // how often to take periodic snapshots. const SNAPSHOT_PERIOD: u64 = 5000; @@ -1002,7 +1003,7 @@ fn print_running_environment(spec_name: &String, dirs: &Directories, db_dirs: &D info!("Path to dapps {}", Colour::White.bold().paint(dapps_conf.dapps_path.to_string_lossy().into_owned())); } -fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[String]) -> Result { +fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[Password]) -> Result { use ethcore::ethstore::EthStore; use ethcore::ethstore::accounts_dir::RootDiskDirectory; @@ -1058,7 +1059,7 @@ fn insert_dev_account(account_provider: &AccountProvider) { let secret: ethkey::Secret = "4d5db4107d237df6a3d58ee5f70ae63d73d7658d4026f2eefd2f204c81682cb7".into(); let dev_account = ethkey::KeyPair::from_secret(secret.clone()).expect("Valid secret produces valid key;qed"); if !account_provider.has_account(dev_account.address()) { - match account_provider.insert_account(secret, "") { + match account_provider.insert_account(secret, &Password::from(String::new())) { Err(e) => warn!("Unable to add development account: {}", e), Ok(address) => { let _ = account_provider.set_account_name(address.clone(), "Development Account".into()); diff --git a/parity/secretstore.rs b/parity/secretstore.rs index 6fe322351..1e322e3ba 100644 --- a/parity/secretstore.rs +++ b/parity/secretstore.rs @@ -95,7 +95,7 @@ pub struct Dependencies<'a> { /// Account provider. pub account_provider: Arc, /// Passed accounts passwords. - pub accounts_passwords: &'a [String], + pub accounts_passwords: &'a [Password], } #[cfg(not(feature = "secretstore"))] @@ -209,6 +209,7 @@ mod server { } pub use self::server::KeyServer; +use ethkey::Password; impl Default for Configuration { fn default() -> Self { diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index 0e6b9d443..b0e69edfb 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -31,7 +31,7 @@ use bytes::Bytes; use parking_lot::{Mutex, RwLock}; use stats::Corpus; -use ethkey::Signature; +use ethkey::{Password, Signature}; use sync::LightSync; use ethcore::ids::BlockId; use ethcore::client::BlockChainClient; @@ -560,15 +560,15 @@ impl Future for ProspectiveSigner { } /// Single-use account token. -pub type AccountToken = String; +pub type AccountToken = Password; /// Values used to unlock accounts for signing. -#[derive(Debug, Clone, PartialEq)] +#[derive(Clone, PartialEq)] pub enum SignWith { /// Nothing -- implies the account is already unlocked. Nothing, /// Unlock with password. - Password(String), + Password(Password), /// Unlock with single-use token. Token(AccountToken), } @@ -584,8 +584,7 @@ impl SignWith { } /// A value, potentially accompanied by a signing token. -#[derive(Debug)] -pub enum WithToken { +pub enum WithToken { /// No token. No(T), /// With token. diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index d7e1fd254..5a9aef3ba 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -27,6 +27,7 @@ use jsonrpc_core::Result; use v1::helpers::errors; use v1::traits::ParityAccounts; use v1::types::{H160 as RpcH160, H256 as RpcH256, H520 as RpcH520, DappId, Derive, DeriveHierarchical, DeriveHash, ExtAccountInfo}; +use ethkey::Password; /// Account management (personal) rpc implementation. pub struct ParityAccountsClient { @@ -74,21 +75,21 @@ impl ParityAccounts for ParityAccountsClient { Ok(accounts) } - fn new_account_from_phrase(&self, phrase: String, pass: String) -> Result { + fn new_account_from_phrase(&self, phrase: String, pass: Password) -> Result { let brain = Brain::new(phrase).generate().unwrap(); self.accounts.insert_account(brain.secret().clone(), &pass) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } - fn new_account_from_wallet(&self, json: String, pass: String) -> Result { + fn new_account_from_wallet(&self, json: String, pass: Password) -> Result { self.accounts.import_presale(json.as_bytes(), &pass) .or_else(|_| self.accounts.import_wallet(json.as_bytes(), &pass, true)) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } - fn new_account_from_secret(&self, secret: RpcH256, pass: String) -> Result { + fn new_account_from_secret(&self, secret: RpcH256, pass: Password) -> Result { let secret = Secret::from_unsafe_slice(&secret.0) .map_err(|e| errors::account("Could not create account.", e))?; self.accounts.insert_account(secret, &pass) @@ -96,7 +97,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not create account.", e)) } - fn test_password(&self, account: RpcH160, password: String) -> Result { + fn test_password(&self, account: RpcH160, password: Password) -> Result { let account: Address = account.into(); self.accounts @@ -104,7 +105,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not fetch account info.", e)) } - fn change_password(&self, account: RpcH160, password: String, new_password: String) -> Result { + fn change_password(&self, account: RpcH160, password: Password, new_password: Password) -> Result { let account: Address = account.into(); self.accounts .change_password(&account, password, new_password) @@ -112,7 +113,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not fetch account info.", e)) } - fn kill_account(&self, account: RpcH160, password: String) -> Result { + fn kill_account(&self, account: RpcH160, password: Password) -> Result { let account: Address = account.into(); self.accounts .kill_account(&account, &password) @@ -209,14 +210,14 @@ impl ParityAccounts for ParityAccountsClient { Ok(into_vec(self.accounts.list_geth_accounts(false))) } - fn create_vault(&self, name: String, password: String) -> Result { + fn create_vault(&self, name: String, password: Password) -> Result { self.accounts .create_vault(&name, &password) .map_err(|e| errors::account("Could not create vault.", e)) .map(|_| true) } - fn open_vault(&self, name: String, password: String) -> Result { + fn open_vault(&self, name: String, password: Password) -> Result { self.accounts .open_vault(&name, &password) .map_err(|e| errors::account("Could not open vault.", e)) @@ -242,7 +243,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not list vaults.", e)) } - fn change_vault_password(&self, name: String, new_password: String) -> Result { + fn change_vault_password(&self, name: String, new_password: Password) -> Result { self.accounts .change_vault_password(&name, &new_password) .map_err(|e| errors::account("Could not change vault password.", e)) @@ -269,7 +270,7 @@ impl ParityAccounts for ParityAccountsClient { .map(|_| true) } - fn derive_key_index(&self, addr: RpcH160, password: String, derivation: DeriveHierarchical, save_as_account: bool) -> Result { + fn derive_key_index(&self, addr: RpcH160, password: Password, derivation: DeriveHierarchical, save_as_account: bool) -> Result { let addr: Address = addr.into(); self.accounts .derive_account( @@ -282,7 +283,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not derive account.", e)) } - fn derive_key_hash(&self, addr: RpcH160, password: String, derivation: DeriveHash, save_as_account: bool) -> Result { + fn derive_key_hash(&self, addr: RpcH160, password: Password, derivation: DeriveHash, save_as_account: bool) -> Result { let addr: Address = addr.into(); self.accounts .derive_account( @@ -295,7 +296,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not derive account.", e)) } - fn export_account(&self, addr: RpcH160, password: String) -> Result { + fn export_account(&self, addr: RpcH160, password: Password) -> Result { let addr = addr.into(); self.accounts .export_account( @@ -306,7 +307,7 @@ impl ParityAccounts for ParityAccountsClient { .map_err(|e| errors::account("Could not export account.", e)) } - fn sign_message(&self, addr: RpcH160, password: String, message: RpcH256) -> Result { + fn sign_message(&self, addr: RpcH160, password: Password, message: RpcH256) -> Result { self.accounts .sign( addr.into(), diff --git a/rpc/src/v1/impls/parity_set.rs b/rpc/src/v1/impls/parity_set.rs index 18f5776c6..e861bd3eb 100644 --- a/rpc/src/v1/impls/parity_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -119,7 +119,7 @@ impl ParitySet for ParitySetClient where } fn set_engine_signer(&self, address: H160, password: String) -> Result { - self.miner.set_author(address.into(), Some(password)).map_err(Into::into).map_err(errors::password)?; + self.miner.set_author(address.into(), Some(password.into())).map_err(Into::into).map_err(errors::password)?; Ok(true) } diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index 3a8d13c82..8cb98a66b 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -77,7 +77,7 @@ impl PersonalClient { Box::new(dispatcher.fill_optional_fields(request.into(), default, false) .and_then(move |filled| { let condition = filled.condition.clone().map(Into::into); - dispatcher.sign(accounts, filled, SignWith::Password(password)) + dispatcher.sign(accounts, filled, SignWith::Password(password.into())) .map(|tx| tx.into_value()) .map(move |tx| PendingTransaction::new(tx, condition)) .map(move |tx| (tx, dispatcher)) @@ -95,7 +95,7 @@ impl Personal for PersonalClient { } fn new_account(&self, pass: String) -> Result { - self.accounts.new_account(&pass) + self.accounts.new_account(&pass.into()) .map(Into::into) .map_err(|e| errors::account("Could not create account.", e)) } @@ -117,14 +117,14 @@ impl Personal for PersonalClient { }; let r = match (self.allow_perm_unlock, duration) { - (false, None) => store.unlock_account_temporarily(account, account_pass), + (false, None) => store.unlock_account_temporarily(account, account_pass.into()), (false, _) => return Err(errors::unsupported( "Time-unlocking is only supported in --geth compatibility mode.", Some("Restart your client with --geth flag or use personal_sendTransaction instead."), )), - (true, Some(0)) => store.unlock_account_permanently(account, account_pass), - (true, Some(d)) => store.unlock_account_timed(account, account_pass, Duration::from_secs(d.into())), - (true, None) => store.unlock_account_timed(account, account_pass, Duration::from_secs(300)), + (true, Some(0)) => store.unlock_account_permanently(account, account_pass.into()), + (true, Some(d)) => store.unlock_account_timed(account, account_pass.into(), Duration::from_secs(d.into())), + (true, None) => store.unlock_account_timed(account, account_pass.into(), Duration::from_secs(300)), }; match r { Ok(_) => Ok(true), @@ -140,7 +140,7 @@ impl Personal for PersonalClient { Box::new(dispatch::from_rpc(payload, account.into(), &dispatcher) .and_then(|payload| { - dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password)) + dispatch::execute(dispatcher, accounts, payload, dispatch::SignWith::Password(password.into())) }) .map(|v| v.into_value()) .then(|res| match res { diff --git a/rpc/src/v1/impls/secretstore.rs b/rpc/src/v1/impls/secretstore.rs index 771599eca..cbb7580e6 100644 --- a/rpc/src/v1/impls/secretstore.rs +++ b/rpc/src/v1/impls/secretstore.rs @@ -29,6 +29,7 @@ use v1::helpers::secretstore::{generate_document_key, encrypt_document, decrypt_document, decrypt_document_with_shadow, ordered_servers_keccak}; use v1::traits::SecretStore; use v1::types::{H160, H256, H512, Bytes, EncryptedDocumentKey}; +use ethkey::Password; /// Parity implementation. pub struct SecretStoreClient { @@ -44,36 +45,36 @@ impl SecretStoreClient { } /// Decrypt public key using account' private key - fn decrypt_key(&self, address: H160, password: String, key: Bytes) -> Result> { + fn decrypt_key(&self, address: H160, password: Password, key: Bytes) -> Result> { self.accounts.decrypt(address.into(), Some(password), &DEFAULT_MAC, &key.0) .map_err(|e| errors::account("Could not decrypt key.", e)) } /// Decrypt secret key using account' private key - fn decrypt_secret(&self, address: H160, password: String, key: Bytes) -> Result { + fn decrypt_secret(&self, address: H160, password: Password, key: Bytes) -> Result { self.decrypt_key(address, password, key) .and_then(|s| Secret::from_unsafe_slice(&s).map_err(|e| errors::account("invalid secret", e))) } } impl SecretStore for SecretStoreClient { - fn generate_document_key(&self, address: H160, password: String, server_key_public: H512) -> Result { + fn generate_document_key(&self, address: H160, password: Password, server_key_public: H512) -> Result { let account_public = self.accounts.account_public(address.into(), &password) .map_err(|e| errors::account("Could not read account public.", e))?; generate_document_key(account_public, server_key_public.into()) } - fn encrypt(&self, address: H160, password: String, key: Bytes, data: Bytes) -> Result { + fn encrypt(&self, address: H160, password: Password, key: Bytes, data: Bytes) -> Result { encrypt_document(self.decrypt_key(address, password, key)?, data.0) .map(Into::into) } - fn decrypt(&self, address: H160, password: String, key: Bytes, data: Bytes) -> Result { + fn decrypt(&self, address: H160, password: Password, key: Bytes, data: Bytes) -> Result { decrypt_document(self.decrypt_key(address, password, key)?, data.0) .map(Into::into) } - fn shadow_decrypt(&self, address: H160, password: String, decrypted_secret: H512, common_point: H512, decrypt_shadows: Vec, data: Bytes) -> Result { + fn shadow_decrypt(&self, address: H160, password: Password, decrypted_secret: H512, common_point: H512, decrypt_shadows: Vec, data: Bytes) -> Result { let mut shadows = Vec::with_capacity(decrypt_shadows.len()); for decrypt_shadow in decrypt_shadows { shadows.push(self.decrypt_secret(address.clone(), password.clone(), decrypt_shadow)?); @@ -87,7 +88,7 @@ impl SecretStore for SecretStoreClient { Ok(ordered_servers_keccak(servers_set)) } - fn sign_raw_hash(&self, address: H160, password: String, raw_hash: H256) -> Result { + fn sign_raw_hash(&self, address: H160, password: Password, raw_hash: H256) -> Result { self.accounts .sign(address.into(), Some(password), raw_hash.into()) .map(|s| Bytes::new((*s).to_vec())) diff --git a/rpc/src/v1/impls/signer.rs b/rpc/src/v1/impls/signer.rs index 58c48bb32..8ed046b88 100644 --- a/rpc/src/v1/impls/signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -169,7 +169,7 @@ impl Signer for SignerClient { -> BoxFuture { Box::new(self.confirm_internal(id, modification, move |dis, accounts, payload| { - dispatch::execute(dis, accounts, payload, dispatch::SignWith::Password(pass)) + dispatch::execute(dis, accounts, payload, dispatch::SignWith::Password(pass.into())) }).map(|v| v.into_value())) } @@ -177,7 +177,7 @@ impl Signer for SignerClient { -> BoxFuture { Box::new(self.confirm_internal(id, modification, move |dis, accounts, payload| { - dispatch::execute(dis, accounts, payload, dispatch::SignWith::Token(token)) + dispatch::execute(dis, accounts, payload, dispatch::SignWith::Token(token.into())) }).and_then(|v| match v { WithToken::No(_) => Err(errors::internal("Unexpected response without token.", "")), WithToken::Yes(response, token) => Ok(ConfirmationResponseWithToken { diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index 2ae9a4995..6e3b9855d 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -317,7 +317,7 @@ const POSITIVE_NONCE_SPEC: &'static [u8] = br#"{ fn eth_transaction_count() { let secret = "8a283037bb19c4fed7b1c569e40c7dcff366165eb869110a1b11532963eb9cb2".parse().unwrap(); let tester = EthTester::from_spec(Spec::load(&env::temp_dir(), TRANSACTION_COUNT_SPEC).expect("invalid chain spec")); - let address = tester.accounts.insert_account(secret, "").unwrap(); + let address = tester.accounts.insert_account(secret, &"".into()).unwrap(); tester.accounts.unlock_account_permanently(address, "".into()).unwrap(); let req_before = r#"{ diff --git a/rpc/src/v1/tests/helpers/miner_service.rs b/rpc/src/v1/tests/helpers/miner_service.rs index 63c28fb6c..ce7ffc57a 100644 --- a/rpc/src/v1/tests/helpers/miner_service.rs +++ b/rpc/src/v1/tests/helpers/miner_service.rs @@ -35,6 +35,7 @@ use miner::pool::{verifier, VerifiedTransaction, QueueStatus}; use parking_lot::{RwLock, Mutex}; use transaction::{self, UnverifiedTransaction, SignedTransaction, PendingTransaction}; use txpool; +use ethkey::Password; /// Test miner service. pub struct TestMinerService { @@ -49,7 +50,7 @@ pub struct TestMinerService { /// Next nonces. pub next_nonces: RwLock>, /// Password held by Engine. - pub password: RwLock, + pub password: RwLock, authoring_params: RwLock, } @@ -62,7 +63,7 @@ impl Default for TestMinerService { local_transactions: Mutex::new(BTreeMap::new()), pending_receipts: Mutex::new(BTreeMap::new()), next_nonces: RwLock::new(HashMap::new()), - password: RwLock::new(String::new()), + password: RwLock::new("".into()), authoring_params: RwLock::new(AuthoringParams { author: Address::zero(), gas_range_target: (12345.into(), 54321.into()), @@ -119,7 +120,7 @@ impl MinerService for TestMinerService { self.authoring_params.read().clone() } - fn set_author(&self, author: Address, password: Option) -> Result<(), AccountError> { + fn set_author(&self, author: Address, password: Option) -> Result<(), AccountError> { self.authoring_params.write().author = author; if let Some(password) = password { *self.password.write() = password; diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index 87ca18fe2..7213ad63d 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -328,7 +328,7 @@ fn rpc_eth_submit_hashrate() { fn rpc_eth_sign() { let tester = EthTester::default(); - let account = tester.accounts_provider.insert_account(Secret::from([69u8; 32]), "abcd").unwrap(); + let account = tester.accounts_provider.insert_account(Secret::from([69u8; 32]), &"abcd".into()).unwrap(); tester.accounts_provider.unlock_account_permanently(account, "abcd".into()).unwrap(); let _message = "0cc175b9c0f1b6a831c399e26977266192eb5ffee6ae2fec3ad71c777531578f".from_hex().unwrap(); @@ -362,11 +362,11 @@ fn rpc_eth_author() { assert_eq!(tester.io.handle_request_sync(req), Some(make_res(Address::zero()))); // Account set - return first account - let addr = tester.accounts_provider.new_account("123").unwrap(); + let addr = tester.accounts_provider.new_account(&"123".into()).unwrap(); assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr))); for i in 0..20 { - let addr = tester.accounts_provider.new_account(&format!("{}", i)).unwrap(); + let addr = tester.accounts_provider.new_account(&format!("{}", i).into()).unwrap(); tester.miner.set_author(addr.clone(), None).unwrap(); assert_eq!(tester.io.handle_request_sync(req), Some(make_res(addr))); @@ -394,7 +394,7 @@ fn rpc_eth_gas_price() { #[test] fn rpc_eth_accounts() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); tester.accounts_provider.set_new_dapps_addresses(None).unwrap(); tester.accounts_provider.set_address_name(1.into(), "1".into()); tester.accounts_provider.set_address_name(10.into(), "10".into()); @@ -804,7 +804,7 @@ fn rpc_eth_estimate_gas_default_block() { #[test] fn rpc_eth_send_transaction() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -855,7 +855,7 @@ fn rpc_eth_send_transaction() { #[test] fn rpc_eth_sign_transaction() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); tester.accounts_provider.unlock_account_permanently(address, "".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -912,7 +912,7 @@ fn rpc_eth_sign_transaction() { #[test] fn rpc_eth_send_transaction_with_bad_to() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", "method": "eth_sendTransaction", @@ -934,7 +934,7 @@ fn rpc_eth_send_transaction_with_bad_to() { #[test] fn rpc_eth_send_transaction_error() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("").unwrap(); + let address = tester.accounts_provider.new_account(&"".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", "method": "eth_sendTransaction", @@ -972,7 +972,7 @@ fn rpc_eth_send_raw_transaction_error() { #[test] fn rpc_eth_send_raw_transaction() { let tester = EthTester::default(); - let address = tester.accounts_provider.new_account("abcd").unwrap(); + let address = tester.accounts_provider.new_account(&"abcd".into()).unwrap(); tester.accounts_provider.unlock_account_permanently(address, "abcd".into()).unwrap(); let t = Transaction { diff --git a/rpc/src/v1/tests/mocked/parity.rs b/rpc/src/v1/tests/mocked/parity.rs index 4bb653c4d..a2db6f083 100644 --- a/rpc/src/v1/tests/mocked/parity.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -122,7 +122,7 @@ fn rpc_parity_accounts_info() { let deps = Dependencies::new(); let io = deps.default_client(); - deps.accounts.new_account("").unwrap(); + deps.accounts.new_account(&"".into()).unwrap(); let accounts = deps.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; @@ -155,7 +155,7 @@ fn rpc_parity_default_account() { assert_eq!(io.handle_request_sync(request), Some(response)); // With account - deps.accounts.new_account("").unwrap(); + deps.accounts.new_account(&"".into()).unwrap(); let accounts = deps.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs index 8342641d6..699ba01f8 100644 --- a/rpc/src/v1/tests/mocked/parity_accounts.rs +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -64,7 +64,7 @@ fn setup_with_vaults_support(temp_path: &str) -> ParityAccountsTester { #[test] fn should_be_able_to_get_account_info() { let tester = setup(); - tester.accounts.new_account("").unwrap(); + tester.accounts.new_account(&"".into()).unwrap(); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; @@ -82,7 +82,7 @@ fn should_be_able_to_get_account_info() { #[test] fn should_be_able_to_set_name() { let tester = setup(); - tester.accounts.new_account("").unwrap(); + tester.accounts.new_account(&"".into()).unwrap(); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; @@ -103,7 +103,7 @@ fn should_be_able_to_set_name() { #[test] fn should_be_able_to_set_meta() { let tester = setup(); - tester.accounts.new_account("").unwrap(); + tester.accounts.new_account(&"".into()).unwrap(); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; @@ -224,7 +224,7 @@ fn rpc_parity_recent_dapps() { #[test] fn should_be_able_to_kill_account() { let tester = setup(); - tester.accounts.new_account("password").unwrap(); + tester.accounts.new_account(&"password".into()).unwrap(); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); let address = accounts[0]; @@ -282,7 +282,7 @@ fn rpc_parity_new_vault() { assert_eq!(tester.io.handle_request_sync(request), Some(response.to_owned())); assert!(tester.accounts.close_vault("vault1").is_ok()); - assert!(tester.accounts.open_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.open_vault("vault1", &"password1".into()).is_ok()); } #[test] @@ -290,7 +290,7 @@ fn rpc_parity_open_vault() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); assert!(tester.accounts.close_vault("vault1").is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_openVault", "params":["vault1", "password1"], "id": 1}"#; @@ -304,7 +304,7 @@ fn rpc_parity_close_vault() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_closeVault", "params":["vault1"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -317,7 +317,7 @@ fn rpc_parity_change_vault_password() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_changeVaultPassword", "params":["vault1", "password2"], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -330,8 +330,8 @@ fn rpc_parity_change_vault() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - let (address, _) = tester.accounts.new_account_and_public("root_password").unwrap(); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + let (address, _) = tester.accounts.new_account_and_public(&"root_password".into()).unwrap(); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_changeVault", "params":["0x{:x}", "vault1"], "id": 1}}"#, address); let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#; @@ -344,9 +344,9 @@ fn rpc_parity_vault_adds_vault_field_to_acount_meta() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - let (address1, _) = tester.accounts.new_account_and_public("root_password1").unwrap(); + let (address1, _) = tester.accounts.new_account_and_public(&"root_password1".into()).unwrap(); let uuid1 = tester.accounts.account_meta(address1.clone()).unwrap().uuid.unwrap(); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); assert!(tester.accounts.change_vault(address1, "vault1").is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_allAccountsInfo", "params":[], "id": 1}"#; @@ -368,8 +368,8 @@ fn rpc_parity_list_vaults() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); - assert!(tester.accounts.create_vault("vault2", "password2").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); + assert!(tester.accounts.create_vault("vault2", &"password2".into()).is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_listVaults", "params":[], "id": 1}"#; let response1 = r#"{"jsonrpc":"2.0","result":["vault1","vault2"],"id":1}"#; @@ -385,9 +385,9 @@ fn rpc_parity_list_opened_vaults() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); - assert!(tester.accounts.create_vault("vault2", "password2").is_ok()); - assert!(tester.accounts.create_vault("vault3", "password3").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); + assert!(tester.accounts.create_vault("vault2", &"password2".into()).is_ok()); + assert!(tester.accounts.create_vault("vault3", &"password3".into()).is_ok()); assert!(tester.accounts.close_vault("vault2").is_ok()); let request = r#"{"jsonrpc": "2.0", "method": "parity_listOpenedVaults", "params":[], "id": 1}"#; @@ -404,7 +404,7 @@ fn rpc_parity_get_set_vault_meta() { let tempdir = TempDir::new("").unwrap(); let tester = setup_with_vaults_support(tempdir.path().to_str().unwrap()); - assert!(tester.accounts.create_vault("vault1", "password1").is_ok()); + assert!(tester.accounts.create_vault("vault1", &"password1".into()).is_ok()); // when no meta set let request = r#"{"jsonrpc": "2.0", "method": "parity_getVaultMeta", "params":["vault1"], "id": 1}"#; @@ -441,7 +441,7 @@ fn derive_key_hash() { let hash = tester.accounts .insert_account( "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a".parse().unwrap(), - "password1") + &"password1".into()) .expect("account should be inserted ok"); assert_eq!(hash, "c171033d5cbff7175f29dfd3a63dda3d6f8f385e".parse().unwrap()); @@ -461,7 +461,7 @@ fn derive_key_index() { let hash = tester.accounts .insert_account( "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a".parse().unwrap(), - "password1") + &"password1".into()) .expect("account should be inserted ok"); assert_eq!(hash, "c171033d5cbff7175f29dfd3a63dda3d6f8f385e".parse().unwrap()); @@ -478,7 +478,7 @@ fn should_export_account() { // given let tester = setup(); let wallet = r#"{"id":"6a186c80-7797-cff2-bc2e-7c1d6a6cc76e","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"a1c6ff99070f8032ca1c4e8add006373"},"ciphertext":"df27e3db64aa18d984b6439443f73660643c2d119a6f0fa2fa9a6456fc802d75","kdf":"pbkdf2","kdfparams":{"c":10240,"dklen":32,"prf":"hmac-sha256","salt":"ddc325335cda5567a1719313e73b4842511f3e4a837c9658eeb78e51ebe8c815"},"mac":"3dc888ae79cbb226ff9c455669f6cf2d79be72120f2298f6cb0d444fddc0aa3d"},"address":"0042e5d2a662eeaca8a7e828c174f98f35d8925b","name":"parity-export-test","meta":"{\"passwordHint\":\"parity-export-test\",\"timestamp\":1490017814987}"}"#; - tester.accounts.import_wallet(wallet.as_bytes(), "parity-export-test", false).unwrap(); + tester.accounts.import_wallet(wallet.as_bytes(), &"parity-export-test".into(), false).unwrap(); let accounts = tester.accounts.accounts().unwrap(); assert_eq!(accounts.len(), 1); @@ -525,7 +525,7 @@ fn should_sign_message() { let hash = tester.accounts .insert_account( "0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a0a".parse().unwrap(), - "password1") + &"password1".into()) .expect("account should be inserted ok"); assert_eq!(hash, "c171033d5cbff7175f29dfd3a63dda3d6f8f385e".parse().unwrap()); diff --git a/rpc/src/v1/tests/mocked/parity_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs index bc9f04de7..90855afe5 100644 --- a/rpc/src/v1/tests/mocked/parity_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -178,7 +178,7 @@ fn rpc_parity_set_engine_signer() { assert_eq!(io.handle_request_sync(request), Some(response.to_owned())); assert_eq!(miner.authoring_params().author, Address::from_str("cd1722f3947def4cf144679da39c4c32bdc35681").unwrap()); - assert_eq!(*miner.password.read(), "password".to_string()); + assert_eq!(*miner.password.read(), "password".into()); } #[test] diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 1e445c67a..a60914823 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -74,7 +74,7 @@ fn setup() -> PersonalTester { #[test] fn accounts() { let tester = setup(); - let address = tester.accounts.new_account("").unwrap(); + let address = tester.accounts.new_account(&"".into()).unwrap(); let request = r#"{"jsonrpc": "2.0", "method": "personal_listAccounts", "params": [], "id": 1}"#; let response = r#"{"jsonrpc":"2.0","result":[""#.to_owned() + &format!("0x{:x}", address) + r#""],"id":1}"#; @@ -99,7 +99,7 @@ fn new_account() { fn invalid_password_test(method: &str) { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -122,7 +122,7 @@ fn invalid_password_test(method: &str) #[test] fn sign() { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let data = vec![5u8]; let request = r#"{ @@ -148,7 +148,7 @@ fn sign() { #[test] fn sign_with_invalid_password() { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -188,7 +188,7 @@ fn sign_and_send_transaction() { fn sign_and_send_test(method: &str) { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -241,7 +241,7 @@ fn sign_and_send_test(method: &str) { #[test] fn ec_recover() { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let data = vec![5u8]; let hash = eth_data_hash(data.clone()); @@ -287,7 +287,7 @@ fn ec_recover_invalid_signature() { #[test] fn should_unlock_not_account_temporarily_if_allow_perm_is_disabled() { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", @@ -308,7 +308,7 @@ fn should_unlock_not_account_temporarily_if_allow_perm_is_disabled() { #[test] fn should_unlock_account_permanently() { let tester = setup(); - let address = tester.accounts.new_account("password123").unwrap(); + let address = tester.accounts.new_account(&"password123".into()).unwrap(); let request = r#"{ "jsonrpc": "2.0", diff --git a/rpc/src/v1/tests/mocked/secretstore.rs b/rpc/src/v1/tests/mocked/secretstore.rs index 33592a488..7e28a5283 100644 --- a/rpc/src/v1/tests/mocked/secretstore.rs +++ b/rpc/src/v1/tests/mocked/secretstore.rs @@ -57,7 +57,7 @@ fn rpc_secretstore_encrypt_and_decrypt() { // insert new account let secret = "c1f1cfe279a5c350d13795bce162941967340c8a228e6ba175489afc564a5bef".parse().unwrap(); - deps.accounts.insert_account(secret, "password").unwrap(); + deps.accounts.insert_account(secret, &"password".into()).unwrap(); // execute encryption request let encryption_request = r#"{"jsonrpc": "2.0", "method": "secretstore_encrypt", "params":[ @@ -87,7 +87,7 @@ fn rpc_secretstore_shadow_decrypt() { // insert new account let secret = "82758356bf46b42710d3946a8efa612b7bf5e125e4d49f28facf1139db4a46f4".parse().unwrap(); - deps.accounts.insert_account(secret, "password").unwrap(); + deps.accounts.insert_account(secret, &"password".into()).unwrap(); // execute decryption request let decryption_request = r#"{"jsonrpc": "2.0", "method": "secretstore_shadowDecrypt", "params":[ @@ -131,7 +131,7 @@ fn rpc_secretstore_sign_raw_hash() { // insert new account let secret = "82758356bf46b42710d3946a8efa612b7bf5e125e4d49f28facf1139db4a46f4".parse().unwrap(); let key_pair = KeyPair::from_secret(secret).unwrap(); - deps.accounts.insert_account(key_pair.secret().clone(), "password").unwrap(); + deps.accounts.insert_account(key_pair.secret().clone(), &"password".into()).unwrap(); // execute signing request let signing_request = r#"{"jsonrpc": "2.0", "method": "secretstore_signRawHash", "params":[ @@ -154,7 +154,7 @@ fn rpc_secretstore_generate_document_key() { // insert new account let secret = "82758356bf46b42710d3946a8efa612b7bf5e125e4d49f28facf1139db4a46f4".parse().unwrap(); let key_pair = KeyPair::from_secret(secret).unwrap(); - deps.accounts.insert_account(key_pair.secret().clone(), "password").unwrap(); + deps.accounts.insert_account(key_pair.secret().clone(), &"password".into()).unwrap(); // execute generation request let generation_request = r#"{"jsonrpc": "2.0", "method": "secretstore_generateDocumentKey", "params":[ diff --git a/rpc/src/v1/tests/mocked/signer.rs b/rpc/src/v1/tests/mocked/signer.rs index b93581842..52d5f7d8d 100644 --- a/rpc/src/v1/tests/mocked/signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -178,7 +178,7 @@ fn should_not_remove_sign_if_password_is_invalid() { fn should_confirm_transaction_and_dispatch() { //// given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest { from: address, @@ -247,7 +247,7 @@ fn should_alter_the_sender_and_nonce() { data: vec![] }; - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let signature = tester.accounts.sign(address, Some("test".into()), t.hash(None)).unwrap(); let t = t.with_signature(signature, None); @@ -274,7 +274,7 @@ fn should_alter_the_sender_and_nonce() { fn should_confirm_transaction_with_token() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest { from: address, @@ -305,7 +305,7 @@ fn should_confirm_transaction_with_token() { let request = r#"{ "jsonrpc":"2.0", "method":"signer_confirmRequestWithToken", - "params":["0x1", {"gasPrice":"0x1000"}, ""#.to_owned() + &token + r#""], + "params":["0x1", {"gasPrice":"0x1000"}, ""#.to_owned() + token.as_str() + r#""], "id":1 }"#; let response = r#"{"jsonrpc":"2.0","result":{"result":""#.to_owned() + @@ -323,7 +323,7 @@ fn should_confirm_transaction_with_token() { fn should_confirm_transaction_with_rlp() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest { from: address, @@ -370,7 +370,7 @@ fn should_confirm_transaction_with_rlp() { fn should_return_error_when_sender_does_not_match() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::SendTransaction(FilledTransactionRequest { from: Address::default(), @@ -417,7 +417,7 @@ fn should_return_error_when_sender_does_not_match() { fn should_confirm_sign_transaction_with_rlp() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let recipient = Address::from_str("d46e8dd67c5d32be8058bb8eb970870f07244567").unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::SignTransaction(FilledTransactionRequest { from: address, @@ -482,7 +482,7 @@ fn should_confirm_sign_transaction_with_rlp() { fn should_confirm_data_sign_with_signature() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::EthSignMessage( address, vec![1, 2, 3, 4].into(), @@ -512,7 +512,7 @@ fn should_confirm_data_sign_with_signature() { fn should_confirm_decrypt_with_phrase() { // given let tester = signer_tester(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); let _confirmation_future = tester.signer.add_request(ConfirmationPayload::Decrypt( address, vec![1, 2, 3, 4].into(), diff --git a/rpc/src/v1/tests/mocked/signing.rs b/rpc/src/v1/tests/mocked/signing.rs index 42d20bbf8..632d8fb76 100644 --- a/rpc/src/v1/tests/mocked/signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -212,7 +212,7 @@ fn should_sign_if_account_is_unlocked() { // given let tester = eth_signing(); let data = vec![5u8]; - let acc = tester.accounts.insert_account(Secret::from([69u8; 32]), "test").unwrap(); + let acc = tester.accounts.insert_account(Secret::from([69u8; 32]), &"test".into()).unwrap(); tester.accounts.unlock_account_permanently(acc, "test".into()).unwrap(); // when @@ -275,7 +275,7 @@ fn should_add_transaction_to_queue() { fn should_add_sign_transaction_to_the_queue() { // given let tester = eth_signing(); - let address = tester.accounts.new_account("test").unwrap(); + let address = tester.accounts.new_account(&"test".into()).unwrap(); assert_eq!(tester.signer.requests().len(), 0); @@ -354,7 +354,7 @@ fn should_add_sign_transaction_to_the_queue() { fn should_dispatch_transaction_if_account_is_unlock() { // given let tester = eth_signing(); - let acc = tester.accounts.new_account("test").unwrap(); + let acc = tester.accounts.new_account(&"test".into()).unwrap(); tester.accounts.unlock_account_permanently(acc, "test".into()).unwrap(); let t = Transaction { @@ -393,7 +393,7 @@ fn should_decrypt_message_if_account_is_unlocked() { let mut tester = eth_signing(); let parity = parity::Dependencies::new(); tester.io.extend_with(parity.client(None).to_delegate()); - let (address, public) = tester.accounts.new_account_and_public("test").unwrap(); + let (address, public) = tester.accounts.new_account_and_public(&"test".into()).unwrap(); tester.accounts.unlock_account_permanently(address, "test".into()).unwrap(); // First encrypt message diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs index 977593d44..c7bc21771 100644 --- a/rpc/src/v1/traits/parity_accounts.rs +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -18,6 +18,7 @@ use std::collections::BTreeMap; use jsonrpc_core::Result; +use ethkey::Password; use ethstore::KeyFile; use v1::types::{H160, H256, H520, DappId, DeriveHash, DeriveHierarchical, ExtAccountInfo}; @@ -31,32 +32,32 @@ build_rpc_trait! { /// Creates new account from the given phrase using standard brainwallet mechanism. /// Second parameter is password for the new account. #[rpc(name = "parity_newAccountFromPhrase")] - fn new_account_from_phrase(&self, String, String) -> Result; + fn new_account_from_phrase(&self, String, Password) -> Result; /// Creates new account from the given JSON wallet. /// Second parameter is password for the wallet and the new account. #[rpc(name = "parity_newAccountFromWallet")] - fn new_account_from_wallet(&self, String, String) -> Result; + fn new_account_from_wallet(&self, String, Password) -> Result; /// Creates new account from the given raw secret. /// Second parameter is password for the new account. #[rpc(name = "parity_newAccountFromSecret")] - fn new_account_from_secret(&self, H256, String) -> Result; + fn new_account_from_secret(&self, H256, Password) -> Result; /// Returns true if given `password` would unlock given `account`. /// Arguments: `account`, `password`. #[rpc(name = "parity_testPassword")] - fn test_password(&self, H160, String) -> Result; + fn test_password(&self, H160, Password) -> Result; /// Changes an account's password. /// Arguments: `account`, `password`, `new_password`. #[rpc(name = "parity_changePassword")] - fn change_password(&self, H160, String, String) -> Result; + fn change_password(&self, H160, Password, Password) -> Result; /// Permanently deletes an account. /// Arguments: `account`, `password`. #[rpc(name = "parity_killAccount")] - fn kill_account(&self, H160, String) -> Result; + fn kill_account(&self, H160, Password) -> Result; /// Permanently deletes an address from the addressbook /// Arguments: `address` @@ -132,11 +133,11 @@ build_rpc_trait! { /// Create new vault. #[rpc(name = "parity_newVault")] - fn create_vault(&self, String, String) -> Result; + fn create_vault(&self, String, Password) -> Result; /// Open existing vault. #[rpc(name = "parity_openVault")] - fn open_vault(&self, String, String) -> Result; + fn open_vault(&self, String, Password) -> Result; /// Close previously opened vault. #[rpc(name = "parity_closeVault")] @@ -152,7 +153,7 @@ build_rpc_trait! { /// Change vault password. #[rpc(name = "parity_changeVaultPassword")] - fn change_vault_password(&self, String, String) -> Result; + fn change_vault_password(&self, String, Password) -> Result; /// Change vault of the given address. #[rpc(name = "parity_changeVault")] @@ -169,21 +170,21 @@ build_rpc_trait! { /// Derive new address from given account address using specific hash. /// Resulting address can be either saved as a new account (with the same password). #[rpc(name = "parity_deriveAddressHash")] - fn derive_key_hash(&self, H160, String, DeriveHash, bool) -> Result; + fn derive_key_hash(&self, H160, Password, DeriveHash, bool) -> Result; /// Derive new address from given account address using /// hierarchical derivation (sequence of 32-bit integer indices). /// Resulting address can be either saved as a new account (with the same password). #[rpc(name = "parity_deriveAddressIndex")] - fn derive_key_index(&self, H160, String, DeriveHierarchical, bool) -> Result; + fn derive_key_index(&self, H160, Password, DeriveHierarchical, bool) -> Result; /// Exports an account with given address if provided password matches. #[rpc(name = "parity_exportAccount")] - fn export_account(&self, H160, String) -> Result; + fn export_account(&self, H160, Password) -> Result; /// Sign raw hash with the key corresponding to address and password. #[rpc(name = "parity_signMessage")] - fn sign_message(&self, H160, String, H256) -> Result; + fn sign_message(&self, H160, Password, H256) -> Result; /// Send a PinMatrixAck to a hardware wallet, unlocking it #[rpc(name = "parity_hardwarePinMatrixAck")] diff --git a/rpc/src/v1/traits/secretstore.rs b/rpc/src/v1/traits/secretstore.rs index e15d71a72..83f63b280 100644 --- a/rpc/src/v1/traits/secretstore.rs +++ b/rpc/src/v1/traits/secretstore.rs @@ -18,6 +18,7 @@ use std::collections::BTreeSet; use jsonrpc_core::Result; +use ethkey::Password; use v1::types::{H160, H256, H512, Bytes, EncryptedDocumentKey}; @@ -27,22 +28,22 @@ build_rpc_trait! { /// Generate document key to store in secret store. /// Arguments: `account`, `password`, `server_key_public`. #[rpc(name = "secretstore_generateDocumentKey")] - fn generate_document_key(&self, H160, String, H512) -> Result; + fn generate_document_key(&self, H160, Password, H512) -> Result; /// Encrypt data with key, received from secret store. /// Arguments: `account`, `password`, `key`, `data`. #[rpc(name = "secretstore_encrypt")] - fn encrypt(&self, H160, String, Bytes, Bytes) -> Result; + fn encrypt(&self, H160, Password, Bytes, Bytes) -> Result; /// Decrypt data with key, received from secret store. /// Arguments: `account`, `password`, `key`, `data`. #[rpc(name = "secretstore_decrypt")] - fn decrypt(&self, H160, String, Bytes, Bytes) -> Result; + fn decrypt(&self, H160, Password, Bytes, Bytes) -> Result; /// Decrypt data with shadow key, received from secret store. /// Arguments: `account`, `password`, `decrypted_secret`, `common_point`, `decrypt_shadows`, `data`. #[rpc(name = "secretstore_shadowDecrypt")] - fn shadow_decrypt(&self, H160, String, H512, H512, Vec, Bytes) -> Result; + fn shadow_decrypt(&self, H160, Password, H512, H512, Vec, Bytes) -> Result; /// Calculates the hash (keccak256) of servers set for using in ServersSetChange session. /// Returned hash must be signed later by using `secretstore_signRawHash` method. @@ -54,6 +55,6 @@ build_rpc_trait! { /// Passed hash is treated as an input to the `sign` function (no prefixes added, no hash function is applied). /// Arguments: `account`, `password`, `raw_hash`. #[rpc(name = "secretstore_signRawHash")] - fn sign_raw_hash(&self, H160, String, H256) -> Result; + fn sign_raw_hash(&self, H160, Password, H256) -> Result; } } diff --git a/rpc/src/v1/types/confirmations.rs b/rpc/src/v1/types/confirmations.rs index 7f4f3ad10..477546aa4 100644 --- a/rpc/src/v1/types/confirmations.rs +++ b/rpc/src/v1/types/confirmations.rs @@ -23,6 +23,7 @@ use bytes::ToPretty; use v1::types::{U256, TransactionRequest, RichRawTransaction, H160, H256, H520, Bytes, TransactionCondition, Origin}; use v1::helpers; +use ethkey::Password; /// Confirmation waiting in a queue #[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)] @@ -149,12 +150,12 @@ impl Serialize for ConfirmationResponse { } /// Confirmation response with additional token for further requests -#[derive(Debug, Clone, PartialEq, Serialize)] +#[derive(Clone, PartialEq, Serialize)] pub struct ConfirmationResponseWithToken { /// Actual response pub result: ConfirmationResponse, /// New token - pub token: String, + pub token: Password, } /// Confirmation payload, i.e. the thing to be confirmed diff --git a/secret_store/src/node_key_pair.rs b/secret_store/src/node_key_pair.rs index 93cf285b2..d96d9ff61 100644 --- a/secret_store/src/node_key_pair.rs +++ b/secret_store/src/node_key_pair.rs @@ -20,6 +20,7 @@ use ethkey::{KeyPair, Public, Signature, Error as EthKeyError, sign, public_to_a use ethcore::account_provider::AccountProvider; use ethereum_types::{H256, Address}; use traits::NodeKeyPair; +use ethkey::Password; pub struct PlainNodeKeyPair { key_pair: KeyPair, @@ -29,7 +30,7 @@ pub struct KeyStoreNodeKeyPair { account_provider: Arc, address: Address, public: Public, - password: String, + password: Password, } impl PlainNodeKeyPair { @@ -61,7 +62,7 @@ impl NodeKeyPair for PlainNodeKeyPair { } impl KeyStoreNodeKeyPair { - pub fn new(account_provider: Arc, address: Address, password: String) -> Result { + pub fn new(account_provider: Arc, address: Address, password: Password) -> Result { let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?; Ok(KeyStoreNodeKeyPair { account_provider: account_provider, diff --git a/util/mem/src/lib.rs b/util/mem/src/lib.rs index db3ad5923..735a58cd2 100644 --- a/util/mem/src/lib.rs +++ b/util/mem/src/lib.rs @@ -31,11 +31,9 @@ impl> From for Memzero { impl> Drop for Memzero { fn drop(&mut self) { - let n = self.mem.as_mut().len(); - let p = self.mem.as_mut().as_mut_ptr(); - for i in 0..n { - unsafe { - ptr::write_volatile(p.offset(i as isize), 0) + unsafe { + for byte_ref in self.mem.as_mut() { + ptr::write_volatile(byte_ref, 0) } } }