Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Commit

Permalink
propagate NonZeroU32
Browse files Browse the repository at this point in the history
  • Loading branch information
ordian committed Jan 30, 2019
1 parent 20bcaca commit b347599
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 53 deletions.
19 changes: 11 additions & 8 deletions accounts/ethstore/src/account/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

use std::str;
use std::num::NonZeroU32;
use ethkey::{Password, Secret};
use {json, Error, crypto};
use crypto::Keccak256;
Expand Down Expand Up @@ -73,12 +74,12 @@ impl From<Crypto> for String {

impl Crypto {
/// Encrypt account secret
pub fn with_secret(secret: &Secret, password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
pub fn with_secret(secret: &Secret, password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
Crypto::with_plain(&*secret, password, iterations)
}

/// Encrypt custom plain data
pub fn with_plain(plain: &[u8], password: &Password, iterations: u32) -> Result<Self, crypto::Error> {
pub fn with_plain(plain: &[u8], password: &Password, iterations: NonZeroU32) -> Result<Self, crypto::Error> {
let salt: [u8; 32] = Random::random();
let iv: [u8; 16] = Random::random();

Expand Down Expand Up @@ -159,29 +160,31 @@ impl Crypto {
#[cfg(test)]
mod tests {
use ethkey::{Generator, Random};
use super::{Crypto, Error};
use super::{Crypto, Error, NonZeroU32};

const ITERATIONS: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(10240) };

#[test]
fn crypto_with_secret_create() {
let keypair = Random.generate().unwrap();
let passwd = "this is sparta".into();
let crypto = Crypto::with_secret(keypair.secret(), &passwd, 10240).unwrap();
let crypto = Crypto::with_secret(keypair.secret(), &passwd, ITERATIONS).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".into(), 10240).unwrap();
let crypto = Crypto::with_secret(keypair.secret(), &"this is sparta".into(), ITERATIONS).unwrap();
assert_matches!(crypto.secret(&"this is sparta!".into()), Err(Error::InvalidPassword))
}

#[test]
fn crypto_with_null_plain_data() {
let original_data = b"";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let crypto = Crypto::with_plain(&original_data[..], &passwd, ITERATIONS).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
Expand All @@ -190,7 +193,7 @@ mod tests {
fn crypto_with_tiny_plain_data() {
let original_data = b"{}";
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data[..], &passwd, 10240).unwrap();
let crypto = Crypto::with_plain(&original_data[..], &passwd, ITERATIONS).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(original_data[..], *decrypted_data);
}
Expand All @@ -199,7 +202,7 @@ mod tests {
fn crypto_with_huge_plain_data() {
let original_data: Vec<_> = (1..65536).map(|i| (i % 256) as u8).collect();
let passwd = "this is sparta".into();
let crypto = Crypto::with_plain(&original_data, &passwd, 10240).unwrap();
let crypto = Crypto::with_plain(&original_data, &passwd, ITERATIONS).unwrap();
let decrypted_data = crypto.decrypt(&passwd).unwrap();
assert_eq!(&original_data, &decrypted_data);
}
Expand Down
3 changes: 2 additions & 1 deletion accounts/ethstore/src/account/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

use json;
use std::num::NonZeroU32;

#[derive(Debug, PartialEq, Clone)]
pub enum Prf {
Expand All @@ -23,7 +24,7 @@ pub enum Prf {

#[derive(Debug, PartialEq, Clone)]
pub struct Pbkdf2 {
pub c: u32,
pub c: NonZeroU32,
pub dklen: u32,
pub prf: Prf,
pub salt: Vec<u8>,
Expand Down
18 changes: 10 additions & 8 deletions accounts/ethstore/src/account/safe_account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use {json, Error};
use account::Version;
use crypto;
use super::crypto::Crypto;
use std::num::NonZeroU32;

/// Account representation.
#[derive(Debug, PartialEq, Clone)]
Expand Down Expand Up @@ -59,7 +60,7 @@ impl SafeAccount {
keypair: &KeyPair,
id: [u8; 16],
password: &Password,
iterations: u32,
iterations: NonZeroU32,
name: String,
meta: String
) -> Result<Self, crypto::Error> {
Expand Down Expand Up @@ -135,7 +136,7 @@ impl SafeAccount {
}

/// Create a new `VaultKeyFile` from the given `self`
pub fn into_vault_file(self, iterations: u32, password: &Password) -> Result<json::VaultKeyFile, Error> {
pub fn into_vault_file(self, iterations: NonZeroU32, password: &Password) -> Result<json::VaultKeyFile, Error> {
let meta_plain = json::VaultKeyMeta {
address: self.address.into(),
name: Some(self.name),
Expand Down Expand Up @@ -177,7 +178,7 @@ impl SafeAccount {
}

/// Change account's password.
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: u32) -> Result<Self, Error> {
pub fn change_password(&self, old_password: &Password, new_password: &Password, iterations: NonZeroU32) -> Result<Self, Error> {
let secret = self.crypto.secret(old_password)?;
let result = SafeAccount {
id: self.id.clone(),
Expand All @@ -200,14 +201,16 @@ impl SafeAccount {
#[cfg(test)]
mod tests {
use ethkey::{Generator, Random, verify_public, Message};
use super::SafeAccount;
use super::{SafeAccount, NonZeroU32};

const ITERATIONS: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(10240) };

#[test]
fn sign_and_verify_public() {
let keypair = Random.generate().unwrap();
let password = "hello world".into();
let message = Message::default();
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 10240, "Test".to_owned(), "{}".to_owned());
let account = SafeAccount::create(&keypair, [0u8; 16], &password, ITERATIONS, "Test".to_owned(), "{}".to_owned());
let signature = account.unwrap().sign(&password, &message).unwrap();
assert!(verify_public(keypair.public(), &signature, &message).unwrap());
}
Expand All @@ -217,10 +220,9 @@ mod tests {
let keypair = Random.generate().unwrap();
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();
let account = SafeAccount::create(&keypair, [0u8; 16], &first_password, ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
let new_account = account.change_password(&first_password, &sec_password, ITERATIONS).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());
Expand Down
18 changes: 11 additions & 7 deletions accounts/ethstore/src/accounts_dir/disk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,11 +356,14 @@ mod test {
extern crate tempdir;

use std::{env, fs};
use std::num::NonZeroU32;
use super::{KeyDirectory, RootDiskDirectory, VaultKey};
use account::SafeAccount;
use ethkey::{Random, Generator};
use self::tempdir::TempDir;

const ITERATIONS: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1024) };

#[test]
fn should_create_new_account() {
// given
Expand All @@ -371,7 +374,7 @@ mod test {
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, ITERATIONS, "Test".to_owned(), "{}".to_owned());
let res = directory.insert(account.unwrap());

// then
Expand All @@ -392,7 +395,7 @@ mod test {
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, ITERATIONS, "Test".to_owned(), "{}".to_owned()).unwrap();
let filename = "test".to_string();
let dedup = true;

Expand Down Expand Up @@ -428,15 +431,15 @@ mod test {

// 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, ITERATIONS));

// then
assert!(vault.is_ok());
let after_root_items_count = fs::read_dir(&dir).unwrap().count();
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, ITERATIONS));

// then
assert!(vault.is_ok());
Expand All @@ -453,8 +456,9 @@ 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".into(), 1)).unwrap();
vault_provider.create("vault2", VaultKey::new(&"password2".into(), 1)).unwrap();
const ITER: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1) };
vault_provider.create("vault1", VaultKey::new(&"password1".into(), ITER)).unwrap();
vault_provider.create("vault2", VaultKey::new(&"password2".into(), ITER)).unwrap();

// then
let vaults = vault_provider.list_vaults().unwrap();
Expand All @@ -476,7 +480,7 @@ mod test {

let keypair = Random.generate().unwrap();
let password = "test pass".into();
let account = SafeAccount::create(&keypair, [0u8; 16], &password, 1024, "Test".to_owned(), "{}".to_owned());
let account = SafeAccount::create(&keypair, [0u8; 16], &password, ITERATIONS, "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");
Expand Down
5 changes: 3 additions & 2 deletions accounts/ethstore/src/accounts_dir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//! Accounts Directory

use ethkey::Password;
use std::num::NonZeroU32;
use std::path::{PathBuf};
use {SafeAccount, Error};

Expand All @@ -41,7 +42,7 @@ pub struct VaultKey {
/// Vault password
pub password: Password,
/// Number of iterations to produce a derived key from password
pub iterations: u32,
pub iterations: NonZeroU32,
}

/// Keys directory
Expand Down Expand Up @@ -96,7 +97,7 @@ pub use self::vault::VaultDiskDirectory;

impl VaultKey {
/// Create new vault key
pub fn new(password: &Password, iterations: u32) -> Self {
pub fn new(password: &Password, iterations: NonZeroU32) -> Self {
VaultKey {
password: password.clone(),
iterations: iterations,
Expand Down
15 changes: 9 additions & 6 deletions accounts/ethstore/src/accounts_dir/vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,11 +282,14 @@ mod test {

use std::fs;
use std::io::Write;
use std::num::NonZeroU32;
use std::path::PathBuf;
use super::VaultKey;
use super::{VAULT_FILE_NAME, check_vault_name, make_vault_dir_path, create_vault_file, read_vault_file, VaultDiskDirectory};
use self::tempdir::TempDir;

const ITERATIONS: NonZeroU32 = unsafe { NonZeroU32::new_unchecked(1024) };

#[test]
fn check_vault_name_succeeds() {
assert!(check_vault_name("vault"));
Expand Down Expand Up @@ -325,7 +328,7 @@ mod test {
fn create_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let key = VaultKey::new(&"password".into(), ITERATIONS);
let mut vault_dir: PathBuf = temp_path.path().into();
vault_dir.push("vault");
fs::create_dir_all(&vault_dir).unwrap();
Expand All @@ -344,7 +347,7 @@ mod test {
fn read_vault_file_succeeds() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let key = VaultKey::new(&"password".into(), ITERATIONS);
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();
Expand All @@ -365,7 +368,7 @@ mod test {
fn read_vault_file_fails() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password1".into(), 1024);
let key = VaultKey::new(&"password1".into(), ITERATIONS);
let dir: PathBuf = temp_path.path().into();
let mut vault_file_path: PathBuf = dir.clone();
vault_file_path.push(VAULT_FILE_NAME);
Expand Down Expand Up @@ -394,7 +397,7 @@ mod test {
fn vault_directory_can_be_created() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let key = VaultKey::new(&"password".into(), ITERATIONS);
let dir: PathBuf = temp_path.path().into();

// when
Expand All @@ -414,7 +417,7 @@ mod test {
fn vault_directory_cannot_be_created_if_already_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let key = VaultKey::new(&"password".into(), ITERATIONS);
let dir: PathBuf = temp_path.path().into();
let mut vault_dir = dir.clone();
vault_dir.push("vault");
Expand All @@ -431,7 +434,7 @@ mod test {
fn vault_directory_cannot_be_opened_if_not_exists() {
// given
let temp_path = TempDir::new("").unwrap();
let key = VaultKey::new(&"password".into(), 1024);
let key = VaultKey::new(&"password".into(), ITERATIONS);
let dir: PathBuf = temp_path.path().into();

// when
Expand Down
11 changes: 6 additions & 5 deletions accounts/ethstore/src/ethstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

use std::collections::{BTreeMap, HashMap};
use std::num::NonZeroU32;
use std::mem;
use std::path::PathBuf;
use parking_lot::{Mutex, RwLock};
Expand All @@ -37,11 +38,11 @@ pub struct EthStore {
impl EthStore {
/// Open a new accounts store with given key directory backend.
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
Self::open_with_iterations(directory, NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS > 0; qed"))
}

/// Open a new account store with given key directory backend and custom number of iterations.
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: u32) -> Result<Self, Error> {
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
Ok(EthStore {
store: EthMultiStore::open_with_iterations(directory, iterations)?,
})
Expand Down Expand Up @@ -257,7 +258,7 @@ impl SecretStore for EthStore {
/// Similar to `EthStore` but may store many accounts (with different passwords) for the same `Address`
pub struct EthMultiStore {
dir: Box<KeyDirectory>,
iterations: u32,
iterations: NonZeroU32,
// order lock: cache, then vaults
cache: RwLock<BTreeMap<StoreAccountRef, Vec<SafeAccount>>>,
vaults: Mutex<HashMap<String, Box<VaultKeyDirectory>>>,
Expand All @@ -273,11 +274,11 @@ struct Timestamp {
impl EthMultiStore {
/// Open new multi-accounts store with given key directory backend.
pub fn open(directory: Box<KeyDirectory>) -> Result<Self, Error> {
Self::open_with_iterations(directory, KEY_ITERATIONS as u32)
Self::open_with_iterations(directory, NonZeroU32::new(KEY_ITERATIONS as u32).expect("KEY_ITERATIONS > 0; qed"))
}

/// Open new multi-accounts store with given key directory backend and custom number of iterations for new keys.
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: u32) -> Result<Self, Error> {
pub fn open_with_iterations(directory: Box<KeyDirectory>, iterations: NonZeroU32) -> Result<Self, Error> {
let store = EthMultiStore {
dir: directory,
vaults: Mutex::new(HashMap::new()),
Expand Down
3 changes: 2 additions & 1 deletion accounts/ethstore/src/json/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
// along with Parity Ethereum. If not, see <http://www.gnu.org/licenses/>.

use std::fmt;
use std::num::NonZeroU32;
use serde::{Serialize, Serializer, Deserialize, Deserializer};
use serde::de::{Visitor, Error as SerdeError};
use super::{Error, Bytes};
Expand Down Expand Up @@ -108,7 +109,7 @@ impl<'a> Visitor<'a> for PrfVisitor {

#[derive(Debug, PartialEq, Serialize, Deserialize)]
pub struct Pbkdf2 {
pub c: u32,
pub c: NonZeroU32,
pub dklen: u32,
pub prf: Prf,
pub salt: Bytes,
Expand Down
Loading

0 comments on commit b347599

Please sign in to comment.