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`.
This commit is contained in:
Toralf Wittner 2018-06-22 15:09:15 +02:00 committed by David
parent c473ab97c7
commit 41348dead4
61 changed files with 550 additions and 457 deletions

2
Cargo.lock generated
View File

@ -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)",
]

View File

@ -56,9 +56,9 @@ impl<T> Keccak256<[u8; 32]> for T where T: AsRef<[u8]> {
}
}
pub fn derive_key_iterations(password: &str, salt: &[u8; 32], c: u32) -> (Vec<u8>, Vec<u8>) {
pub fn derive_key_iterations(password: &[u8], salt: &[u8; 32], c: u32) -> (Vec<u8>, Vec<u8>) {
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())

View File

@ -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<u8>, Vec<u8>), ScryptError> {
pub fn derive_key(pass: &[u8], salt: &[u8; 32], n: u32, p: u32, r: u32) -> Result<(Vec<u8>, Vec<u8>), 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()))

View File

@ -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<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<String>,
pub passwords: Vec<Password>,
}
struct EncryptionSession {

View File

@ -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<Address>,
/// Passwords used to unlock accounts
pub passwords: Vec<String>,
pub passwords: Vec<Password>,
}
#[derive(Debug)]
@ -121,7 +122,7 @@ pub struct Provider {
encryptor: Box<Encryptor>,
validator_accounts: HashSet<Address>,
signer_account: Option<Address>,
passwords: Vec<String>,
passwords: Vec<Password>,
notify: RwLock<Vec<Weak<ChainNotify>>>,
transactions_for_signing: Mutex<SigningStore>,
// TODO [ToDr] Move the Mutex/RwLock inside `VerificationStore` after refactored to `drain`.
@ -670,7 +671,7 @@ impl Importer for Arc<Provider> {
}
/// Try to unlock account using stored password, return found password if any
fn find_account_password(passwords: &Vec<String>, account_provider: &AccountProvider, account: &Address) -> Option<String> {
fn find_account_password(passwords: &Vec<Password>, account_provider: &AccountProvider, account: &Address) -> Option<Password> {
for password in passwords {
if let Ok(true) = account_provider.test_password(account, password) {
return Some(password.clone());

View File

@ -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()],

View File

@ -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<Address, Error> {
pub fn new_account(&self, password: &Password) -> Result<Address, Error> {
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<Address, Error> {
pub fn insert_account(&self, secret: Secret, password: &Password) -> Result<Address, Error> {
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<String>, derivation: Derivation, save: bool)
pub fn derive_account(&self, address: &Address, password: Option<Password>, derivation: Derivation, save: bool)
-> Result<Address, SignError>
{
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<Address, Error> {
pub fn import_presale(&self, presale_json: &[u8], password: &Password) -> Result<Address, Error> {
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<Address, Error> {
pub fn import_wallet(&self, json: &[u8], password: &Password, gen_id: bool) -> Result<Address, Error> {
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<Public, Error> {
pub fn account_public(&self, address: Address, password: &Password) -> Result<Public, Error> {
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<bool, Error> {
pub fn test_password(&self, address: &Address, password: &Password) -> Result<bool, Error> {
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<KeyFile, Error> {
pub fn export_account(&self, address: &Address, password: Password) -> Result<KeyFile, Error> {
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<String, SignError> {
fn password(&self, account: &StoreAccountRef) -> Result<Password, SignError> {
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<String>, message: Message) -> Result<Signature, SignError> {
pub fn sign(&self, address: Address, password: Option<Password>, message: Message) -> Result<Signature, SignError> {
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<String>, derivation: Derivation, message: Message)
pub fn sign_derived(&self, address: &Address, password: Option<Password>, derivation: Derivation, message: Message)
-> Result<Signature, SignError>
{
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<String>, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, SignError> {
pub fn decrypt(&self, address: Address, password: Option<Password>, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, 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<String>, other_public: &Public) -> Result<Secret, SignError> {
pub fn agree(&self, address: Address, password: Option<Password>, other_public: &Public) -> Result<Secret, SignError> {
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

View File

@ -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<EthereumMachine> for AuthorityRound {
self.validators.register_client(client);
}
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
fn set_signer(&self, ap: Arc<AccountProvider>, 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::<U256>().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();

View File

@ -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<EthereumMachine> for BasicAuthority {
self.validators.register_client(client);
}
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
fn set_signer(&self, ap: Arc<AccountProvider>, 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());

View File

@ -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<M: Machine>: 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<AccountProvider>, _address: Address, _password: String) {}
fn set_signer(&self, _account_provider: Arc<AccountProvider>, _address: Address, _password: Password) {}
/// Sign using the EngineSigner, to be used for consensus tx signing.
fn sign(&self, _hash: H256) -> Result<Signature, M::Error> { unimplemented!() }

View File

@ -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<AccountProvider>,
address: Option<Address>,
password: Option<String>,
password: Option<Password>,
}
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<AccountProvider>, address: Address, password: String) {
pub fn set(&mut self, ap: Arc<AccountProvider>, address: Address, password: Password) {
self.account_provider = ap;
self.address = Some(address);
self.password = Some(password);

View File

@ -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()));

View File

@ -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<EthereumMachine> for Tendermint {
}
}
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: String) {
fn set_signer(&self, ap: Arc<AccountProvider>, address: Address, password: Password) {
{
self.signer.write().set(ap, address, password);
}
@ -831,7 +831,7 @@ mod tests {
}
fn insert_and_unlock(tap: &Arc<AccountProvider>, 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
}

View File

@ -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::<Address>().unwrap();

View File

@ -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 _);

View File

@ -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 _);

View File

@ -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<String>) -> Result<(), AccountError> {
fn set_author(&self, address: Address, password: Option<Password>) -> 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 });
}

View File

@ -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<String>) -> Result<(), ::account_provider::SignError>;
fn set_author(&self, address: Address, password: Option<Password>) -> Result<(), ::account_provider::SignError>;
// Transaction Pool

View File

@ -71,7 +71,7 @@ fn make_accounts(secrets: &[Secret]) -> (Arc<AccountProvider>, Vec<Address>) {
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)

View File

@ -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<IoHandler<ClientIoMessage>> = 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));

View File

@ -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<IoHandler<ClientIoMessage>> = 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)));

View File

@ -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"

View File

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

60
ethkey/src/password.rs Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
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<String> 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))
}
}

View File

@ -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<String>, wallet_path: &str) -> Result<(), Error> {
pub fn run(passwords: VecDeque<Password>, 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<String>, wallet_path: &str) -> Result<(), Error>
Ok(())
}
fn look_for_password(passwords: Arc<Mutex<VecDeque<String>>>, wallet: PresaleWallet) {
fn look_for_password(passwords: Arc<Mutex<VecDeque<Password>>>, wallet: PresaleWallet) {
let mut counter = 0;
while !passwords.lock().is_empty() {
let package = {
@ -54,7 +54,7 @@ fn look_for_password(passwords: Arc<Mutex<VecDeque<String>>>, wallet: PresaleWal
counter += 1;
match wallet.decrypt(&pass) {
Ok(_) => {
println!("Found password: {}", &pass);
println!("Found password: {}", pass.as_str());
passwords.lock().clear();
return;
},

View File

@ -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<String, Error> {
fn load_password(path: &str) -> Result<Password, Error> {
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<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item=S>, S: AsRef<str> {
@ -252,7 +252,7 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
Ok(format!("0x{:x}", account_ref.address))
} else if args.cmd_find_wallet_pass {
let passwords = load_password(&args.arg_password)?;
let passwords = passwords.lines().map(str::to_owned).collect::<VecDeque<_>>();
let passwords = passwords.as_str().lines().map(|line| str::to_owned(line).into()).collect::<VecDeque<_>>();
crack::run(passwords, &args.arg_path)?;
Ok(format!("Password not found."))
} else if args.cmd_remove {

View File

@ -15,7 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<Crypto> for String {
impl Crypto {
/// Encrypt account secret
pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Result<Self, crypto::Error> {
pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
Crypto::with_plain(&*secret, password, iterations)
}
/// Encrypt custom plain data
pub fn with_plain(plain: &[u8], password: &str, iterations: u32) -> Result<Self, crypto::Error> {
pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
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<Secret, Error> {
pub fn secret(&self, password: &Password) -> Result<Secret, Error> {
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<Vec<u8>, Error> {
pub fn decrypt(&self, password: &Password) -> Result<Vec<u8>, Error> {
let expected_len = self.ciphertext.len();
self.do_decrypt(password, expected_len)
}
fn do_decrypt(&self, password: &str, expected_len: usize) -> Result<Vec<u8>, Error> {
fn do_decrypt(&self, password: &Password, expected_len: usize) -> Result<Vec<u8>, Error> {
let (derived_left_bits, derived_right_bits) = match self.kdf {
Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password, &params.salt, params.c),
Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password, &params.salt, params.n, params.p, params.r)?,
Kdf::Pbkdf2(ref params) => crypto::derive_key_iterations(password.as_bytes(), &params.salt, params.c),
Kdf::Scrypt(ref params) => crypto::scrypt::derive_key(password.as_bytes(), &params.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);
}
}

View File

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
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<String>) -> Result<Self, Error> {
pub fn from_vault_file(password: &Password, json: json::VaultKeyFile, filename: Option<String>) -> Result<Self, Error> {
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<json::VaultKeyFile, Error> {
pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result<json::VaultKeyFile, Error> {
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<Signature, Error> {
pub fn sign(&self, password: &Password, message: &Message) -> Result<Signature, Error> {
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<Vec<u8>, Error> {
pub fn decrypt(&self, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, 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<Secret, Error> {
pub fn agree(&self, password: &Password, other: &Public) -> Result<Secret, Error> {
let secret = self.crypto.secret(password)?;
agree(&secret, other).map_err(From::from)
}
/// Derive public key.
pub fn public(&self, password: &str) -> Result<Public, Error> {
pub fn public(&self, password: &Password) -> Result<Public, Error> {
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<Self, Error> {
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result<Self, Error> {
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());
}
}

View File

@ -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");

View File

@ -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,
}
}

View File

@ -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<P>(vault_dir_path: P, key: &VaultKey, meta: &str) -> Result<(), Error> where P: AsRef<Path> {
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<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<Strin
if let Some(key) = key {
let password_bytes = vault_file_crypto.decrypt(&key.password)?;
let password_hash = key.password.keccak256();
let password_hash = key.password.as_bytes().keccak256();
if password_hash != password_bytes.as_slice() {
return Err(Error::InvalidPassword);
}
@ -323,7 +323,7 @@ mod test {
fn create_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let key = VaultKey::new(&"password".into(), 1024);
let mut vault_dir: PathBuf = temp_path.path().into();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
@ -342,7 +342,7 @@ mod test {
fn read_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let key = VaultKey::new(&"password".into(), 1024);
let vault_file_contents = r#"{"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"758696c8dc6378ab9b25bb42790da2f5"},"ciphertext":"54eb50683717d41caaeb12ea969f2c159daada5907383f26f327606a37dc7168","kdf":"pbkdf2","kdfparams":{"c":1024,"dklen":32,"prf":"hmac-sha256","salt":"3c320fa566a1a7963ac8df68a19548d27c8f40bf92ef87c84594dcd5bbc402b6"},"mac":"9e5c2314c2a0781962db85611417c614bd6756666b6b1e93840f5b6ed895f003"}}"#;
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
@ -363,7 +363,7 @@ mod test {
fn read_vault_file_fails() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password1", 1024);
let key = VaultKey::new(&"password1".into(), 1024);
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
@ -392,7 +392,7 @@ mod test {
fn vault_directory_can_be_created() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
// when
@ -412,7 +412,7 @@ mod test {
fn vault_directory_cannot_be_created_if_already_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
@ -429,7 +429,7 @@ mod test {
fn vault_directory_cannot_be_opened_if_not_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let key = VaultKey::new(&"password".into(), 1024);
let dir: PathBuf = temp_path.path().into();
// when

View File

@ -22,7 +22,7 @@ use std::time::{Instant, Duration};
use crypto::KEY_ITERATIONS;
use random::Random;
use ethkey::{self, Signature, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair};
use ethkey::{self, Signature, Password, Address, Message, Secret, Public, KeyPair, ExtendedKeyPair};
use accounts_dir::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError};
use account::SafeAccount;
use presale::PresaleWallet;
@ -64,17 +64,17 @@ impl EthStore {
}
impl SimpleSecretStore for EthStore {
fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &str) -> Result<StoreAccountRef, Error> {
fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result<StoreAccountRef, Error> {
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<StoreAccountRef, Error>
{
self.store.insert_derived(vault, account_ref, password, derivation)
}
fn generate_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation) -> Result<Address, Error> {
fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result<Address, Error> {
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<OpaqueKeyFile, Error> {
fn export_account(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueKeyFile, Error> {
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<Signature, Error> {
fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result<Signature, Error> {
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<Signature, Error>
{
self.store.sign_derived(account_ref, password, derivation, message)
}
fn agree(&self, account: &StoreAccountRef, password: &str, other: &Public) -> Result<Secret, Error> {
fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result<Secret, Error> {
self.store.agree(account, password, other)
}
fn decrypt(&self, account: &StoreAccountRef, password: &str, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error> {
fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, 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<OpaqueSecret, Error> {
fn raw_secret(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueSecret, Error> {
Ok(OpaqueSecret(self.get(account)?.crypto.secret(password)?))
}
fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result<StoreAccountRef, Error> {
fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &Password) -> Result<StoreAccountRef, Error> {
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<StoreAccountRef, Error> {
fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &Password, gen_id: bool) -> Result<StoreAccountRef, Error> {
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<bool, Error> {
fn test_password(&self, account: &StoreAccountRef, password: &Password) -> Result<bool, Error> {
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<Public, Error> {
fn public(&self, account: &StoreAccountRef, password: &Password) -> Result<Public, Error> {
let account = self.get(account)?;
account.public(password)
}
@ -365,7 +365,7 @@ impl EthMultiStore {
}
}
fn get_matching(&self, account: &StoreAccountRef, password: &str) -> Result<Vec<SafeAccount>, Error> {
fn get_matching(&self, account: &StoreAccountRef, password: &Password) -> Result<Vec<SafeAccount>, 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<StoreAccountRef, Error> {
fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result<StoreAccountRef, Error> {
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<StoreAccountRef, Error>
{
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<Address, Error>
{
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<Signature, Error>
{
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<OpaqueKeyFile, Error> {
fn export_account(&self, account_ref: &StoreAccountRef, password: &Password) -> Result<OpaqueKeyFile, Error> {
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<Signature, Error> {
fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result<Signature, Error> {
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<Vec<u8>, Error> {
fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, 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<Secret, Error> {
fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result<Secret, Error> {
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);

View File

@ -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<KeyPair, Error> {
pub fn decrypt(&self, password: &Password) -> Result<KeyPair, Error> {
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());
}
}

View File

@ -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<Address> 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<StoreAccountRef, Error>;
fn insert_account(&self, vault: SecretVaultRef, secret: Secret, password: &Password) -> Result<StoreAccountRef, Error>;
/// 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<StoreAccountRef, Error>;
fn insert_derived(&self, vault: SecretVaultRef, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result<StoreAccountRef, Error>;
/// 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<OpaqueKeyFile, Error>;
fn export_account(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueKeyFile, Error>;
/// 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<Address, Error>;
fn generate_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation) -> Result<Address, Error>;
/// Sign a message with given account.
fn sign(&self, account: &StoreAccountRef, password: &str, message: &Message) -> Result<Signature, Error>;
fn sign(&self, account: &StoreAccountRef, password: &Password, message: &Message) -> Result<Signature, Error>;
/// Sign a message with derived account.
fn sign_derived(&self, account_ref: &StoreAccountRef, password: &str, derivation: Derivation, message: &Message) -> Result<Signature, Error>;
fn sign_derived(&self, account_ref: &StoreAccountRef, password: &Password, derivation: Derivation, message: &Message) -> Result<Signature, Error>;
/// Decrypt a messages with given account.
fn decrypt(&self, account: &StoreAccountRef, password: &str, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error>;
fn decrypt(&self, account: &StoreAccountRef, password: &Password, shared_mac: &[u8], message: &[u8]) -> Result<Vec<u8>, Error>;
/// Agree on shared key.
fn agree(&self, account: &StoreAccountRef, password: &str, other: &Public) -> Result<Secret, Error>;
fn agree(&self, account: &StoreAccountRef, password: &Password, other: &Public) -> Result<Secret, Error>;
/// Returns all accounts in this secret store.
fn accounts(&self) -> Result<Vec<StoreAccountRef>, Error>;
@ -83,9 +83,9 @@ pub trait SimpleSecretStore: Send + Sync {
fn account_ref(&self, address: &Address) -> Result<StoreAccountRef, Error>;
/// 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<Vec<String>, 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<StoreAccountRef, Error>;
/// 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<OpaqueSecret, Error>;
fn raw_secret(&self, account: &StoreAccountRef, password: &Password) -> Result<OpaqueSecret, Error>;
/// Signs a message with raw secret.
fn sign_with_secret(&self, secret: &OpaqueSecret, message: &Message) -> Result<Signature, Error> {
@ -114,16 +114,16 @@ pub trait SecretStore: SimpleSecretStore {
}
/// Imports presale wallet
fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &str) -> Result<StoreAccountRef, Error>;
fn import_presale(&self, vault: SecretVaultRef, json: &[u8], password: &Password) -> Result<StoreAccountRef, Error>;
/// Imports existing JSON wallet
fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &str, gen_id: bool) -> Result<StoreAccountRef, Error>;
fn import_wallet(&self, vault: SecretVaultRef, json: &[u8], password: &Password, gen_id: bool) -> Result<StoreAccountRef, Error>;
/// 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<bool, Error>;
fn test_password(&self, account: &StoreAccountRef, password: &Password) -> Result<bool, Error>;
/// Returns a public key for given account.
fn public(&self, account: &StoreAccountRef, password: &str) -> Result<Public, Error>;
fn public(&self, account: &StoreAccountRef, password: &Password) -> Result<Public, Error>;
/// Returns uuid of an account.
fn uuid(&self, account: &StoreAccountRef) -> Result<Uuid, Error>;

View File

@ -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());

View File

@ -85,7 +85,7 @@ fn secret_store(dir: Box<RootDiskDirectory>, iterations: Option<u32>) -> Result<
}
fn new(n: NewAccount) -> Result<String, String> {
let password: String = match n.password_file {
let password = match n.password_file {
Some(file) => password_from_file(file)?,
None => password_prompt()?,
};

View File

@ -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<Duration, String> {
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<String, String> {
pub fn password_prompt() -> Result<Password, String> {
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<String, String> {
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<String, String> {
}
/// Read a password from password file.
pub fn password_from_file(path: String) -> Result<String, String> {
pub fn password_from_file(path: String) -> Result<Password, String> {
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<Vec<String>, String> {
pub fn passwords_from_files(files: &[String]) -> Result<Vec<Password>, 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::<Vec<String>>();
.map(|pwd| pwd.trim().to_owned().into())
.collect::<Vec<Password>>();
Ok(lines)
}).collect::<Result<Vec<Vec<String>>, String>>();
}).collect::<Result<Vec<Vec<Password>>, 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]

View File

@ -30,7 +30,7 @@ pub struct ImportWallet {
}
pub fn execute(cmd: ImportWallet) -> Result<String, String> {
let password: String = match cmd.password_file {
let password = match cmd.password_file {
Some(file) => password_from_file(file)?,
None => password_prompt()?,
};

View File

@ -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<AccountProvider, String> {
fn prepare_account_provider(spec: &SpecType, dirs: &Directories, data_dir: &str, cfg: AccountsConfig, passwords: &[Password]) -> Result<AccountProvider, String> {
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());

View File

@ -95,7 +95,7 @@ pub struct Dependencies<'a> {
/// Account provider.
pub account_provider: Arc<AccountProvider>,
/// 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 {

View File

@ -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<T: Debug> {
pub enum WithToken<T> {
/// No token.
No(T),
/// With token.

View File

@ -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<RpcH160> {
fn new_account_from_phrase(&self, phrase: String, pass: Password) -> Result<RpcH160> {
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<RpcH160> {
fn new_account_from_wallet(&self, json: String, pass: Password) -> Result<RpcH160> {
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<RpcH160> {
fn new_account_from_secret(&self, secret: RpcH256, pass: Password) -> Result<RpcH160> {
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<bool> {
fn test_password(&self, account: RpcH160, password: Password) -> Result<bool> {
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<bool> {
fn change_password(&self, account: RpcH160, password: Password, new_password: Password) -> Result<bool> {
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<bool> {
fn kill_account(&self, account: RpcH160, password: Password) -> Result<bool> {
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<bool> {
fn create_vault(&self, name: String, password: Password) -> Result<bool> {
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<bool> {
fn open_vault(&self, name: String, password: Password) -> Result<bool> {
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<bool> {
fn change_vault_password(&self, name: String, new_password: Password) -> Result<bool> {
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<RpcH160> {
fn derive_key_index(&self, addr: RpcH160, password: Password, derivation: DeriveHierarchical, save_as_account: bool) -> Result<RpcH160> {
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<RpcH160> {
fn derive_key_hash(&self, addr: RpcH160, password: Password, derivation: DeriveHash, save_as_account: bool) -> Result<RpcH160> {
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<KeyFile> {
fn export_account(&self, addr: RpcH160, password: Password) -> Result<KeyFile> {
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<RpcH520> {
fn sign_message(&self, addr: RpcH160, password: Password, message: RpcH256) -> Result<RpcH520> {
self.accounts
.sign(
addr.into(),

View File

@ -119,7 +119,7 @@ impl<C, M, U, F> ParitySet for ParitySetClient<C, M, U, F> where
}
fn set_engine_signer(&self, address: H160, password: String) -> Result<bool> {
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)
}

View File

@ -77,7 +77,7 @@ impl<D: Dispatcher + 'static> PersonalClient<D> {
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<D: Dispatcher + 'static> Personal for PersonalClient<D> {
}
fn new_account(&self, pass: String) -> Result<RpcH160> {
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<D: Dispatcher + 'static> Personal for PersonalClient<D> {
};
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<D: Dispatcher + 'static> Personal for PersonalClient<D> {
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 {

View File

@ -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<Vec<u8>> {
fn decrypt_key(&self, address: H160, password: Password, key: Bytes) -> Result<Vec<u8>> {
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<Secret> {
fn decrypt_secret(&self, address: H160, password: Password, key: Bytes) -> Result<Secret> {
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<EncryptedDocumentKey> {
fn generate_document_key(&self, address: H160, password: Password, server_key_public: H512) -> Result<EncryptedDocumentKey> {
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<Bytes> {
fn encrypt(&self, address: H160, password: Password, key: Bytes, data: Bytes) -> Result<Bytes> {
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<Bytes> {
fn decrypt(&self, address: H160, password: Password, key: Bytes, data: Bytes) -> Result<Bytes> {
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<Bytes>, data: Bytes) -> Result<Bytes> {
fn shadow_decrypt(&self, address: H160, password: Password, decrypted_secret: H512, common_point: H512, decrypt_shadows: Vec<Bytes>, data: Bytes) -> Result<Bytes> {
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<Bytes> {
fn sign_raw_hash(&self, address: H160, password: Password, raw_hash: H256) -> Result<Bytes> {
self.accounts
.sign(address.into(), Some(password), raw_hash.into())
.map(|s| Bytes::new((*s).to_vec()))

View File

@ -169,7 +169,7 @@ impl<D: Dispatcher + 'static> Signer for SignerClient<D> {
-> BoxFuture<ConfirmationResponse>
{
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<D: Dispatcher + 'static> Signer for SignerClient<D> {
-> BoxFuture<ConfirmationResponseWithToken>
{
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 {

View File

@ -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#"{

View File

@ -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<HashMap<Address, U256>>,
/// Password held by Engine.
pub password: RwLock<String>,
pub password: RwLock<Password>,
authoring_params: RwLock<AuthoringParams>,
}
@ -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<String>) -> Result<(), AccountError> {
fn set_author(&self, author: Address, password: Option<Password>) -> Result<(), AccountError> {
self.authoring_params.write().author = author;
if let Some(password) = password {
*self.password.write() = password;

View File

@ -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 {

View File

@ -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];

View File

@ -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());

View File

@ -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]

View File

@ -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",

View File

@ -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":[

View File

@ -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(),

View File

@ -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

View File

@ -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<H160>;
fn new_account_from_phrase(&self, String, Password) -> Result<H160>;
/// 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<H160>;
fn new_account_from_wallet(&self, String, Password) -> Result<H160>;
/// 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<H160>;
fn new_account_from_secret(&self, H256, Password) -> Result<H160>;
/// Returns true if given `password` would unlock given `account`.
/// Arguments: `account`, `password`.
#[rpc(name = "parity_testPassword")]
fn test_password(&self, H160, String) -> Result<bool>;
fn test_password(&self, H160, Password) -> Result<bool>;
/// Changes an account's password.
/// Arguments: `account`, `password`, `new_password`.
#[rpc(name = "parity_changePassword")]
fn change_password(&self, H160, String, String) -> Result<bool>;
fn change_password(&self, H160, Password, Password) -> Result<bool>;
/// Permanently deletes an account.
/// Arguments: `account`, `password`.
#[rpc(name = "parity_killAccount")]
fn kill_account(&self, H160, String) -> Result<bool>;
fn kill_account(&self, H160, Password) -> Result<bool>;
/// 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<bool>;
fn create_vault(&self, String, Password) -> Result<bool>;
/// Open existing vault.
#[rpc(name = "parity_openVault")]
fn open_vault(&self, String, String) -> Result<bool>;
fn open_vault(&self, String, Password) -> Result<bool>;
/// 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<bool>;
fn change_vault_password(&self, String, Password) -> Result<bool>;
/// 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<H160>;
fn derive_key_hash(&self, H160, Password, DeriveHash, bool) -> Result<H160>;
/// 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<H160>;
fn derive_key_index(&self, H160, Password, DeriveHierarchical, bool) -> Result<H160>;
/// Exports an account with given address if provided password matches.
#[rpc(name = "parity_exportAccount")]
fn export_account(&self, H160, String) -> Result<KeyFile>;
fn export_account(&self, H160, Password) -> Result<KeyFile>;
/// Sign raw hash with the key corresponding to address and password.
#[rpc(name = "parity_signMessage")]
fn sign_message(&self, H160, String, H256) -> Result<H520>;
fn sign_message(&self, H160, Password, H256) -> Result<H520>;
/// Send a PinMatrixAck to a hardware wallet, unlocking it
#[rpc(name = "parity_hardwarePinMatrixAck")]

View File

@ -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<EncryptedDocumentKey>;
fn generate_document_key(&self, H160, Password, H512) -> Result<EncryptedDocumentKey>;
/// 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<Bytes>;
fn encrypt(&self, H160, Password, Bytes, Bytes) -> Result<Bytes>;
/// 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<Bytes>;
fn decrypt(&self, H160, Password, Bytes, Bytes) -> Result<Bytes>;
/// 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>, Bytes) -> Result<Bytes>;
fn shadow_decrypt(&self, H160, Password, H512, H512, Vec<Bytes>, Bytes) -> Result<Bytes>;
/// 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<Bytes>;
fn sign_raw_hash(&self, H160, Password, H256) -> Result<Bytes>;
}
}

View File

@ -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

View File

@ -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<AccountProvider>,
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<AccountProvider>, address: Address, password: String) -> Result<Self, EthKeyError> {
pub fn new(account_provider: Arc<AccountProvider>, address: Address, password: Password) -> Result<Self, EthKeyError> {
let public = account_provider.account_public(address.clone(), &password).map_err(|e| EthKeyError::Custom(format!("{}", e)))?;
Ok(KeyStoreNodeKeyPair {
account_provider: account_provider,

View File

@ -31,11 +31,9 @@ impl<T: AsMut<[u8]>> From<T> for Memzero<T> {
impl<T: AsMut<[u8]>> Drop for Memzero<T> {
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)
}
}
}