diff --git a/examples/test.rs b/examples/test.rs index ef7d954..94ad70b 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -5,9 +5,9 @@ // use rustwallet::{ - aes_decrypt, aes_encrypt, free_cwallet, generate_sec_key, get_address, get_public_key, - hash_pass_svr, hex_deflate, hex_inflate, keccak256_hash, new_wallet, rencrypt, sign, - sign_for_tran, wallet_decrypt, wallet_encrypt, CWallet, + aes_decrypt, aes_encrypt, generate_sec_key, get_address, get_public_key, hash_pass_svr, + hex_deflate, hex_inflate, keccak256_hash, local_pass_hasher, rencrypt, sign, sign_for_tran, + wallet_decrypt, wallet_encrypt, }; use std::ffi::{CStr, CString}; use std::os::raw::c_char; @@ -57,27 +57,23 @@ fn main() { // print_cchar!(s_key); let key0 = "3f26e586111b5c4cab6a5dd5e0d13c3b13184ba74410ba064a3b485be4f9a2cd"; - let key1 = ""; - let key2 = "cd00eb0126aeed39762579ce94c90a04695ad17fbd5e79aa4e9fc4a34ba32a5"; + let key1 = "cd00eb0126aeed39762579ce94c90a04695ad17fbd5e79aa4e9fc4a34ba32a5"; let address2 = get_address( str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), ); print_cchar!(address2); let key_public = get_public_key( str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), ); print_cchar!(key_public); let key_private = generate_sec_key( str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), ); print_cchar!(key_private); let msg = "hello world"; @@ -85,7 +81,6 @@ fn main() { str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), str_to_cchar!(msg), ); print_cchar!(str_signed); @@ -94,7 +89,6 @@ fn main() { str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), str_to_cchar!(tran_str), ); print_cchar!(str_signed2); @@ -103,7 +97,6 @@ fn main() { str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), str_to_cchar!(msg), ); print_cchar!(str_encrypt); @@ -111,23 +104,10 @@ fn main() { str_to_cchar!(msg_key), str_to_cchar!(key0), str_to_cchar!(key1), - str_to_cchar!(key2), str_encrypt, ); print_cchar!(str_decrypt); - let pk = "031a8338368250f544b6cc8f5d72d77ab13bd067f51d4e84b8148edcc6595327e2"; - let str_encrypt2 = rencrypt(str_to_cchar!(pk), str_to_cchar!(msg)); - print_cchar!(str_encrypt2); - let str_decrypt2 = wallet_decrypt( - str_to_cchar!(msg_key), - str_to_cchar!(key0), - str_to_cchar!(key1), - str_to_cchar!(key2), - str_encrypt2, - ); - print_cchar!(str_decrypt2); - let str_encode = hex_deflate(key_public); print_cchar!(str_encode); @@ -137,21 +117,20 @@ fn main() { let msg = "$argon2id$v=19$m=19456,t=2,p=1$adcr3ix1Mpcx2wWd/It8gw$VG1I+RrEQ5rbKlGiVDB2Lux50XTfxgaxLsvHG4SCtTI"; let result = keccak256_hash(str_to_cchar!(msg)); print_cchar!(result); - let address2 = get_address( - str_to_cchar!(msg_key), - str_to_cchar!(key0), - result, - str_to_cchar!(key1), - ); + let address2 = get_address(str_to_cchar!(msg_key), str_to_cchar!(key0), result); print_cchar!(address2); let pass = "111111"; let hash_pass = hash_pass_svr(str_to_cchar!(pass)); print_cchar!(hash_pass); - - let str_encrypt = aes_encrypt(str_to_cchar!(pass)); + let aes_key = "111111"; + let str_encrypt = aes_encrypt(str_to_cchar!(pass), str_to_cchar!(aes_key)); print_cchar!(str_encrypt); - let str_plain = aes_decrypt(str_encrypt); + let str_plain = aes_decrypt(str_encrypt, str_to_cchar!(aes_key)); print_cchar!(str_plain); + + let salt = "11213xxx"; + let local_pass_hass = local_pass_hasher(str_to_cchar!(pass), str_to_cchar!(salt)); + print_cchar!(local_pass_hass); } } diff --git a/rustwallet.h b/rustwallet.h index b4f35b2..6c68363 100644 --- a/rustwallet.h +++ b/rustwallet.h @@ -3,47 +3,17 @@ #include #include -typedef struct CWallet { - char *msg_key; - char *master_key; - char *second_key; - char *backup_key; -} CWallet; +char *get_address(const char *msg_key, const char *master_key, const char *second_key); -struct CWallet new_wallet(const char *msg); +char *get_public_key(const char *msg_key, const char *master_key, const char *second_key); -struct CWallet reset_wallet(const char *msg_key, - const char *master_key, - const char *second_key, - const char *backup_key); +char *generate_sec_key(const char *msg_key, const char *master_key, const char *second_key); -void free_cwallet(struct CWallet cw); - -char *get_address(const char *msg_key, - const char *master_key, - const char *second_key, - const char *backup_key); - -char *get_public_key(const char *msg_key, - const char *master_key, - const char *second_key, - const char *backup_key); - -char *generate_sec_key(const char *msg_key, - const char *master_key, - const char *second_key, - const char *backup_key); - -char *sign(const char *msg_key, - const char *master_key, - const char *second_key, - const char *backup_key, - const char *msg); +char *sign(const char *msg_key, const char *master_key, const char *second_key, const char *msg); char *sign_for_tran(const char *msg_key, const char *master_key, const char *second_key, - const char *backup_key, const char *msg); char *rencrypt(const char *pk, const char *msg); @@ -51,15 +21,27 @@ char *rencrypt(const char *pk, const char *msg); char *wallet_encrypt(const char *msg_key, const char *master_key, const char *second_key, - const char *backup_key, const char *msg); char *wallet_decrypt(const char *msg_key, const char *master_key, const char *second_key, - const char *backup_key, const char *msg); char *hex_deflate(const char *content); char *hex_inflate(const char *content); + +char *hash_pass_svr(const char *content); + +char *keccak256_hash(const char *content); + +char *aes_encrypt(const char *content, const char *key); + +char *aes_decrypt(const char *content, const char *key); + +char *local_pass_hasher(const char *password, const char *salt); + +bool verify_local_pass(const char *password, const char *pass_hash); + +char *generate_client_key(const char *password, const char *openid, const char *salt); diff --git a/scripts/android_build.sh b/scripts/android_build.sh index 0dd6bef..c090388 100755 --- a/scripts/android_build.sh +++ b/scripts/android_build.sh @@ -1,5 +1,6 @@ #!/usr/bin/env bash # set the version to use the library +export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/23.2.8568313" min_ver=22 # verify before executing this that you have the proper targets installed cargo ndk -t armeabi-v7a -t arm64-v8a -t x86_64 -t x86 -p ${min_ver} build --release diff --git a/src/lib.rs b/src/lib.rs index 005a725..b7f5247 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,19 +36,6 @@ macro_rules! cchar_to_string { }}; } -macro_rules! cchar_to_ostring { - ($p1:expr) => {{ - let s = CStr::from_ptr($p1); - let pb = s.to_str().unwrap(); - let result = if pb.is_empty() { - None - } else { - Some(pb.to_string()) - }; - result - }}; -} - macro_rules! str_to_cchar { ($p1:expr) => {{ let msgkey = CString::new($p1).unwrap(); @@ -57,60 +44,13 @@ macro_rules! str_to_cchar { }}; } -macro_rules! ostr_to_cchar { - ($p1:expr) => {{ - let key = match $p1 { - Some(val) => CString::new(val).unwrap(), - None => CString::new("").unwrap(), - }; - let c_key: *mut c_char = key.into_raw(); - c_key - }}; -} - -#[repr(C)] -pub struct CWallet { - pub msg_key: *mut c_char, - pub master_key: *mut c_char, - pub second_key: *mut c_char, - pub backup_key: *mut c_char, -} - -#[no_mangle] -pub unsafe extern "C" fn new_wallet(msg: *const c_char) -> CWallet { - let str = cchar_to_str!(msg); - let rust_wallet = wallet_impl::Wallet::new(str); - convert_to_cwallet(rust_wallet) -} - -#[no_mangle] -pub unsafe extern "C" fn reset_wallet( - msg_key: *const c_char, - master_key: *const c_char, - second_key: *const c_char, - backup_key: *const c_char, -) -> CWallet { - let rust_wallet = generate_rwallet(msg_key, master_key, second_key, backup_key); - let rust_wallet2 = rust_wallet.reset_wallet(); - convert_to_cwallet(rust_wallet2) -} - -#[no_mangle] -pub unsafe extern "C" fn free_cwallet(cw: CWallet) { - drop(CString::from_raw(cw.msg_key)); - drop(CString::from_raw(cw.master_key)); - drop(CString::from_raw(cw.second_key)); - drop(CString::from_raw(cw.backup_key)); -} - #[no_mangle] pub unsafe extern "C" fn get_address( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let address = rwallet.get_address(); let address_str = format!("{:?}", address); let c_address = CString::new(address_str).unwrap(); @@ -122,9 +62,8 @@ pub unsafe extern "C" fn get_public_key( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let pk = rwallet.get_public_key(); let c_pk = CString::new(pk.to_string()).unwrap(); c_pk.into_raw() @@ -135,9 +74,8 @@ pub unsafe extern "C" fn generate_sec_key( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let s_key = rwallet.generate_sec_key(); let cs_key = CString::new(s_key).unwrap(); cs_key.into_raw() @@ -148,10 +86,9 @@ pub unsafe extern "C" fn sign( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, msg: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let msg_str = cchar_to_str!(msg); let signature = rwallet.sign(msg_str); let r = match signature { @@ -166,10 +103,9 @@ pub unsafe extern "C" fn sign_for_tran( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, msg: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let msg_str = cchar_to_str!(msg); println!("msg for sign tran: {}", &msg_str); let signature = rwallet.sign_for_tran(msg_str); @@ -201,10 +137,9 @@ pub unsafe extern "C" fn wallet_encrypt( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, msg: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let msg_str = cchar_to_str!(msg); let pk = rwallet.get_public_key(); let msg_encrypt = match zencrypt(pk, msg_str) { @@ -219,10 +154,9 @@ pub unsafe extern "C" fn wallet_decrypt( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, msg: *const c_char, ) -> *mut c_char { - let rwallet = generate_rwallet(msg_key, master_key, second_key, backup_key); + let rwallet = generate_rwallet(msg_key, master_key, second_key); let msg_str = cchar_to_str!(msg); let sk = rwallet.get_secret_key(); let msg_decrypt = match zdecrypt(sk, msg_str) { @@ -253,12 +187,6 @@ pub unsafe extern "C" fn hash_pass_svr(content: *const c_char) -> *mut c_char { str_to_cchar!(msg_hex) } #[no_mangle] -pub unsafe extern "C" fn hash_pass_client(content: *const c_char) -> *mut c_char { - let content_str = cchar_to_str!(content); - let msg_hex = utils::crypto_utils::hash_pass_client(&content_str); - str_to_cchar!(msg_hex) -} -#[no_mangle] pub unsafe extern "C" fn keccak256_hash(content: *const c_char) -> *mut c_char { let content_str = cchar_to_str!(content); let msg_hex = utils::crypto_utils::keccak256_hash(&content_str); @@ -266,50 +194,65 @@ pub unsafe extern "C" fn keccak256_hash(content: *const c_char) -> *mut c_char { } #[no_mangle] -pub unsafe extern "C" fn aes_encrypt(content: *const c_char) -> *mut c_char { +pub unsafe extern "C" fn aes_encrypt(content: *const c_char, key: *const c_char) -> *mut c_char { let content_str = cchar_to_str!(content); - let pass = "2a3a6e3ef5e6e4617a09d91014cb54dcdc0dd6dcb1809d3f5701779651e51cf2"; + let pass = cchar_to_str!(key); + let pass = utils::crypto_utils::keccak256_hash(pass); let msg_hex = utils::crypto_utils::aes_encrypt(&content_str, &pass); str_to_cchar!(msg_hex) } #[no_mangle] -pub unsafe extern "C" fn aes_decrypt(content: *const c_char) -> *mut c_char { +pub unsafe extern "C" fn aes_decrypt(content: *const c_char, key: *const c_char) -> *mut c_char { let content_str = cchar_to_str!(content); - let pass = "2a3a6e3ef5e6e4617a09d91014cb54dcdc0dd6dcb1809d3f5701779651e51cf2"; + let pass = cchar_to_str!(key); + let pass = utils::crypto_utils::keccak256_hash(pass); let msg_hex = utils::crypto_utils::aes_decrypt(&content_str, &pass); str_to_cchar!(msg_hex) } -unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet { - let c_msgkey: *mut c_char = str_to_cchar!(rwallet.msg_key); - let c_masterkey: *mut c_char = str_to_cchar!(rwallet.master_key); - let c_secondkey = ostr_to_cchar!(rwallet.second_key); - let c_backupkey = ostr_to_cchar!(rwallet.backup_key); +#[no_mangle] +pub unsafe extern "C" fn local_pass_hasher( + password: *const c_char, + salt: *const c_char, +) -> *mut c_char { + let result = wallet_impl::local_pass_hasher(cchar_to_str!(password), cchar_to_str!(salt)); + str_to_cchar!(result) +} - let cw = CWallet { - msg_key: c_msgkey, - master_key: c_masterkey, - second_key: c_secondkey, - backup_key: c_backupkey, - }; - cw +#[no_mangle] +pub unsafe extern "C" fn verify_local_pass( + password: *const c_char, + pass_hash: *const c_char, +) -> bool { + utils::crypto_utils::verify_password(cchar_to_str!(password), cchar_to_str!(pass_hash)) +} + +#[no_mangle] +pub unsafe extern "C" fn generate_client_key( + password: *const c_char, + openid: *const c_char, + salt: *const c_char, +) -> *mut c_char { + let result = wallet_impl::generate_client_key( + cchar_to_str!(password), + cchar_to_str!(openid), + cchar_to_str!(salt), + ); + str_to_cchar!(result) } unsafe fn generate_rwallet( msg_key: *const c_char, master_key: *const c_char, second_key: *const c_char, - backup_key: *const c_char, ) -> Wallet { let pmsg = cchar_to_string!(msg_key); let pm = cchar_to_string!(master_key); - let second_key = cchar_to_ostring!(second_key); - let backup_key = cchar_to_ostring!(backup_key); + let second_key = cchar_to_string!(second_key); Wallet { msg_key: pmsg, master_key: pm, second_key: second_key, - backup_key: backup_key, } } diff --git a/src/utils/crypto_utils.rs b/src/utils/crypto_utils.rs index e073db3..a06a0ae 100644 --- a/src/utils/crypto_utils.rs +++ b/src/utils/crypto_utils.rs @@ -14,8 +14,13 @@ use secp256k1::{PublicKey, SecretKey}; use std::str; use tiny_keccak::keccak256; -pub fn hash_password(pass: &str) -> String { +pub fn random_argon2_salt() -> String { let salt: SaltString = SaltString::generate(&mut OsRng); + salt.as_str().to_string() +} +pub fn hash_password(pass: &str, salt: &str) -> String { + // let salt: SaltString = SaltString::generate(&mut OsRng); + let salt = SaltString::from_b64(salt).expect("error parse salt"); let password = pass.as_bytes(); let password_hash: String = match Argon2::default().hash_password(password, &salt) { Ok(v) => v.to_string(), @@ -121,7 +126,7 @@ pub fn aes_decrypt(str: &str, key: &str) -> String { let plaintext = str::from_utf8(&plaintext).expect("err convert to utf8"); plaintext.to_string() } - +// encrypt content with wallet public key pub fn zencrypt(pk: PublicKey, msg: &str) -> Result { let pk = &pk.serialize(); let msg = msg.as_bytes(); @@ -134,7 +139,7 @@ pub fn zencrypt(pk: PublicKey, msg: &str) -> Result { let str_encrypt = hex::encode(&msg_encrypt); Ok(str_encrypt) } - +// decrypt content with wallet private key pub fn zdecrypt(sk: SecretKey, msg1: &str) -> Result { let sk = sk.secret_bytes(); let mut msg: String = msg1.clone().to_string(); diff --git a/src/wallet/wallet_impl.rs b/src/wallet/wallet_impl.rs index 2871d6e..b303389 100644 --- a/src/wallet/wallet_impl.rs +++ b/src/wallet/wallet_impl.rs @@ -1,9 +1,10 @@ extern crate hex; +use crate::utils::{crypto_utils as crypro_utils, str_utils}; use anyhow::Result; use core::fmt::Write; use primitive_types::{H160, H256}; -use secp256k1::rand::rngs::OsRng; +// use secp256k1::rand::rngs::OsRng; use secp256k1::{Message, PublicKey, Secp256k1, SecretKey}; use serde::{Deserialize, Serialize}; use shamir_secret_sharing::num_bigint::BigInt; @@ -12,12 +13,34 @@ use std::str; use std::str::FromStr; use tiny_keccak::keccak256; -pub fn generate_keypair() -> (SecretKey, PublicKey) { - let secp = Secp256k1::new(); - // let mut rng = OsRng::new().expect("OsRng"); - secp.generate_keypair(&mut OsRng) +// generate client key +pub fn generate_client_key(password: &str, openid: &str, salt: &str) -> String { + let password = crypro_utils::hash_pass_client(password); + let mut s = String::new(); + s.push_str(&password); + s.push_str(openid); + let salt = crypro_utils::keccak256_hash(&salt); + let salt = str_utils::hex_to_base64(&salt); + let pass_hash = crypro_utils::hash_password(&s, &salt); + let key = crypro_utils::keccak256_hash(&pass_hash); + key } +pub fn local_pass_hasher(password: &str, salt: &str) -> String { + let password = crypro_utils::hash_pass_client(password); + let mut s = String::new(); + s.push_str(&password); + s.push_str(salt); + let salt = crypro_utils::random_argon2_salt(); + let pass_hash = crypro_utils::hash_password(&s, &salt); + pass_hash +} + +// pub fn generate_keypair() -> (SecretKey, PublicKey) { +// let secp = Secp256k1::new(); +// secp.generate_keypair(&mut OsRng) +// } + pub fn public_key_address(public_key: &PublicKey) -> H160 { let public_key = public_key.serialize_uncompressed(); debug_assert_eq!(public_key[0], 0x04); @@ -42,16 +65,16 @@ pub fn get_sss(msg: &str) -> SSS { } } -pub fn generate_sss_keypair(msg: &str, skey: &str) -> Vec { - let secret = BigInt::parse_bytes(&skey.as_bytes(), 16).unwrap(); - let sss = get_sss(msg); - let shares = sss.split(secret.clone()); - let mut shares_str: Vec = Vec::new(); - for (_i, v) in &shares { - shares_str.push(v.to_str_radix(16)); - } - shares_str -} +// pub fn generate_sss_keypair(msg: &str, skey: &str) -> Vec { +// let secret = BigInt::parse_bytes(&skey.as_bytes(), 16).unwrap(); +// let sss = get_sss(msg); +// let shares = sss.split(secret.clone()); +// let mut shares_str: Vec = Vec::new(); +// for (_i, v) in &shares { +// shares_str.push(v.to_str_radix(16)); +// } +// shares_str +// } pub fn hash_message(message: S) -> H256 where @@ -69,55 +92,17 @@ where pub struct Wallet { pub msg_key: String, pub master_key: String, - pub second_key: Option, - pub backup_key: Option, + pub second_key: String, } impl Wallet { - pub fn new(msg: &str) -> Self { - let (secret_key, _pub_key) = generate_keypair(); - let s = hex::encode(&secret_key.secret_bytes()); - let shares_str = generate_sss_keypair(msg, &s); - // println!("secret key: {:?}", secret_key); - // println!("{:?}", s); - let second_key = shares_str.get(1).map(String::clone); - let backup_key = shares_str.get(2).map(String::clone); - Wallet { - msg_key: msg.to_string(), - master_key: shares_str.get(0).unwrap().to_string(), - second_key: second_key, - backup_key: backup_key, - } - } - - pub fn reset_wallet(&self) -> Self { - let secret_key = self.get_secret_key(); - let s = hex::encode(&secret_key.secret_bytes()); - let shares_str = generate_sss_keypair(&self.msg_key, &s); - let second_key = shares_str.get(1).map(String::clone); - let backup_key = shares_str.get(2).map(String::clone); - - Wallet { - msg_key: self.msg_key.clone(), - master_key: shares_str.get(0).unwrap().to_string(), - second_key: second_key, - backup_key: backup_key, - } - } - pub fn get_secret_key(&self) -> SecretKey { let key_str_0: &str = &self.master_key; let key0 = BigInt::parse_bytes(&key_str_0.as_bytes(), 16).unwrap(); let kp0: (usize, BigInt) = (1, key0); - let (i, key_str_1) = match (&self.second_key, &self.backup_key) { - (Some(val), _) => (2, val), - (_, Some(val)) => (3, val), - _ => { - panic!("error generate key") - } - }; + let key_str_1: &str = &self.second_key; let key1 = BigInt::parse_bytes(&key_str_1.as_bytes(), 16).unwrap(); - let kp1 = (i, key1); + let kp1 = (2, key1); let _tmp = vec![kp0, kp1]; let sss = get_sss(&self.msg_key); let secret_b = sss.recover(&_tmp);