easy to use conversion from and to string for ethstore::Crypto (#5437)

* easy to use conversion from and to string for ethstore::Crypto

* ethstore uses tempdir instead of devtools

* ethstore does not depend on ethcore-util
This commit is contained in:
Marek Kotewicz 2017-04-11 16:24:56 +08:00 committed by Gav Wood
parent d3b2bcdd79
commit 4f8e61dce9
10 changed files with 82 additions and 47 deletions

4
Cargo.lock generated
View File

@ -784,8 +784,7 @@ name = "ethstore"
version = "0.1.0"
dependencies = [
"docopt 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ethcore-devtools 1.7.0",
"ethcore-util 1.7.0",
"ethcore-bigint 0.1.2",
"ethcrypto 0.1.0",
"ethkey 0.2.0",
"itertools 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
@ -800,6 +799,7 @@ dependencies = [
"serde_derive 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)",
"tiny-keccak 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -94,11 +94,11 @@ pub trait Keccak256<T> {
fn keccak256(&self) -> T where T: Sized;
}
impl Keccak256<[u8; 32]> for [u8] {
impl<T> Keccak256<[u8; 32]> for T where T: AsRef<[u8]> {
fn keccak256(&self) -> [u8; 32] {
let mut keccak = Keccak::new_keccak256();
let mut result = [0u8; 32];
keccak.update(self);
keccak.update(self.as_ref());
keccak.finalize(&mut result);
result
}

View File

@ -19,10 +19,10 @@ time = "0.1.34"
itertools = "0.5"
parking_lot = "0.4"
ethcrypto = { path = "../ethcrypto" }
ethcore-util = { path = "../util" }
ethcore-bigint = { path = "../util/bigint" }
smallvec = "0.3.1"
ethcore-devtools = { path = "../devtools" }
parity-wordlist = "1.0"
tempdir = "0.3"
[features]
cli = ["docopt"]

View File

@ -15,6 +15,7 @@
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use std::iter::repeat;
use std::str;
use ethkey::Secret;
use {json, Error, crypto};
use crypto::Keccak256;
@ -46,17 +47,31 @@ impl From<json::Crypto> for Crypto {
}
}
impl Into<json::Crypto> for Crypto {
fn into(self) -> json::Crypto {
impl From<Crypto> for json::Crypto {
fn from(c: Crypto) -> Self {
json::Crypto {
cipher: self.cipher.into(),
ciphertext: self.ciphertext.into(),
kdf: self.kdf.into(),
mac: self.mac.into(),
cipher: c.cipher.into(),
ciphertext: c.ciphertext.into(),
kdf: c.kdf.into(),
mac: c.mac.into(),
}
}
}
impl str::FromStr for Crypto {
type Err = <json::Crypto as str::FromStr>::Err;
fn from_str(s: &str) -> Result<Self, Self::Err> {
s.parse::<json::Crypto>().map(Into::into)
}
}
impl From<Crypto> for String {
fn from(c: Crypto) -> Self {
json::Crypto::from(c).into()
}
}
impl Crypto {
pub fn with_secret(secret: &Secret, password: &str, iterations: u32) -> Self {
Crypto::with_plain(&*secret, password, iterations)

View File

@ -225,8 +225,8 @@ impl<T> KeyDirectory for DiskDirectory<T> where T: KeyFileManager {
Some(self)
}
fn unique_repr(&self) -> Result<u64, Error> {
self.files_hash()
fn unique_repr(&self) -> Result<u64, Error> {
self.files_hash()
}
}
@ -280,12 +280,14 @@ impl KeyFileManager for DiskKeyFileManager {
#[cfg(test)]
mod test {
extern crate tempdir;
use std::{env, fs};
use super::RootDiskDirectory;
use dir::{KeyDirectory, VaultKey};
use account::SafeAccount;
use ethkey::{Random, Generator};
use devtools::RandomTempPath;
use self::tempdir::TempDir;
#[test]
fn should_create_new_account() {
@ -344,7 +346,7 @@ mod test {
#[test]
fn should_list_vaults() {
// given
let temp_path = RandomTempPath::new();
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();
@ -359,11 +361,11 @@ mod test {
#[test]
fn hash_of_files() {
let temp_path = RandomTempPath::new();
let temp_path = TempDir::new("").unwrap();
let directory = RootDiskDirectory::create(&temp_path).unwrap();
let hash = directory.files_hash().expect("Files hash should be calculated ok");
assert_eq!(
let hash = directory.files_hash().expect("Files hash should be calculated ok");
assert_eq!(
hash,
15130871412783076140
);
@ -373,7 +375,7 @@ mod test {
let account = SafeAccount::create(&keypair, [0u8; 16], password, 1024, "Test".to_owned(), "{}".to_owned());
directory.insert(account).expect("Account should be inserted ok");
let new_hash = directory.files_hash().expect("New files hash should be calculated ok");
let new_hash = directory.files_hash().expect("New files hash should be calculated ok");
assert!(new_hash != hash, "hash of the file list should change once directory content changed");
}

View File

@ -18,7 +18,7 @@ use std::{fs, io};
use std::path::{PathBuf, Path};
use parking_lot::Mutex;
use {json, SafeAccount, Error};
use util::sha3::Hashable;
use crypto::Keccak256;
use super::super::account::Crypto;
use super::{KeyDirectory, VaultKeyDirectory, VaultKey, SetKeyError};
use super::disk::{DiskDirectory, KeyFileManager};
@ -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.sha3();
let password_hash = key.password.keccak256();
let crypto = Crypto::with_plain(&password_hash, &key.password, key.iterations);
let mut vault_file_path: PathBuf = vault_dir_path.as_ref().into();
@ -268,8 +268,8 @@ 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.sha3();
if &*password_hash != password_bytes.as_slice() {
let password_hash = key.password.keccak256();
if password_hash != password_bytes.as_slice() {
return Err(Error::InvalidPassword);
}
}
@ -279,12 +279,14 @@ fn read_vault_file<P>(vault_dir_path: P, key: Option<&VaultKey>) -> Result<Strin
#[cfg(test)]
mod test {
extern crate tempdir;
use std::fs;
use std::io::Write;
use std::path::PathBuf;
use dir::VaultKey;
use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory};
use devtools::RandomTempPath;
use self::tempdir::TempDir;
#[test]
fn check_vault_name_succeeds() {
@ -320,9 +322,9 @@ mod test {
#[test]
fn create_vault_file_succeeds() {
// given
let temp_path = RandomTempPath::new();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let mut vault_dir: PathBuf = temp_path.as_path().into();
let mut vault_dir: PathBuf = temp_path.path().into();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
@ -339,10 +341,10 @@ mod test {
#[test]
fn read_vault_file_succeeds() {
// given
let temp_path = RandomTempPath::create_dir();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 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.as_path().into();
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
{
@ -360,9 +362,9 @@ mod test {
#[test]
fn read_vault_file_fails() {
// given
let temp_path = RandomTempPath::create_dir();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password1", 1024);
let dir: PathBuf = temp_path.as_path().into();
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
@ -389,9 +391,9 @@ mod test {
#[test]
fn vault_directory_can_be_created() {
// given
let temp_path = RandomTempPath::new();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let dir: PathBuf = temp_path.as_path().into();
let dir: PathBuf = temp_path.path().into();
// when
let vault = VaultDiskDirectory::create(&dir, "vault", key.clone());
@ -409,9 +411,9 @@ mod test {
#[test]
fn vault_directory_cannot_be_created_if_already_exists() {
// given
let temp_path = RandomTempPath::new();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let dir: PathBuf = temp_path.as_path().into();
let dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
@ -426,9 +428,9 @@ mod test {
#[test]
fn vault_directory_cannot_be_opened_if_not_exists() {
// given
let temp_path = RandomTempPath::create_dir();
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new("password", 1024);
let dir: PathBuf = temp_path.as_path().into();
let dir: PathBuf = temp_path.path().into();
// when
let vault = VaultDiskDirectory::at(&dir, "vault", key);

View File

@ -620,13 +620,14 @@ impl SimpleSecretStore for EthMultiStore {
#[cfg(test)]
mod tests {
extern crate tempdir;
use dir::{KeyDirectory, MemoryDirectory, RootDiskDirectory};
use ethkey::{Random, Generator, KeyPair};
use secret_store::{SimpleSecretStore, SecretStore, SecretVaultRef, StoreAccountRef, Derivation};
use super::{EthStore, EthMultiStore};
use devtools::RandomTempPath;
use util::H256;
use self::tempdir::TempDir;
use bigint::hash::H256;
fn keypair() -> KeyPair {
Random.generate().unwrap()
@ -642,13 +643,13 @@ mod tests {
struct RootDiskDirectoryGuard {
pub key_dir: Option<Box<KeyDirectory>>,
_path: RandomTempPath,
_path: TempDir,
}
impl RootDiskDirectoryGuard {
pub fn new() -> Self {
let temp_path = RandomTempPath::new();
let disk_dir = Box::new(RootDiskDirectory::create(temp_path.as_path()).unwrap());
let temp_path = TempDir::new("").unwrap();
let disk_dir = Box::new(RootDiskDirectory::create(temp_path.path()).unwrap());
RootDiskDirectoryGuard {
key_dir: Some(disk_dir),

View File

@ -14,10 +14,11 @@
// 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;
use std::{fmt, str};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::ser::SerializeStruct;
use serde::de::{Visitor, MapVisitor, Error};
use serde_json;
use super::{Cipher, CipherSer, CipherSerParams, Kdf, KdfSer, KdfSerParams, H256, Bytes};
pub type CipherText = Bytes;
@ -30,6 +31,20 @@ pub struct Crypto {
pub mac: H256,
}
impl str::FromStr for Crypto {
type Err = serde_json::error::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
serde_json::from_str(s)
}
}
impl From<Crypto> for String {
fn from(c: Crypto) -> Self {
serde_json::to_string(&c).expect("serialization cannot fail, cause all crypto keys are strings")
}
}
enum CryptoField {
Cipher,
CipherParams,

View File

@ -29,9 +29,9 @@ extern crate serde_json;
extern crate smallvec;
extern crate time;
extern crate tiny_keccak;
extern crate tempdir;
extern crate ethcore_devtools as devtools;
extern crate ethcore_util as util;
extern crate ethcore_bigint as bigint;
extern crate ethcrypto as crypto;
extern crate ethkey as _ethkey;
extern crate parity_wordlist;
@ -54,7 +54,7 @@ mod presale;
mod random;
mod secret_store;
pub use self::account::SafeAccount;
pub use self::account::{SafeAccount, Crypto};
pub use self::error::Error;
pub use self::ethstore::{EthStore, EthMultiStore};
pub use self::import::{import_accounts, read_geth_accounts};

View File

@ -19,7 +19,7 @@ use std::path::PathBuf;
use ethkey::{Address, Message, Signature, Secret, Public};
use Error;
use json::{Uuid, OpaqueKeyFile};
use util::H256;
use bigint::hash::H256;
/// Key directory reference
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]