Skip to content

Commit

Permalink
feat: add import private key and key hash
Browse files Browse the repository at this point in the history
  • Loading branch information
XuNeal committed Dec 15, 2023
1 parent 26133d2 commit c0ac358
Show file tree
Hide file tree
Showing 23 changed files with 497 additions and 367 deletions.
8 changes: 5 additions & 3 deletions token-core/tcx-btc-kin/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,8 @@ mod tests {
use super::*;

fn hex_keystore(hex: &str) -> Keystore {
let mut keystore = Keystore::from_private_key(hex, TEST_PASSWORD, Metadata::default());
let mut keystore =
Keystore::from_private_key(hex, TEST_PASSWORD, Metadata::default()).unwrap();
keystore.unlock_by_password(TEST_PASSWORD).unwrap();
keystore
}
Expand Down Expand Up @@ -616,7 +617,8 @@ mod tests {
"b0dabbf9ffed224fbca3b41a9e446b3d0b6240c6d2957197a8ab75bbf2e1a5d4",
TEST_PASSWORD,
Metadata::default(),
);
)
.unwrap();
ks.unlock_by_password(TEST_PASSWORD).unwrap();

let params = SignatureParameters {
Expand Down Expand Up @@ -1384,7 +1386,7 @@ mod tests {
.to_hex();

let mut keystore =
Keystore::from_private_key(&prv_key, TEST_PASSWORD, Metadata::default());
Keystore::from_private_key(&prv_key, TEST_PASSWORD, Metadata::default()).unwrap();
let _coin_info = coin_info_from_param("LITECOIN", "TESTNET", "NONE", "").unwrap();
let _ = keystore.unlock_by_password(TEST_PASSWORD).unwrap();
let params = SignatureParameters {
Expand Down
3 changes: 2 additions & 1 deletion token-core/tcx-ckb/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ mod tests {
"dcec27d0d975b0378471183a03f7071dea8532aaf968be796719ecd20af6988f",
"Password",
Metadata::default(),
);
)
.unwrap();
ks.unlock_by_password("Password").unwrap();

let coin_info = CoinInfo {
Expand Down
2 changes: 1 addition & 1 deletion token-core/tcx-common/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::Result;

pub fn utf8_or_hex_to_bytes(value: &str) -> Result<Vec<u8>> {
if value.to_lowercase().starts_with("0x") {
FromHex::from_hex_auto(value)
FromHex::from_0x_hex(value)
} else {
Ok(value.as_bytes().to_vec())
}
Expand Down
2 changes: 1 addition & 1 deletion token-core/tcx-eth/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ mod test {
use tcx_keystore::{Keystore, MessageSigner, Metadata, SignatureParameters, TransactionSigner};

fn private_key_store(key: &str) -> Keystore {
let mut ks = Keystore::from_private_key(key, "imToken1", Metadata::default());
let mut ks = Keystore::from_private_key(key, "imToken1", Metadata::default()).unwrap();
ks.unlock_by_password("imToken1").unwrap();
ks
}
Expand Down
4 changes: 2 additions & 2 deletions token-core/tcx-filecoin/src/key_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ use super::Error;
#[derive(Deserialize, Serialize, Debug)]
pub struct KeyInfo {
#[serde(rename = "Type")]
r#type: String,
pub r#type: String,

#[serde(rename = "PrivateKey")]
private_key: String,
pub private_key: String,
}

impl KeyInfo {
Expand Down
8 changes: 5 additions & 3 deletions token-core/tcx-filecoin/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@ mod tests {
&Vec::from_hex("7b2254797065223a22736563703235366b31222c22507269766174654b6579223a222f5059574777574e577a58614d5675437a613958502b314b4a695a4474696f4c76777863754268783041553d227d").unwrap()).unwrap();
let private_key = key_info.decode_private_key().unwrap();
let mut ks =
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default());
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default())
.unwrap();
ks.unlock_by_password("Password").unwrap();

let sign_context = SignatureParameters {
Expand Down Expand Up @@ -163,7 +164,8 @@ mod tests {
&Vec::from_hex("7b2254797065223a22626c73222c22507269766174654b6579223a2269376b4f2b7a78633651532b7637597967636d555968374d55595352657336616e6967694c684b463830383d227d").unwrap()).unwrap();
let private_key = key_info.decode_private_key().unwrap();
let mut ks =
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default());
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default())
.unwrap();
ks.unlock_by_password("Password").unwrap();

let sign_context = SignatureParameters {
Expand Down Expand Up @@ -205,7 +207,7 @@ mod tests {
&Vec::from_hex("7b2254797065223a22626c73222c22507269766174654b6579223a2269376b4f2b7a78633651532b7637597967636d555968374d55595352657336616e6967694c684b463830383d227d").unwrap()).unwrap();
let private_key = key_info.decode_private_key().unwrap();
let mut ks =
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default());
Keystore::from_private_key(&private_key.to_hex(), "Password", Metadata::default()).unwrap();
ks.unlock_by_password("Password").unwrap();

let sign_context = SignatureParameters {
Expand Down
60 changes: 40 additions & 20 deletions token-core/tcx-keystore/src/identity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,20 @@ pub struct Identity {
}

impl Identity {
pub fn new(seed: &Seed, unlocker: &Unlocker, network: &IdentityNetwork) -> Result<Self> {
let network_type = if network == &IdentityNetwork::Mainnet {
Network::Bitcoin
pub fn new(
master_private_key: &[u8],
unlocker: &Unlocker,
network: &IdentityNetwork,
) -> Result<Self> {
let (network_type, network_salt) = if network == &IdentityNetwork::Mainnet {
(Network::Bitcoin, "Mainnet")
} else {
Network::Testnet
(Network::Testnet, "Testnet")
};

let master_key = ExtendedPrivKey::new_master(network_type, seed.as_ref())?;

let network_salt = if network == &IdentityNetwork::Mainnet {
"Mainnet"
} else {
"Testnet"
};
let salt = format!("Automatic Backup Key {}", network_salt);

let backup_key = HMAC::mac(salt.as_bytes(), master_key.private_key.secret_bytes());
let backup_key = HMAC::mac(salt.as_bytes(), master_private_key);

let authentication_key = HMAC::mac("Authentication Key".as_bytes(), backup_key);

Expand Down Expand Up @@ -101,18 +98,24 @@ impl Identity {
}
let mnemonic = Mnemonic::from_phrase(mnemonic_phrase, Language::English).unwrap();
let seed = Seed::new(&mnemonic, "");
return Self::new(&seed, unlocker, network);

let network_type = if network == &IdentityNetwork::Mainnet {
Network::Bitcoin
} else {
Network::Testnet
};

let master_key = ExtendedPrivKey::new_master(network_type, seed.as_ref())?;
return Self::new(&master_key.private_key.secret_bytes(), unlocker, network);
}

pub fn from_private_key(
private_key: &str,
unlocker: &Unlocker,
network: &IdentityNetwork,
) -> Result<Self> {
let entropy = Vec::from_hex_auto(private_key)?;
let mnemonic = Mnemonic::from_entropy(&entropy, Language::English).unwrap();
let seed = Seed::new(&mnemonic, "");
return Self::new(&seed, unlocker, network);
let private_key_bytes = Vec::<u8>::from_hex_auto(private_key)?;
return Self::new(&private_key_bytes, unlocker, network);
}

pub fn calculate_ipfs_id(pub_key: &PublicKey) -> String {
Expand Down Expand Up @@ -392,15 +395,32 @@ mod test {
#[test]
fn test_create_identity_from_private_key() {
let meta = Metadata::default();
let keystore = PrivateKeystore::from_private_key(&PRIVATE_KEY, &PASSWORD, meta);
let keystore = PrivateKeystore::from_private_key(&PRIVATE_KEY, &PASSWORD, meta).unwrap();
let identity = &keystore.store().identity;

assert_eq!(
"im14x5GLbjpSGz4Y2ebqcP2aN2R1qY54qKsX6bj",
identity.identifier
);
assert_eq!(
"QmYS86Nzo9mi7ccBH7iZc11ModqXahbUxtTDNaZHU6EHqV",
identity.ipfs_id
);
}

#[test]
fn test_create_identity_from_private_key_testnet() {
let mut meta = Metadata::default();
meta.network = IdentityNetwork::Testnet;
let keystore = PrivateKeystore::from_private_key(&PRIVATE_KEY, &PASSWORD, meta).unwrap();
let identity = &keystore.store().identity;

assert_eq!(
"im14x5Ka4SC7WkwL1PzPtHvB1jdzLyaJ3tru511",
"im18MD7LnJJa6vkDd9jZmjqXw2N7K9KZuk2bGjW",
identity.identifier
);
assert_eq!(
"QmRYFQbmD37D4fvodcFvQtaSFo3mcAPJmYLPUHrr8w1teZ",
"QmYtS45NgsQBqZdJbJGn33DYPWGsSbmUbuuVoR2rdfaJWV",
identity.ipfs_id
);
}
Expand Down
2 changes: 1 addition & 1 deletion token-core/tcx-keystore/src/keystore/guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ mod tests {

assert!(ks.is_locked());

let mut ks = Keystore::from_private_key(PRIVATE_KEY, TEST_PASSWORD, Metadata::default());
let mut ks = Keystore::from_private_key(PRIVATE_KEY, TEST_PASSWORD, Metadata::default()).unwrap();
let derived_key = ks.get_derived_key(&TEST_PASSWORD).unwrap();

{
Expand Down
48 changes: 16 additions & 32 deletions token-core/tcx-keystore/src/keystore/hd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,10 @@ pub struct HdKeystore {
}

pub fn key_hash_from_mnemonic(mnemonic: &str) -> Result<String> {
let mn =
Mnemonic::from_phrase(mnemonic, Language::English).map_err(transform_mnemonic_error)?;

let seed = Seed::new(&mn, "");

let bytes = sha256d(seed.as_bytes())[..20].to_vec();
Ok(bytes.to_hex())
let xprv = TypedDeterministicPrivateKey::from_mnemonic(CurveType::SECP256k1, mnemonic)?;
let xpub = xprv.deterministic_public_key();
let fingerprint = xpub.fingerprint()?;
Ok(fingerprint.to_0x_hex())
}

impl HdKeystore {
Expand Down Expand Up @@ -261,13 +258,6 @@ mod tests {
assert_eq!(meta.source, expected.source);
}

#[test]
fn test_key_hash_from_mnemonic() {
let mnemonic = "inject kidney empty canal shadow pact comfort wife crush horse wife sketch";
let key_hash = key_hash_from_mnemonic(mnemonic).unwrap();
assert_eq!(key_hash, "512115eca3ae86646aeb06861d551e403b543509");
}

#[test]
fn test_new_keystore() {
let keystore = HdKeystore::new(TEST_PASSWORD, Metadata::default());
Expand Down Expand Up @@ -403,24 +393,6 @@ mod tests {
assert_eq!(format!("{}", wrong_password_err), "password_incorrect");
}

// #[test]
// pub fn generate_seed() {
// let mnemonic = Mnemonic::from_phrase(
// "favorite liar zebra assume hurt cage any damp inherit rescue delay panic",
// Language::English,
// )
// .unwrap();
//
// // let entropy = mnemonic.entropy();
//
// let seed = bip39::Seed::new(&mnemonic, &"").as_bytes().to_vec();
//
// assert_eq!(
// "235c69907d33b85f27bd78e73ff5d0c67bd4894515cc30c77f4391859bc1a3f2",
// hex::encode(seed)
// );
// }

#[test]
fn test_get_private_key() {
let mut keystore =
Expand Down Expand Up @@ -489,4 +461,16 @@ mod tests {

assert_eq!(acc, expected);
}

#[test]
fn test_key_hash_from_mnemonic() {
let key_hash = key_hash_from_mnemonic(&TEST_MNEMONIC).unwrap();
assert_eq!("0x1468dba9", key_hash);

let key_hash = key_hash_from_mnemonic(
"risk outer wing rent aerobic hamster island skin mistake high boost swear",
)
.unwrap();
assert_eq!("0xf6f23259", key_hash);
}
}
18 changes: 11 additions & 7 deletions token-core/tcx-keystore/src/keystore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ pub enum Source {
Wif,
Private,
KeystoreV3,
SubstrateKeystore,
Mnemonic,
NewMnemonic,
/*NewIdentity,
Expand All @@ -135,6 +136,7 @@ impl FromStr for Source {
"WIF" => Ok(Source::Wif),
"PRIVATE" => Ok(Source::Private),
"KEYSTORE_V3" => Ok(Source::KeystoreV3),
"SUBSTRATE_KEYSTORE" => Ok(Source::SubstrateKeystore),
"MNEMONIC" => Ok(Source::Mnemonic),
"NEW_MNEMONIC" => Ok(Source::NewMnemonic),
_ => Err(format_err!("unknown_source")),
Expand All @@ -147,6 +149,7 @@ impl fmt::Display for Source {
Source::Wif => write!(f, "WIF"),
Source::Private => write!(f, "PRIVATE"),
Source::KeystoreV3 => write!(f, "KEYSTORE_V3"),
Source::SubstrateKeystore => write!(f, "SUBSTRATE_KEYSTORE"),
Source::Mnemonic => write!(f, "MNEMONIC"),
Source::NewMnemonic => write!(f, "NEW_MNEMONIC"),
}
Expand Down Expand Up @@ -231,12 +234,12 @@ pub enum Keystore {
}

impl Keystore {
pub fn from_private_key(private_key: &str, password: &str, meta: Metadata) -> Keystore {
Keystore::PrivateKey(PrivateKeystore::from_private_key(
pub fn from_private_key(private_key: &str, password: &str, meta: Metadata) -> Result<Keystore> {
Ok(Keystore::PrivateKey(PrivateKeystore::from_private_key(
private_key,
password,
meta,
))
)?))
}

pub fn from_mnemonic(mnemonic: &str, password: &str, metadata: Metadata) -> Result<Keystore> {
Expand Down Expand Up @@ -529,8 +532,8 @@ impl ChainSigner for Keystore {
pub(crate) mod tests {
use crate::keystore::Keystore::{Hd, PrivateKey};
use crate::{
Address, ChainSigner, HdKeystore, Keystore, Metadata, PrivateKeystore, SignatureParameters,
Signer, Source,
Address, HdKeystore, Keystore, Metadata, PrivateKeystore, SignatureParameters, Signer,
Source,
};
use serde_json::Value;
use std::str::FromStr;
Expand Down Expand Up @@ -832,7 +835,8 @@ pub(crate) mod tests {
"a392604efc2fad9c0b3da43b5f698a2e3f270f170d859912be0d54742275c5f6",
TEST_PASSWORD,
meta,
);
)
.unwrap();
let keystore = PrivateKey(pk_store);
assert!(!keystore.derivable());

Expand Down Expand Up @@ -872,7 +876,7 @@ pub(crate) mod tests {
#[test]
fn test_private_keystore() {
let mut keystore =
Keystore::from_private_key(TEST_PRIVATE_KEY, TEST_PASSWORD, Metadata::default());
Keystore::from_private_key(TEST_PRIVATE_KEY, TEST_PASSWORD, Metadata::default()).unwrap();

assert!(keystore
.unlock(&Key::Password(TEST_PASSWORD.to_owned()))
Expand Down
Loading

0 comments on commit c0ac358

Please sign in to comment.