From f13a543cf36289eb723b2136760755499b529d20 Mon Sep 17 00:00:00 2001 From: CounterFire2023 <136581895+CounterFire2023@users.noreply.github.com> Date: Thu, 19 Oct 2023 18:57:55 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0rsa=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E5=AF=86=E7=9B=B8=E5=85=B3=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 153 ++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 + examples/test.rs | 41 +++++++--- rustwallet.h | 6 ++ src/lib.rs | 26 ++++++- src/utils/crypto_utils.rs | 61 +++++++++++++++ 6 files changed, 278 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 05d2819..4a51009 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -190,6 +190,12 @@ dependencies = [ "bitflags", ] +[[package]] +name = "const-oid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" + [[package]] name = "cpufeatures" version = "0.2.5" @@ -235,6 +241,17 @@ dependencies = [ "cipher", ] +[[package]] +name = "der" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + [[package]] name = "digest" version = "0.9.0" @@ -251,6 +268,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer 0.10.3", + "const-oid", "crypto-common", "subtle", ] @@ -432,12 +450,27 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] + [[package]] name = "libc" version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libsecp256k1" version = "0.7.1" @@ -513,6 +546,23 @@ dependencies = [ "rand 0.5.6", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -523,6 +573,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -530,6 +591,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -591,6 +653,36 @@ dependencies = [ "hmac 0.12.1", ] +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "polyval" version = "0.6.0" @@ -712,6 +804,28 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rsa" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +dependencies = [ + "byteorder", + "const-oid", + "digest 0.10.6", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-hex" version = "2.1.0" @@ -731,6 +845,7 @@ dependencies = [ "hex", "primitive-types", "rand 0.8.5", + "rsa", "scrypt", "secp256k1", "serde", @@ -852,6 +967,38 @@ dependencies = [ "rand 0.5.6", ] +[[package]] +name = "signature" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +dependencies = [ + "digest 0.10.6", + "rand_core 0.6.4", +] + +[[package]] +name = "smallvec" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +dependencies = [ + "base64ct", + "der", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1046,3 +1193,9 @@ checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ "tap", ] + +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/Cargo.toml b/Cargo.toml index 2283434..b914702 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,3 +29,7 @@ scrypt = { version = "0.11.0", default-features = false, features = ["simple"] } argon2 = { version = "0.5.0" } aes-gcm = "0.10.1" rand = "0.8.5" +rsa = "0.9.2" + +[profile.dev.package.num-bigint-dig] +opt-level = 3 \ No newline at end of file diff --git a/examples/test.rs b/examples/test.rs index 35b4a54..1ffd66b 100644 --- a/examples/test.rs +++ b/examples/test.rs @@ -7,7 +7,7 @@ use rustwallet::{ aes_decrypt, aes_encrypt, generate_sec_key, get_address, get_public_key, hash_pass_svr, hex_deflate, hex_inflate, keccak256_hash, local_pass_hasher, rdecrypt, rencrypt, sign, - sign_for_tran, wallet_decrypt, wallet_encrypt,simple_sign, + sign_for_tran, wallet_decrypt, wallet_encrypt,simple_sign,rsa_key_pair,rsa_decrypt, rsa_encrypt, }; use std::ffi::{CStr, CString}; use std::os::raw::c_char; @@ -25,13 +25,13 @@ macro_rules! print_cchar { }; } -// macro_rules! cchar_to_str { -// ($p1:expr) => {{ -// let s = CStr::from_ptr($p1); -// let ps = s.to_str().unwrap(); -// ps -// }}; -// } +macro_rules! cchar_to_str { + ($p1:expr) => {{ + let s = CStr::from_ptr($p1); + let ps = s.to_str().unwrap(); + ps + }}; +} macro_rules! str_to_cchar { ($p1:expr) => {{ @@ -143,9 +143,26 @@ fn main() { let sig = simple_sign(str_to_cchar!(msg), key_private); print_cchar!(sig); - let str_1111 = "67181d63581e5506f137cfc66af17ffc8c0138238eb7fb9c2b4f424402d6c9d1"; - let aes_key = "02aaaafbd375639879d6a694893dd14413662d90c59abaceb6cc4c791aa0834352"; - let str_aes_plain = aes_decrypt(str_to_cchar!(str_1111), str_to_cchar!(aes_key)); - print_cchar!(str_aes_plain); + // let str_1111 = "67181d63581e5506f137cfc66af17ffc8c0138238eb7fb9c2b4f424402d6c9d1"; + // let aes_key = "02aaaafbd375639879d6a694893dd14413662d90c59abaceb6cc4c791aa0834352"; + // let str_aes_plain = aes_decrypt(str_to_cchar!(str_1111), str_to_cchar!(aes_key)); + // print_cchar!(str_aes_plain); + + let rsa_keys_str = rsa_key_pair(); + let keys_str = cchar_to_str!(rsa_keys_str); + let mut strs = keys_str.split("|"); + let s_key_str = strs.next().expect("empty private key"); + println!("RSA private key=> {}", s_key_str); + let p_key_str = strs.next().expect("empty public key"); + println!("RSA public key=> {}", p_key_str); + let msg = "hello world"; + let p_key_str = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0NCk1JR2ZNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0R05BRENCaVFLQmdRRGFrUXlQYmorWlZTS21KYllveFI5ZGVPb1UNCndSQWk1SjhMcG5wcWtTQUsvcVd6VVhNd0llajFENkVJYWdoR2RNSWtUWDFqT2h1N2U0blRxWmNyTmNzR1J5RXENCnVyT0pKcVNVMExQZ0ttdTRkM2pJa0RwMmgva1Zjc0hEcHM0emM2d1lnNEIzK2FRcC8ySldjbDBFWjBPbUdqNmkNCnJUY3dHbGFzbnVsdlYrM1V0UUlEQVFBQg0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tDQo="; + let s_key_str = "LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tDQpNSUlDZUFJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0FtSXdnZ0plQWdFQUFvR0JBTnFSREk5dVA1bFZJcVlsDQp0aWpGSDExNDZoVEJFQ0xrbnd1bWVtcVJJQXIrcGJOUmN6QWg2UFVQb1FocUNFWjB3aVJOZldNNkc3dDdpZE9wDQpseXMxeXdaSElTcTZzNGttcEpUUXMrQXFhN2gzZU1pUU9uYUgrUlZ5d2NPbXpqTnpyQmlEZ0hmNXBDbi9ZbFp5DQpYUVJuUTZZYVBxS3ROekFhVnF5ZTZXOVg3ZFMxQWdNQkFBRUNnWUVBZ1Zrd0pyNG5VMVlvQUUzM0pOK3I5VVIyDQp1N3VhRWh4YzU2Y3BjV0hicGNZWVNDd2UwRkJ4TG42R1haVnF1aytsQ1pqMmFML2Q0N0Z6MnRqVnh0TzZCekFBDQpWVGNZWVJqRnFody9JMitPaEJTRjF3U3doYUhvQ2dEZUFua2dOMTFlVDJCN3R3d2NvRHhsQ1h1WWQ3MEx3MEpkDQozbXVwejhOalV6ZC8vdzYwVG9FQ1FRRHpSbUlSckZMdyt6VWtqKzFWdHFnSklQZU56eXZ5R0JmUW5ZMEN1VVdjDQpMQ2xta1UwaHdNM0g2ODJIbEk0RWJSTkhVejVJTTVORm9mSGlVUDRVTjljVkFrRUE1Zi9OOXRnUjNjY1ZVems4DQp1Mk5iN3d2b1FMekVBd2lJN2tQTFp1SlI0MTZjSHEwWmZEUHZ5LytuZXRVZEJuZTFreHJwRmxyRFBwSVdDU3hHDQp5dFZ2SVFKQkFNb0gxNFhKMEkra2IzdlBzMUFOZ3ZzaHo3U0xLbm5CSEhYNWdaT1RmWVcyL3lMWTVHOTFpTy9RDQptajFRVjZqQlZOTlZCRkk5MHI1dlFVdXI2M1dxOGdrQ1FRRGlDWHpKMDUvN2JlU3ZYZGtwOElReGNtcFc5UzFPDQpMZDBsRE11aDJWclJNZklNMCtId0JycnNxZHhYQTRyN0NEc1N6NmV6cUkrcHRyaWhXenBYclZzQkFrQU1NT01WDQo4UmFJaDkwckJMWWpLN2l1SmZOeXhvemFQQkNVZ0J0UTZhMEdzbGo2OERCdDVEek1iRkFCelZKdE9hL25qTFE1DQpXMGs1R2tlYjR5M2NFOGoyDQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tDQo="; + let str_encrypt = rsa_encrypt(str_to_cchar!(msg), str_to_cchar!(p_key_str)); + print_cchar!(str_encrypt); + let str_encrypt = cchar_to_str!(str_encrypt); + let str_encrypt = "Z0eBsOhFz+IzGFywFtIAnmQ5fvEeQeruHyTYvxYADjoazpd8qVx9W8LvTU782PSCUpE5oswHSlFljcjbcAvetiUfKOy3Q+c8cnxmsBDgzBNclKspI2MKW2TuGQcijxB1DB7ggkNyqSvvNPJTt/mBYA1y+Ix1jGSjz+Ile7QtKMw="; + let str_decrypt = rsa_decrypt(str_to_cchar!(str_encrypt), str_to_cchar!(s_key_str)); + print_cchar!(str_decrypt); } } diff --git a/rustwallet.h b/rustwallet.h index d481994..8fdd151 100644 --- a/rustwallet.h +++ b/rustwallet.h @@ -51,3 +51,9 @@ char *generate_client_key(const char *password, const char *openid, const char * char *simple_sign(const char *content, const char *key); char *ramdonKey(void); + +char *rsa_key_pair(void); + +char *rsa_encrypt(const char *content, const char *p_key); + +char *rsa_decrypt(const char *content, const char *s_key); diff --git a/src/lib.rs b/src/lib.rs index 74950db..e3d7f6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,9 @@ use wallet_impl::Wallet; use crate::wallet::*; mod utils; -use utils::crypto_utils::{zdecrypt, zencrypt}; +use utils::crypto_utils::{ + general_rsa_keystr, zdecrypt, zencrypt +}; use utils::str_utils::{base64_to_hex, hex_to_base64}; // #[cfg(target_os = "android")] @@ -273,6 +275,28 @@ pub unsafe extern "C" fn ramdonKey() -> *mut c_char { cs_key.into_raw() } +#[no_mangle] +pub unsafe extern "C" fn rsa_key_pair() -> *mut c_char { + let key_str = general_rsa_keystr(); + return str_to_cchar!(key_str); +} + +#[no_mangle] +pub unsafe extern "C" fn rsa_encrypt(content: *const c_char, p_key: *const c_char) -> *mut c_char { + let content_str = cchar_to_str!(content); + let p_key_str = cchar_to_str!(p_key); + let msg_encrypt = utils::crypto_utils::rsa_encrypt(content_str, p_key_str); + str_to_cchar!(msg_encrypt) +} + +#[no_mangle] +pub unsafe extern "C" fn rsa_decrypt(content: *const c_char, s_key: *const c_char) -> *mut c_char { + let content_str = cchar_to_str!(content); + let s_key_str = cchar_to_str!(s_key); + let msg_decrypt = utils::crypto_utils::rsa_decrypt(content_str, s_key_str); + str_to_cchar!(msg_decrypt) +} + unsafe fn generate_rwallet( msg_key: *const c_char, master_key: *const c_char, diff --git a/src/utils/crypto_utils.rs b/src/utils/crypto_utils.rs index a06a0ae..7d2330f 100644 --- a/src/utils/crypto_utils.rs +++ b/src/utils/crypto_utils.rs @@ -7,6 +7,7 @@ use argon2::{ password_hash::{rand_core::OsRng, PasswordHash, PasswordHasher, PasswordVerifier, SaltString}, Argon2, }; +use rsa::{Pkcs1v15Encrypt, RsaPrivateKey, RsaPublicKey, pkcs8::{EncodePrivateKey, DecodePrivateKey}, pkcs8::{EncodePublicKey, DecodePublicKey}}; use base64::{engine::general_purpose, Engine as _}; use ecies::{decrypt, encrypt}; use rand::prelude::*; @@ -165,3 +166,63 @@ pub fn zdecrypt(sk: SecretKey, msg1: &str) -> Result { Ok(result) } + +pub fn generate_rsa_keypair() -> (RsaPrivateKey, RsaPublicKey) { + let mut rng = rand::thread_rng(); + let bits = 1024; + let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); + let pub_key = RsaPublicKey::from(&priv_key); + (priv_key, pub_key) +} + +pub fn general_rsa_keystr() -> String { + let (s_key, p_key) = generate_rsa_keypair(); + let mut s_key_str = encode_rsa_privatekey(s_key); + let p_key = encode_rsa_publickey(p_key); + s_key_str.push_str("|"); + s_key_str.push_str(&p_key); + s_key_str +} + +pub fn rsa_encrypt(content: &str, p_key: &str) -> String { + let p_key = decode_rsa_publickey(p_key); + let mut rng = rand::thread_rng(); + let msg_encrypt = p_key.encrypt(&mut rng, Pkcs1v15Encrypt, content.as_bytes()).expect("encrypt error"); + let msg_encrypt = general_purpose::STANDARD.encode(msg_encrypt); + msg_encrypt +} + +pub fn rsa_decrypt(content: &str, s_key: &str) -> String { + let content = general_purpose::STANDARD.decode(content).expect("error decode msg"); + let s_key = decode_rsa_privatekey(s_key); + let msg_decrypt = s_key.decrypt(Pkcs1v15Encrypt, &content).expect("decrypt error"); + let msg_decrypt = str::from_utf8(&msg_decrypt).expect("error convert to utf8"); + msg_decrypt.to_string() +} + +fn encode_rsa_privatekey(s_key: RsaPrivateKey) -> String { + let s_key = s_key.to_pkcs8_pem(rsa::pkcs8::LineEnding::CRLF).expect("error encode private key"); + let key_str = s_key.to_string(); + let key_str = general_purpose::STANDARD.encode(key_str.as_bytes()); + key_str +} + +fn encode_rsa_publickey(p_key: RsaPublicKey) -> String { + let p_key = p_key.to_public_key_pem(rsa::pkcs8::LineEnding::CRLF).expect("error encode public key"); + let key_str = general_purpose::STANDARD.encode(p_key.as_bytes()); + return key_str; +} + +fn decode_rsa_privatekey(key: &str) -> RsaPrivateKey{ + let key = general_purpose::STANDARD.decode(key).expect("err decode private key"); + let key = str::from_utf8(&key).expect("err convert to utf8"); + let key = RsaPrivateKey::from_pkcs8_pem(key).expect("error restore private key"); + key +} + +fn decode_rsa_publickey(key: &str) -> RsaPublicKey { + let key = general_purpose::STANDARD.decode(key).expect("err decode msg"); + let key = str::from_utf8(&key).expect("err convert to utf8"); + let key = RsaPublicKey::from_public_key_pem(key).expect("error restore public key"); + key +}