Skip to content

Commit

Permalink
feat: add the import json
Browse files Browse the repository at this point in the history
  • Loading branch information
XuNeal committed Dec 11, 2023
1 parent 51ad49f commit 98e41f5
Show file tree
Hide file tree
Showing 14 changed files with 275 additions and 200 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions token-core/tcx-constants/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@ pub const TEST_MNEMONIC: &'static str =
pub const TEST_PASSWORD: &'static str = "Insecure Pa55w0rd";

pub const TEST_WIF: &'static str = "cT4fTJyLd5RmSZFHnkGmVCzXDKuJLbyTt7cy77ghTTCagzNdPH1j";
pub const TEST_PRIVATE_KEY: &'static str =
"0xcce64585e3b15a0e4ee601a467e050c9504a0db69a559d7ec416fa25ad3410c2";
26 changes: 13 additions & 13 deletions token-core/tcx-crypto/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
use std::env;
use tiny_keccak::Hasher;


const CREDENTIAL_LEN: usize = 64usize;

pub type Credential = [u8; CREDENTIAL_LEN];
Expand Down Expand Up @@ -128,7 +129,6 @@ impl KdfParams for SCryptParams {
}
}

/*
#[derive(Clone, Debug, Serialize, Deserialize)]
struct CacheDerivedKey {
hashed_key: String,
Expand All @@ -144,7 +144,9 @@ impl CacheDerivedKey {
}

fn hash(key: &str) -> String {
hex_dsha256(key)
// hex_dsha256(key)
// TODO: missing hex_dsha256
unimplemented!()
}

pub fn get_derived_key(&self, key: &str) -> Result<Vec<u8>> {
Expand All @@ -155,7 +157,6 @@ impl CacheDerivedKey {
}
}
}
*/

#[derive(Clone, Debug, Serialize, Deserialize, Default)]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -577,15 +578,14 @@ mod tests {
assert_eq!(crypto.ciphertext, "17ff4858e697455f4966c6072473f3501534bc20deb339b58aeb8db0bd9fe91777148d0a909f679fb6e3a7a64609034afeb72a");
}

// TODO: test case cannot compile
// #[test]
// fn test_cache_derived_key() {
// let cdk = CacheDerivedKey::new("12345678", &[1, 1, 1, 1]);
// let ret = cdk.get_derived_key("1234");
// assert!(ret.is_err());
// assert_eq!(format!("{}", ret.err().unwrap()), "password_incorrect");
#[test]
fn test_cache_derived_key() {
let cdk = CacheDerivedKey::new("12345678", &[1, 1, 1, 1]);
let ret = cdk.get_derived_key("1234");
assert!(ret.is_err());
assert_eq!(format!("{}", ret.err().unwrap()), "password_incorrect");

// let ret = cdk.get_derived_key("12345678").unwrap();
// assert_eq!(hex::encode(ret), "01010101");
// }
let ret = cdk.get_derived_key("12345678").unwrap();
assert_eq!(hex::encode(ret), "01010101");
}
}
2 changes: 1 addition & 1 deletion token-core/tcx-identity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ eth-keystore = "0.5.0"
hex = "0.4.3"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
uuid = { version = "1.3", features = ["serde", "v4"] }
uuid = { version = "1.2.2", features = ["serde", "v4"] }
bitcoin = "0.29.2"
sha2 = "0.10.6"
hmac-sha256 = "1.1.6"
Expand Down
1 change: 1 addition & 0 deletions token-core/tcx-migration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ base64 = "0.13.1"
base58 = "0.2.0"
parking_lot = "0.12.1"
ethers = "2.0.3"
uuid = { version = "1.2.2", features = ["serde", "v4"] }
227 changes: 146 additions & 81 deletions token-core/tcx-migration/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ use failure::format_err;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use tcx_atom::address::AtomAddress;
use tcx_constants::CoinInfo;
use tcx_common::hex_to_bytes;
use tcx_constants::{coin_info_from_param, CoinInfo, CurveType};
use tcx_crypto::{Crypto, EncPair, Key};
use tcx_keystore::{
key_hash_from_mnemonic, key_hash_from_private_key, Account, HdKeystore, PrivateKeystore,
Result, Source,
key_hash_from_mnemonic, key_hash_from_private_key, Account, Address, HdKeystore,
PrivateKeystore, Result, Source,
};

use tcx_btc_kin::address::BtcKinAddress;
Expand All @@ -16,7 +17,7 @@ use tcx_eos::address::EosAddress;
use tcx_eth::address::EthAddress;
use tcx_keystore::identity::Identity;
use tcx_keystore::keystore::{IdentityNetwork, Keystore, Metadata, Store};
use tcx_primitive::{PrivateKey, Secp256k1PrivateKey};
use tcx_primitive::{PrivateKey, Secp256k1PrivateKey, TypedPublicKey};

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
Expand Down Expand Up @@ -82,16 +83,54 @@ impl OldMetadata {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct LegacyKeystore {
version: i32,
id: String,
crypto: Crypto,
enc_mnemonic: Option<EncPair>,
address: String,
mnemonic_path: Option<String>,
im_token_meta: OldMetadata,
pub version: i32,
pub id: String,
pub crypto: Crypto,
#[serde(skip_serializing_if = "Option::is_none")]
pub enc_mnemonic: Option<EncPair>,
pub address: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub mnemonic_path: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub im_token_meta: Option<OldMetadata>,
}

impl LegacyKeystore {
pub fn new_v3(private_key: &[u8], password: &str) -> Result<Self> {
let crypto = Crypto::new(password, private_key);
let sec_key = Secp256k1PrivateKey::from_slice(private_key)?;
let pub_key = TypedPublicKey::Secp256k1(sec_key.public_key());
let coin_info = coin_info_from_param("ETHEREUM", "", "", CurveType::SECP256k1.as_str())?;
let address = EthAddress::from_public_key(&pub_key, &coin_info)?.to_string();
let id = uuid::Uuid::new_v4().to_string();
Ok(LegacyKeystore {
version: 3,
id,
crypto,
enc_mnemonic: None,
address,
mnemonic_path: None,
im_token_meta: None,
})
}

pub fn validate_v3(&self, password: &str) -> Result<()> {
let key = Key::Password(password.to_string());
let unlocker = self.crypto.use_key(&key)?;
let sec_key_bytes = unlocker.plaintext()?;
let sec_key = Secp256k1PrivateKey::from_slice(&sec_key_bytes)?;
let pub_key = TypedPublicKey::Secp256k1(sec_key.public_key());
let coin_info = coin_info_from_param("ETHEREUM", "", "", CurveType::SECP256k1.as_str())?;
let calc_address = EthAddress::from_public_key(&pub_key, &coin_info)?.to_string();
let calc_addr_bytes = hex_to_bytes(&calc_address)?;
let addr_bytes = hex_to_bytes(&self.address)?;
if calc_addr_bytes == addr_bytes {
Ok(())
} else {
Err(format_err!("private_key_and_address_not_match"))
}
}

fn real_derivation_path(&self) -> String {
match self.version {
44 => {
Expand All @@ -113,69 +152,69 @@ impl LegacyKeystore {
self.enc_mnemonic.is_some()
}

pub fn derive_account(&self, keystore: &mut Keystore) -> Result<Account> {
let derivation_path;
if self.has_mnemonic() {
derivation_path = self.real_derivation_path();
} else {
derivation_path = "".to_string();
}

let chain_type = if self.im_token_meta.chain_type.is_some() {
self.im_token_meta.chain_type.as_ref().unwrap().to_string()
} else {
self.im_token_meta
.chain
.as_ref()
.expect("meta chain")
.to_string()
};

match chain_type.as_str() {
"ETHEREUM" => {
let coin_info = CoinInfo {
coin: "ETHEREUM".to_string(),
derivation_path,
curve: tcx_constants::CurveType::SECP256k1,
network: "".to_string(),
seg_wit: "".to_string(),
};
Ok(keystore.derive_coin::<EthAddress>(&coin_info)?)
}
"BITCOIN" => {
let coin_info = CoinInfo {
coin: "BITCOIN".to_string(),
derivation_path,
curve: tcx_constants::CurveType::SECP256k1,
network: self.im_token_meta.network.clone().unwrap_or("".to_string()),
seg_wit: self.im_token_meta.seg_wit.clone().unwrap_or("".to_string()),
};
Ok(keystore.derive_coin::<BtcKinAddress>(&coin_info)?)
}
"EOS" => {
let coin_info = CoinInfo {
coin: "EOS".to_string(),
derivation_path,
curve: tcx_constants::CurveType::SECP256k1,
network: self.im_token_meta.network.clone().unwrap_or("".to_string()),
seg_wit: "".to_string(),
};
Ok(keystore.derive_coin::<EosAddress>(&coin_info)?)
}
"COSMOS" => {
let coin_info = CoinInfo {
coin: "COSMOS".to_string(),
derivation_path,
curve: tcx_constants::CurveType::SECP256k1,
network: "".to_string(),
seg_wit: "".to_string(),
};

Ok(keystore.derive_coin::<AtomAddress>(&coin_info)?)
}
_ => Err(Error::UnsupportedChain.into()),
}
}
// pub fn derive_account(&self, keystore: &mut Keystore) -> Result<Account> {
// let derivation_path;
// if self.has_mnemonic() {
// derivation_path = self.real_derivation_path();
// } else {
// derivation_path = "".to_string();
// }

// let chain_type = if self.im_token_meta.chain_type.is_some() {
// self.im_token_meta.chain_type.as_ref().unwrap().to_string()
// } else {
// self.im_token_meta
// .chain
// .as_ref()
// .expect("meta chain")
// .to_string()
// };

// match chain_type.as_str() {
// "ETHEREUM" => {
// let coin_info = CoinInfo {
// coin: "ETHEREUM".to_string(),
// derivation_path,
// curve: tcx_constants::CurveType::SECP256k1,
// network: "".to_string(),
// seg_wit: "".to_string(),
// };
// Ok(keystore.derive_coin::<EthAddress>(&coin_info)?)
// }
// "BITCOIN" => {
// let coin_info = CoinInfo {
// coin: "BITCOIN".to_string(),
// derivation_path,
// curve: tcx_constants::CurveType::SECP256k1,
// network: self.im_token_meta.network.clone().unwrap_or("".to_string()),
// seg_wit: self.im_token_meta.seg_wit.clone().unwrap_or("".to_string()),
// };
// Ok(keystore.derive_coin::<BtcKinAddress>(&coin_info)?)
// }
// "EOS" => {
// let coin_info = CoinInfo {
// coin: "EOS".to_string(),
// derivation_path,
// curve: tcx_constants::CurveType::SECP256k1,
// network: self.im_token_meta.network.clone().unwrap_or("".to_string()),
// seg_wit: "".to_string(),
// };
// Ok(keystore.derive_coin::<EosAddress>(&coin_info)?)
// }
// "COSMOS" => {
// let coin_info = CoinInfo {
// coin: "COSMOS".to_string(),
// derivation_path,
// curve: tcx_constants::CurveType::SECP256k1,
// network: "".to_string(),
// seg_wit: "".to_string(),
// };

// Ok(keystore.derive_coin::<AtomAddress>(&coin_info)?)
// }
// _ => Err(Error::UnsupportedChain.into()),
// }
// }

pub fn from_json_str(keystore_str: &str) -> Result<LegacyKeystore> {
let keystore: LegacyKeystore = serde_json::from_str(&keystore_str)?;
Expand All @@ -187,12 +226,12 @@ impl LegacyKeystore {
}

pub fn migrate(&self, key: &Key) -> Result<Keystore> {
let mut keystore = if self.has_mnemonic() {
let keystore = if self.has_mnemonic() {
self.migrate_to_hd(key)?
} else {
self.migrate_to_private(key)?
};
self.derive_account(&mut keystore)?;
// self.derive_account(&mut keystore)?;
Ok(keystore)
}

Expand All @@ -205,7 +244,11 @@ impl LegacyKeystore {
)?;
let mnemonic = String::from_utf8(mnemonic_data.to_owned())?;
let key_hash = key_hash_from_mnemonic(&mnemonic)?;
let meta = self.im_token_meta.to_metadata();
let meta = self
.im_token_meta
.as_ref()
.expect("migration to hd need imTokenMeta")
.to_metadata();
let identity = Identity::from_mnemonic(&mnemonic, &unlocker, &meta.network)?;
let mut store = Store {
id: self.id.to_string(),
Expand Down Expand Up @@ -238,8 +281,11 @@ impl LegacyKeystore {

let key_hash = key_hash_from_private_key(&private_key);
let unlocker = self.crypto.use_key(key)?;
let network = self
let im_token_meta = self
.im_token_meta
.as_ref()
.expect("migrate to private need imTokenMeta");
let network = im_token_meta
.network
.clone()
.and_then(|net| IdentityNetwork::from_str(&net).ok())
Expand All @@ -251,7 +297,7 @@ impl LegacyKeystore {
version: PrivateKeystore::VERSION,
key_hash: key_hash.to_string(),
crypto: self.crypto.clone(),
meta: self.im_token_meta.to_metadata(),
meta: im_token_meta.to_metadata(),
identity,
};

Expand Down Expand Up @@ -299,8 +345,18 @@ impl LegacyKeystore {

#[cfg(test)]
mod tests {
use tcx_crypto::Key;
use tcx_keystore::Keystore;
use serde_json::Value;
use tcx_common::hex_to_bytes;
use tcx_constants::{CoinInfo, TEST_MNEMONIC};
use tcx_constants::{TEST_PASSWORD, TEST_PRIVATE_KEY};
use tcx_crypto::crypto::SCryptParams;
use tcx_crypto::hex;
use tcx_crypto::Crypto;
use tcx_crypto::Pbkdf2Params;
use tcx_crypto::{EncPair, Key};
use tcx_keystore::keystore::Store;
use tcx_keystore::HdKeystore;
use tcx_keystore::{Keystore, KeystoreGuard, Metadata, PrivateKeystore, Source};

use super::LegacyKeystore;

Expand Down Expand Up @@ -492,4 +548,13 @@ mod tests {
// .account("ETHEREUM", "0x6031564e7b2f5cc33737807b2e58daff870b590b")
// .is_some());
}

#[test]
fn test_export_v3_keystore() {
let private_key_bytes = hex_to_bytes(TEST_PRIVATE_KEY).unwrap();
let v3_keystore =
LegacyKeystore::new_v3(&private_key_bytes, TEST_PASSWORD).expect("v3 keystore");
let keystore_json = serde_json::to_string(&v3_keystore).expect("serde v3");
assert_eq!("", keystore_json);
}
}
Loading

0 comments on commit 98e41f5

Please sign in to comment.