importing presale wallet (#1368)
* importing presale wallet in progress * PresaleWallet data structure
This commit is contained in:
parent
c5f6250668
commit
57e9ed3f08
@ -65,8 +65,8 @@ impl Keccak256<[u8; 32]> for [u8] {
|
|||||||
|
|
||||||
/// AES encryption
|
/// AES encryption
|
||||||
pub mod aes {
|
pub mod aes {
|
||||||
use rcrypto::blockmodes::CtrMode;
|
use rcrypto::blockmodes::{CtrMode, CbcDecryptor, PkcsPadding};
|
||||||
use rcrypto::aessafe::AesSafe128Encryptor;
|
use rcrypto::aessafe::{AesSafe128Encryptor, AesSafe128Decryptor};
|
||||||
use rcrypto::symmetriccipher::{Encryptor, Decryptor};
|
use rcrypto::symmetriccipher::{Encryptor, Decryptor};
|
||||||
use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer};
|
use rcrypto::buffer::{RefReadBuffer, RefWriteBuffer};
|
||||||
|
|
||||||
@ -81,5 +81,12 @@ pub mod aes {
|
|||||||
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
let mut encryptor = CtrMode::new(AesSafe128Encryptor::new(k), iv.to_vec());
|
||||||
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
encryptor.decrypt(&mut RefReadBuffer::new(encrypted), &mut RefWriteBuffer::new(dest), true).expect("Invalid length or padding");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decrypt a message using cbc mode
|
||||||
|
pub fn decrypt_cbc(k: &[u8], iv: &[u8], encrypted: &[u8], dest: &mut [u8]) {
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,3 +31,11 @@ impl From<json::H160> for Address {
|
|||||||
From::from(a)
|
From::from(a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a json::H160> for Address {
|
||||||
|
fn from(json: &'a json::H160) -> Self {
|
||||||
|
let mut a = [0u8; 20];
|
||||||
|
a.copy_from_slice(json);
|
||||||
|
From::from(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
use std::fmt;
|
||||||
|
use std::ops;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use rustc_serialize::hex::{FromHex, ToHex};
|
use rustc_serialize::hex::{FromHex, ToHex};
|
||||||
use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError};
|
use serde::{Serialize, Serializer, Deserialize, Deserializer, Error as SerdeError};
|
||||||
@ -22,9 +24,31 @@ use super::Error;
|
|||||||
|
|
||||||
macro_rules! impl_hash {
|
macro_rules! impl_hash {
|
||||||
($name: ident, $size: expr) => {
|
($name: ident, $size: expr) => {
|
||||||
#[derive(Debug, PartialEq)]
|
|
||||||
pub struct $name([u8; $size]);
|
pub struct $name([u8; $size]);
|
||||||
|
|
||||||
|
impl fmt::Debug for $name {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
let self_ref: &[u8] = &self.0;
|
||||||
|
write!(f, "{:?}", self_ref)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for $name {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
let self_ref: &[u8] = &self.0;
|
||||||
|
let other_ref: &[u8] = &other.0;
|
||||||
|
self_ref == other_ref
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ops::Deref for $name {
|
||||||
|
type Target = [u8];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Serialize for $name {
|
impl Serialize for $name {
|
||||||
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
|
||||||
where S: Serializer {
|
where S: Serializer {
|
||||||
@ -85,3 +109,4 @@ macro_rules! impl_hash {
|
|||||||
impl_hash!(H128, 16);
|
impl_hash!(H128, 16);
|
||||||
impl_hash!(H160, 20);
|
impl_hash!(H160, 20);
|
||||||
impl_hash!(H256, 32);
|
impl_hash!(H256, 32);
|
||||||
|
impl_hash!(H768, 96);
|
||||||
|
@ -5,14 +5,16 @@ mod hash;
|
|||||||
mod id;
|
mod id;
|
||||||
mod kdf;
|
mod kdf;
|
||||||
mod key_file;
|
mod key_file;
|
||||||
|
mod presale;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr};
|
pub use self::cipher::{Cipher, CipherSer, CipherSerParams, Aes128Ctr};
|
||||||
pub use self::crypto::Crypto;
|
pub use self::crypto::Crypto;
|
||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use self::hash::{H128, H160, H256};
|
pub use self::hash::{H128, H160, H256, H768};
|
||||||
pub use self::id::UUID;
|
pub use self::id::UUID;
|
||||||
pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams};
|
pub use self::kdf::{Kdf, KdfSer, Prf, Pbkdf2, Scrypt, KdfSerParams};
|
||||||
pub use self::key_file::KeyFile;
|
pub use self::key_file::KeyFile;
|
||||||
|
pub use self::presale::PresaleWallet;
|
||||||
pub use self::version::Version;
|
pub use self::version::Version;
|
||||||
|
|
||||||
|
42
ethstore/src/json/presale.rs
Normal file
42
ethstore/src/json/presale.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
use std::io::Read;
|
||||||
|
use serde_json;
|
||||||
|
use super::{H160, H768};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
pub struct PresaleWallet {
|
||||||
|
pub encseed: H768,
|
||||||
|
#[serde(rename = "ethaddr")]
|
||||||
|
pub address: H160,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PresaleWallet {
|
||||||
|
pub fn load<R>(reader: R) -> Result<Self, serde_json::Error> where R: Read {
|
||||||
|
serde_json::from_reader(reader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::str::FromStr;
|
||||||
|
use serde_json;
|
||||||
|
use json::{PresaleWallet, H160, H768};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn presale_wallet() {
|
||||||
|
let json = r#"
|
||||||
|
{
|
||||||
|
"encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066",
|
||||||
|
"ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1",
|
||||||
|
"email": "123@gmail.com",
|
||||||
|
"btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
|
||||||
|
} "#;
|
||||||
|
|
||||||
|
let expected = PresaleWallet {
|
||||||
|
encseed: H768::from_str("137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066").unwrap(),
|
||||||
|
address: H160::from_str("ede84640d1a1d3e06902048e67aa7db8d52c2ce1").unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let wallet: PresaleWallet = serde_json::from_str(json).unwrap();
|
||||||
|
assert_eq!(expected, wallet);
|
||||||
|
}
|
||||||
|
}
|
@ -37,6 +37,7 @@ mod crypto;
|
|||||||
mod error;
|
mod error;
|
||||||
mod ethstore;
|
mod ethstore;
|
||||||
mod import;
|
mod import;
|
||||||
|
mod presale;
|
||||||
mod random;
|
mod random;
|
||||||
mod secret_store;
|
mod secret_store;
|
||||||
|
|
||||||
@ -44,5 +45,6 @@ pub use self::account::SafeAccount;
|
|||||||
pub use self::error::Error;
|
pub use self::error::Error;
|
||||||
pub use self::ethstore::EthStore;
|
pub use self::ethstore::EthStore;
|
||||||
pub use self::import::import_accounts;
|
pub use self::import::import_accounts;
|
||||||
|
pub use self::presale::PresaleWallet;
|
||||||
pub use self::secret_store::SecretStore;
|
pub use self::secret_store::SecretStore;
|
||||||
|
|
||||||
|
80
ethstore/src/presale.rs
Normal file
80
ethstore/src/presale.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::path::Path;
|
||||||
|
use rcrypto::pbkdf2::pbkdf2;
|
||||||
|
use rcrypto::sha2::Sha256;
|
||||||
|
use rcrypto::hmac::Hmac;
|
||||||
|
use json;
|
||||||
|
use ethkey::{Address, Secret, KeyPair};
|
||||||
|
use crypto::Keccak256;
|
||||||
|
use {crypto, Error};
|
||||||
|
|
||||||
|
pub struct PresaleWallet {
|
||||||
|
iv: [u8; 16],
|
||||||
|
ciphertext: [u8; 80],
|
||||||
|
address: Address,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<json::PresaleWallet> for PresaleWallet {
|
||||||
|
fn from(wallet: json::PresaleWallet) -> Self {
|
||||||
|
let mut iv = [0u8; 16];
|
||||||
|
iv.copy_from_slice(&wallet.encseed[..16]);
|
||||||
|
|
||||||
|
let mut ciphertext = [0u8; 80];
|
||||||
|
ciphertext.copy_from_slice(&wallet.encseed[16..]);
|
||||||
|
|
||||||
|
PresaleWallet {
|
||||||
|
iv: iv,
|
||||||
|
ciphertext: ciphertext,
|
||||||
|
address: Address::from(wallet.address),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PresaleWallet {
|
||||||
|
pub fn open<P>(path: P) -> Result<Self, Error> where P: AsRef<Path> {
|
||||||
|
let file = try!(fs::File::open(path));
|
||||||
|
let presale = json::PresaleWallet::load(file).unwrap();
|
||||||
|
Ok(PresaleWallet::from(presale))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decrypt(&self, password: &str) -> Result<KeyPair, Error> {
|
||||||
|
let mut h_mac = Hmac::new(Sha256::new(), password.as_bytes());
|
||||||
|
let mut derived_key = vec![0u8; 16];
|
||||||
|
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);
|
||||||
|
|
||||||
|
let secret = Secret::from(key.keccak256());
|
||||||
|
if let Ok(kp) = KeyPair::from_secret(secret) {
|
||||||
|
if kp.address() == self.address {
|
||||||
|
return Ok(kp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(Error::InvalidPassword)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use ethkey::Address;
|
||||||
|
use super::PresaleWallet;
|
||||||
|
use json;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let json = r#"
|
||||||
|
{
|
||||||
|
"encseed": "137103c28caeebbcea5d7f95edb97a289ded151b72159137cb7b2671f394f54cff8c121589dcb373e267225547b3c71cbdb54f6e48ec85cd549f96cf0dedb3bc0a9ac6c79b9c426c5878ca2c9d06ff42a23cb648312fc32ba83649de0928e066",
|
||||||
|
"ethaddr": "ede84640d1a1d3e06902048e67aa7db8d52c2ce1",
|
||||||
|
"email": "123@gmail.com",
|
||||||
|
"btcaddr": "1JvqEc6WLhg6GnyrLBe2ztPAU28KRfuseH"
|
||||||
|
} "#;
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user