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

Presale wallet #1376

Merged
merged 8 commits into from
Jun 22, 2016
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ethstore/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Usage:
ethstore change-pwd <address> <old-pwd> <new-pwd> [--dir DIR]
ethstore list [--dir DIR]
ethstore import [--src DIR] [--dir DIR]
ethstore import-wallet <path> <password> [--dir DIR]
Copy link
Contributor

@gavofyork gavofyork Jun 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<password> is a file containing the password, right?

ethstore remove <address> <password> [--dir DIR]
ethstore sign <address> <password> <message> [--dir DIR]
ethstore [-h | --help]
Expand All @@ -38,6 +39,7 @@ Commands:
change-pwd Change account password.
list List accounts.
import Import accounts from src.
import-wallet Import presale wallet.
remove Remove account.
sign Sign message.
```
Expand Down Expand Up @@ -119,6 +121,19 @@ ethstore list

--

#### `import-wallet <path> <password> [--dir DIR]`
*Import account from presale wallet.*

- `<path>` - presale wallet path
- `<password>` - account password, any string
- `[--dir DIR]` - secret store directory, It may be either parity, parity-test, geth, geth-test or a path. default: parity

```
e6a3d25a7cb7cd21cb720df5b5e8afd154af1bbb
```

--

#### `remove <address> <password> [--dir DIR]`
*Remove account from secret store.*

Expand Down
11 changes: 10 additions & 1 deletion ethstore/src/bin/ethstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ use std::str::FromStr;
use docopt::Docopt;
use ethstore::ethkey::{Secret, Address, Message};
use ethstore::dir::{KeyDirectory, ParityDirectory, DiskDirectory, GethDirectory, DirectoryType};
use ethstore::{EthStore, SecretStore, import_accounts, Error};
use ethstore::{EthStore, SecretStore, import_accounts, Error, PresaleWallet};

pub const USAGE: &'static str = r#"
Ethereum key management.
Expand All @@ -35,6 +35,7 @@ Usage:
ethstore change-pwd <address> <old-pwd> <new-pwd> [--dir DIR]
ethstore list [--dir DIR]
ethstore import [--src DIR] [--dir DIR]
ethstore import-wallet <path> <password> [--dir DIR]
ethstore remove <address> <password> [--dir DIR]
ethstore sign <address> <password> <message> [--dir DIR]
ethstore [-h | --help]
Expand All @@ -53,6 +54,7 @@ Commands:
change-pwd Change password.
list List accounts.
import Import accounts from src.
import-wallet Import presale wallet.
remove Remove account.
sign Sign message.
"#;
Expand All @@ -63,6 +65,7 @@ struct Args {
cmd_change_pwd: bool,
cmd_list: bool,
cmd_import: bool,
cmd_import_wallet: bool,
cmd_remove: bool,
cmd_sign: bool,
arg_secret: String,
Expand All @@ -71,6 +74,7 @@ struct Args {
arg_new_pwd: String,
arg_address: String,
arg_message: String,
arg_path: String,
flag_src: String,
flag_dir: String,
}
Expand Down Expand Up @@ -128,6 +132,11 @@ fn execute<S, I>(command: I) -> Result<String, Error> where I: IntoIterator<Item
let dst = try!(key_dir(&args.flag_dir));
let accounts = try!(import_accounts(src.deref(), dst.deref()));
Ok(format_accounts(&accounts))
} else if args.cmd_import_wallet {
let wallet = try!(PresaleWallet::open(&args.arg_path));
let kp = try!(wallet.decrypt(&args.arg_password));
let address = try!(store.insert_account(kp.secret().clone(), &args.arg_password));
Ok(format!("{}", address))
} else if args.cmd_remove {
let address = try!(Address::from_str(&args.arg_address));
let ok = store.remove_account(&address, &args.arg_password).is_ok();
Expand Down
7 changes: 4 additions & 3 deletions ethstore/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ impl Keccak256<[u8; 32]> for [u8] {
pub mod aes {
use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding};
use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor};
use rcrypto::symmetriccipher::{Encryptor, Decryptor};
use rcrypto::symmetriccipher::{Encryptor, Decryptor, SymmetricCipherError};
use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer};

/// Encrypt a message
Expand All @@ -83,9 +83,10 @@ pub mod aes {
}

/// Decrypt a message using cbc mode
pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) -> Result<(), SymmetricCipherError> {
let mut encryptor = CbcDecryptor::new(AesSafe128Decryptor::new(k), PkcsPadding, iv.to_vec());
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
try!(encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true));
Ok(())
}

}
Expand Down
7 changes: 3 additions & 4 deletions ethstore/src/presale.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl PresaleWallet {
pbkdf2(&mut h_mac, password.as_bytes(), 2000, &mut derived_key);

let mut key = [0u8; 64];
crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key);
try!(crypto::aes::decrypt_cbc(&derived_key, &self.iv, &self.ciphertext, &mut key).map_err(|_| Error::InvalidPassword));

let secret = Secret::from(key.keccak256());
if let Ok(kp) = KeyPair::from_secret(secret) {
Expand All @@ -58,7 +58,6 @@ impl PresaleWallet {

#[cfg(test)]
mod tests {
use ethkey::Address;
use super::PresaleWallet;
use json;

Expand All @@ -74,7 +73,7 @@ mod tests {

let wallet = json::PresaleWallet::load(json.as_bytes()).unwrap();
let wallet = PresaleWallet::from(wallet);
let kp = wallet.decrypt("123").unwrap();
assert_eq!(kp.address(), Address::from(wallet.address));
assert!(wallet.decrypt("123").is_ok());
assert!(wallet.decrypt("124").is_err());
}
}
2 changes: 2 additions & 0 deletions parity/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Usage:
parity daemon <pid-file> [options]
parity account (new | list ) [options]
parity account import <path>... [options]
parity wallet import <path> --password FILE [options]
parity import [ <file> ] [options]
parity export [ <file> ] [options]
parity signer new-token [options]
Expand Down Expand Up @@ -215,6 +216,7 @@ Miscellaneous Options:
pub struct Args {
pub cmd_daemon: bool,
pub cmd_account: bool,
pub cmd_wallet: bool,
pub cmd_new: bool,
pub cmd_list: bool,
pub cmd_export: bool,
Expand Down
29 changes: 29 additions & 0 deletions parity/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,11 @@ fn execute(conf: Configuration) {
return;
}

if conf.args.cmd_wallet {
execute_wallet_cli(conf);
return;
}

if conf.args.cmd_export {
execute_export(conf);
return;
Expand Down Expand Up @@ -534,6 +539,30 @@ fn execute_account_cli(conf: Configuration) {
}
}

fn execute_wallet_cli(conf: Configuration) {
use ethcore::ethstore::{PresaleWallet, SecretStore, EthStore};
use ethcore::ethstore::dir::DiskDirectory;
use ethcore::account_provider::AccountProvider;

let wallet_path = conf.args.arg_path.first().unwrap();
let filename = conf.args.flag_password.first().unwrap();
let mut file = File::open(filename).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));
let mut file_content = String::new();
file.read_to_string(&mut file_content).unwrap_or_else(|_| die!("{} Unable to read password file.", filename));

let dir = Box::new(DiskDirectory::create(conf.keys_path()).unwrap());
let iterations = conf.keys_iterations();
let store = AccountProvider::new(Box::new(EthStore::open_with_iterations(dir, iterations).unwrap()));

// remove eof
let pass = &file_content[..file_content.len() - 1];
let wallet = PresaleWallet::open(wallet_path).unwrap_or_else(|_| die!("Unable to open presale wallet."));
let kp = wallet.decrypt(pass).unwrap_or_else(|_| die!("Invalid password"));
let address = store.insert_account(kp.secret().clone(), pass).unwrap();

println!("Imported account: {}", address);
}

fn wait_for_exit(
panic_handler: Arc<PanicHandler>,
_rpc_server: Option<RpcServer>,
Expand Down