Skip to content

Commit

Permalink
feat: add biometric to more api
Browse files Browse the repository at this point in the history
  • Loading branch information
XuNeal committed Feb 6, 2024
1 parent 4accb41 commit 49b9e43
Show file tree
Hide file tree
Showing 14 changed files with 489 additions and 233 deletions.
1 change: 0 additions & 1 deletion token-core/tcx-btc-kin/src/signer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,7 +1153,6 @@ mod tests {
}

mod ltc {
//todo: test error
use super::*;

#[test]
Expand Down
2 changes: 2 additions & 0 deletions token-core/tcx-crypto/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ impl Crypto {
fn derive_key(&self, password: &str) -> Result<Vec<u8>> {
let mut derived_key: Credential = [0u8; CREDENTIAL_LEN];
self.kdf.derive_key(password.as_bytes(), &mut derived_key);

dbg!(hex::encode(derived_key));
Ok(derived_key.to_vec())
}

Expand Down
27 changes: 21 additions & 6 deletions token-core/tcx-keystore/src/keystore/hd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{transform_mnemonic_error, Account, Address, Error, Metadata, Result,

use std::collections::{hash_map::Entry, HashMap};

use tcx_common::ToHex;
use tcx_common::{FromHex, ToHex};
use tcx_constants::{coin_info::get_xpub_prefix, CoinInfo, CurveType};
use tcx_crypto::{Crypto, Key};
use tcx_primitive::{
Expand Down Expand Up @@ -224,8 +224,18 @@ impl HdKeystore {
&self.store().identity
}

pub(crate) fn verify_password(&self, password: &str) -> bool {
self.store.crypto.verify_password(password)
pub(crate) fn verify_password(&self, key: &Key) -> bool {
match key {
Key::Password(password) => {
return self.store.crypto.verify_password(password);
}
Key::DerivedKey(derived_key_hex) => {
let Ok(derived_key) = Vec::from_hex_auto(derived_key_hex) else {
return false;
};
return self.store.crypto.verify_derived_key(&derived_key);
}
}
}
}

Expand All @@ -235,7 +245,7 @@ mod tests {
use crate::keystore::{metadata_default_time, IdentityNetwork};

use crate::keystore::tests::MockAddress;
use crate::Source;
use crate::{Keystore, Source};
use bitcoin_hashes::hex::ToHex;
use std::string::ToString;
use tcx_common::FromHex;
Expand All @@ -258,8 +268,13 @@ mod tests {
let keystore =
HdKeystore::from_mnemonic(TEST_MNEMONIC, TEST_PASSWORD, Metadata::default()).unwrap();

assert!(keystore.verify_password(TEST_PASSWORD));
assert!(!keystore.verify_password("WrongPassword"));
let derived_key = Keystore::Hd(keystore.clone())
.get_derived_key(TEST_PASSWORD)
.unwrap();
assert!(keystore.verify_password(&Key::Password(TEST_PASSWORD.to_string())));
assert!(keystore.verify_password(&Key::DerivedKey(derived_key.to_string())));
assert!(!keystore.verify_password(&Key::Password("WRONG PASSWORD".to_string())));
assert!(!keystore.verify_password(&Key::DerivedKey("731dd44109f9897eb39980907161b7531be44714352ddaa40542da22fb4fab7533678f2e132226389174faad4e653c542811a7b0c9391ae3cce4e75039a15adc".to_string())));
}

#[test]
Expand Down
36 changes: 20 additions & 16 deletions token-core/tcx-keystore/src/keystore/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,8 @@ impl Keystore {
}
}

pub fn backup(&self, password: &str) -> Result<String> {
let unlocker = self
.store()
.crypto
.use_key(&Key::Password(password.to_string()))?;
pub fn backup(&self, key: &Key) -> Result<String> {
let unlocker = self.store().crypto.use_key(key)?;
let decrypted = unlocker.decrypt_enc_pair(&self.store().enc_original)?;
let original = String::from_utf8_lossy(&decrypted);
Ok(original.to_string())
Expand All @@ -417,10 +414,10 @@ impl Keystore {
&self.store().identity
}

pub fn verify_password(&self, password: &str) -> bool {
pub fn verify_password(&self, key: &Key) -> bool {
match self {
Keystore::PrivateKey(ks) => ks.verify_password(password),
Keystore::Hd(ks) => ks.verify_password(password),
Keystore::PrivateKey(ks) => ks.verify_password(key),
Keystore::Hd(ks) => ks.verify_password(key),
}
}

Expand Down Expand Up @@ -773,8 +770,11 @@ pub(crate) mod tests {
"password_incorrect"
);

assert!(keystore.verify_password(TEST_PASSWORD));
assert!(!keystore.verify_password("WRONG PASSWORD"));
let derived_key = keystore.get_derived_key(TEST_PASSWORD).unwrap();
assert!(keystore.verify_password(&Key::Password(TEST_PASSWORD.to_string())));
assert!(keystore.verify_password(&Key::DerivedKey(derived_key.to_string())));
assert!(!keystore.verify_password(&Key::Password("WRONG PASSWORD".to_string())));
assert!(!keystore.verify_password(&Key::DerivedKey("731dd44109f9897eb39980907161b7531be44714352ddaa40542da22fb4fab7533678f2e132226389174faad4e653c542811a7b0c9391ae3cce4e75039a15adc".to_string())));
keystore.unlock_by_password(TEST_PASSWORD).unwrap();
assert_eq!(
"inject kidney empty canal shadow pact comfort wife crush horse wife sketch",
Expand Down Expand Up @@ -889,9 +889,11 @@ pub(crate) mod tests {
assert!(keystore.identity().identifier.starts_with("im"));
assert_eq!(keystore.meta().name, "Unknown");
assert_ne!(keystore.id(), "");

assert!(keystore.verify_password(&TEST_PASSWORD));
assert!(!keystore.verify_password(&WRONG_PASSWORD));
let derived_key = keystore.get_derived_key(TEST_PASSWORD).unwrap();
assert!(keystore.verify_password(&Key::Password(TEST_PASSWORD.to_string())));
assert!(keystore.verify_password(&Key::DerivedKey(derived_key.to_string())));
assert!(!keystore.verify_password(&Key::Password("WRONG PASSWORD".to_string())));
assert!(!keystore.verify_password(&Key::DerivedKey("731dd44109f9897eb39980907161b7531be44714352ddaa40542da22fb4fab7533678f2e132226389174faad4e653c542811a7b0c9391ae3cce4e75039a15adc".to_string())));

let coin_info = CoinInfo {
coin: "BITCOIN".to_string(),
Expand Down Expand Up @@ -959,9 +961,11 @@ pub(crate) mod tests {
format!("0x{}", keystore.export().unwrap()),
TEST_PRIVATE_KEY.to_string()
);

assert!(keystore.verify_password(&TEST_PASSWORD));
assert!(!keystore.verify_password(&WRONG_PASSWORD));
let derived_key = keystore.get_derived_key(TEST_PASSWORD).unwrap();
assert!(keystore.verify_password(&Key::Password(TEST_PASSWORD.to_string())));
assert!(keystore.verify_password(&Key::DerivedKey(derived_key.to_string())));
assert!(!keystore.verify_password(&Key::Password("WRONG PASSWORD".to_string())));
assert!(!keystore.verify_password(&Key::DerivedKey("731dd44109f9897eb39980907161b7531be44714352ddaa40542da22fb4fab7533678f2e132226389174faad4e653c542811a7b0c9391ae3cce4e75039a15adc".to_string())));

let coin_info = CoinInfo {
coin: "BITCOIN".to_string(),
Expand Down
26 changes: 21 additions & 5 deletions token-core/tcx-keystore/src/keystore/private.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::Account;
use super::{Address, Metadata};
use bitcoin::util;
use tcx_constants::{CoinInfo, CurveType};
use tcx_crypto::{Crypto, Key};

Expand Down Expand Up @@ -82,8 +83,18 @@ impl PrivateKeystore {
Ok(account)
}

pub(crate) fn verify_password(&self, password: &str) -> bool {
self.store.crypto.verify_password(password)
pub(crate) fn verify_password(&self, key: &Key) -> bool {
match key {
Key::Password(password) => {
return self.store.crypto.verify_password(password);
}
Key::DerivedKey(derived_key_hex) => {
let Ok(derived_key) = Vec::from_hex_auto(derived_key_hex) else {
return false;
};
return self.store.crypto.verify_derived_key(&derived_key);
}
}
}

pub fn from_private_key(
Expand Down Expand Up @@ -160,7 +171,7 @@ impl PrivateKeystore {
mod tests {
use crate::keystore::private::fingerprint_from_private_key;
use crate::keystore::tests::MockAddress;
use crate::{Metadata, PrivateKeystore, Source};
use crate::{Keystore, Metadata, PrivateKeystore, Source};
use tcx_common::FromHex;
use tcx_constants::{CoinInfo, CurveType, TEST_PASSWORD, TEST_PRIVATE_KEY};
use tcx_crypto::Key;
Expand Down Expand Up @@ -205,8 +216,13 @@ mod tests {
)
.unwrap();

assert!(keystore.verify_password(TEST_PASSWORD));
assert!(!keystore.verify_password("WrongPassword"));
let derived_key = Keystore::PrivateKey(keystore.clone())
.get_derived_key(TEST_PASSWORD)
.unwrap();
assert!(keystore.verify_password(&Key::Password(TEST_PASSWORD.to_string())));
assert!(keystore.verify_password(&Key::DerivedKey(derived_key.to_string())));
assert!(!keystore.verify_password(&Key::Password("WRONG PASSWORD".to_string())));
assert!(!keystore.verify_password(&Key::DerivedKey("731dd44109f9897eb39980907161b7531be44714352ddaa40542da22fb4fab7533678f2e132226389174faad4e653c542811a7b0c9391ae3cce4e75039a15adc".to_string())));
}

#[test]
Expand Down
105 changes: 56 additions & 49 deletions token-core/tcx-migration/src/keystore_upgrade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,13 +576,15 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();
assert_eq!(
ori,
"685634d212eabe016a1cb09d9f1ea1ea757ebe590b9a097d7b1c9379ad280171"
);

let ori = ks.backup(&Key::DerivedKey("1a60471067b6c6a3202e0014de2ce9b2d45fd73e2289b3cc3d8e5b58fe99ff242fd61e9fe63e75abbdc0ed87a50756cc10c57daf1d6297b99ec9a3b174eee017".to_string())).unwrap();
assert_eq!(
ori,
"685634d212eabe016a1cb09d9f1ea1ea757ebe590b9a097d7b1c9379ad280171"
Expand All @@ -596,13 +598,15 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();
assert_eq!(
ori,
"edskS3E5CLrkwHRYAbDvw5xC913C9GGseMcyNGeGbeaD57Yvvi2jqizpAAZyzUtRK626UvkKYdJwCYE9oKMcqFCtJeBpDYcrVH"
);

let ori = ks.backup(&Key::DerivedKey("b009d3c4e961411836028a9fffbea994e03c71f75589a571cd52125884537f2ac165b92e7bc49c7828d4be0c5c05263a306744f0b9dc785142c8562d45ce4345".to_string())).unwrap();
assert_eq!(
ori,
"edskS3E5CLrkwHRYAbDvw5xC913C9GGseMcyNGeGbeaD57Yvvi2jqizpAAZyzUtRK626UvkKYdJwCYE9oKMcqFCtJeBpDYcrVH"
Expand All @@ -616,13 +620,13 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();

assert_eq!(ori, "TBRMznXcDf2HK2jBKJsqjBpsEdaiaZUBGKN8aKdwTMrPnMNB5UQM");
let ori = ks.backup(&Key::DerivedKey("2e70651f06a28d2f6053a90ee55ab8cb14518ab82182cd922926b4239713286ac6746ad4448608fc1599e6f4e0af33c65f70bc5de13a376933e5e145681d0f80".to_string())).unwrap();

assert_eq!(ori, "TBRMznXcDf2HK2jBKJsqjBpsEdaiaZUBGKN8aKdwTMrPnMNB5UQM");
}

Expand All @@ -633,13 +637,14 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();

assert_eq!(ori, "L1xDTJYPqhofU8DQCiwjStEBr1X6dhiNfweUhxhoRSgYyMJPcZ6B");

let ori = ks.backup(&Key::DerivedKey("d175dad756f59a59b6a311f2b369802537d92011c8e3bf6dc2dfaf8df00d942648bf83133bd0204ebc43efcbd0ab79a8d5551c8dcf7ae1f67fc2d1d4aff33c06".to_string())).unwrap();

assert_eq!(ori, "L1xDTJYPqhofU8DQCiwjStEBr1X6dhiNfweUhxhoRSgYyMJPcZ6B");
}

Expand All @@ -650,13 +655,11 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();
assert!(ori.contains("FDS7ZJpJg4R7Kd2hzfsEc6mtW5iknjZ3UazX76EsnbH74v8"));
let ori = ks.backup(&Key::DerivedKey("daa734e276c7420bd7eb6f9d59d39f3072d9ab0c4c0bda09eb410ab930c745302fb39714a2c4ca1935b18d1d216db11455a4c962daf8bf360ba41c65d872a5a8".to_string())).unwrap();
assert!(ori.contains("FDS7ZJpJg4R7Kd2hzfsEc6mtW5iknjZ3UazX76EsnbH74v8"));
}

Expand All @@ -667,13 +670,15 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();

let expected_ori =
r#"{"Type":"secp256k1","PrivateKey":"o5JgTvwvrZwLPaQ7X2mKLj8nDxcNhZkSvg1UdCJ1xfY="}"#;
assert_eq!(ori, expected_ori.as_bytes().to_hex());

let ori = ks.backup(&Key::DerivedKey("bee56a3cc9e6536dd22a695742ff1b4a00a797fa6c0ddd6f2c3bfd2ec25d05d61918ab3ceaf5c135f771d957889ee2b361c5d70f1911cc8857299d349a0d9ee6".to_string())).unwrap();
let expected_ori =
r#"{"Type":"secp256k1","PrivateKey":"o5JgTvwvrZwLPaQ7X2mKLj8nDxcNhZkSvg1UdCJ1xfY="}"#;
assert_eq!(ori, expected_ori.as_bytes().to_hex());
Expand All @@ -686,13 +691,15 @@ mod tests {
);
let json = serde_json::from_str(json_str).unwrap();
let old_ks = KeystoreUpgrade::new(json);
let ks = old_ks
.upgrade(
&Key::Password(TEST_PASSWORD.to_string()),
&IdentityNetwork::Mainnet,
)
.unwrap();
let ori = ks.backup(TEST_PASSWORD).unwrap();
let key = Key::Password(TEST_PASSWORD.to_string());
let ks = old_ks.upgrade(&key, &IdentityNetwork::Mainnet).unwrap();
let ori = ks.backup(&key).unwrap();

let expected_ori =
r#"{"Type":"bls","PrivateKey":"i7kO+zxc6QS+v7YygcmUYh7MUYSRes6anigiLhKF808="}"#;
assert_eq!(ori, expected_ori.as_bytes().to_hex());

let ori = ks.backup(&Key::DerivedKey("f3207a9f25adbdae5eff58bb13a9d9be4d763c6d47269fb14e4bd7a59ed667ba7282f1ba40746c60ae842c3f9dfeba91060f29f547ef2a94a66cfee93573ffaa".to_string())).unwrap();
let expected_ori =
r#"{"Type":"bls","PrivateKey":"i7kO+zxc6QS+v7YygcmUYh7MUYSRes6anigiLhKF808="}"#;
assert_eq!(ori, expected_ori.as_bytes().to_hex());
Expand Down
Loading

0 comments on commit 49b9e43

Please sign in to comment.