修改钱包

This commit is contained in:
cebgcontract 2022-10-22 23:27:47 +08:00
parent 8cea569438
commit 4b872279df
3 changed files with 232 additions and 139 deletions

View File

@ -5,42 +5,60 @@
//
use std::ffi::CStr;
use std::os::raw::c_char;
//use rustylib::gen::{CWallet};
use rustwallet::{fetch_cwallet, free_cwallet, sign, sss_sign, CWallet};
use rustwallet::{new_wallet, get_address, free_cwallet, CWallet};
fn main() {
unsafe {
// let wallet: CWallet = generate_cwallet();
// println!("---- generated a wallet to be used on C-side ----");
// print_wallet(&wallet);
let msg = "111";
let cstr = std::ffi::CString::new(msg).unwrap();
let wallet: CWallet = new_wallet(cstr.into_raw());
println!("---- generated a wallet to be used on C-side ----");
print_wallet(&wallet);
let address = get_address(wallet);
let address_str = cchar_str(address);
println!("address: {}", address_str);
let key0 = "b8256097c1ff2bdd483ffb53d35203a8a7ff19547d65d97f2810732a27e80c1f";
let key1 = "8e25c8b2e2c8504ea3d6d37cc268facec17ae60667048cfeb7a0092cfda8323a";
let key2 = "642630ce039174bfff6daba5b17ff1f4daf6b2b850a3407e472f9f2fd3685855";
// println!("---- saving the wallet to wallet.json ----");
// save_wallet(&wallet);
// println!("---- saved! ----");
println!("---- fetching the saved wallet to be exposed to C-side ----");
let fetched = fetch_cwallet();
print_wallet(&fetched);
sign();
let sign_str = "111";
let cstr = std::ffi::CString::new(sign_str).unwrap();
sss_sign(cstr.into_raw());
// println!("---- fetching the saved wallet to be exposed to C-side ----");
// let fetched = fetch_cwallet();
// print_wallet(&fetched);
// sign();
// let sign_str = "111";
// let cstr = std::ffi::CString::new(sign_str).unwrap();
// sss_sign(cstr.into_raw());
// free_cwallet(wallet); // 对应 generate_cwallet()
free_cwallet(fetched); // 对应 fetch_wallet()
// // free_cwallet(wallet); // 对应 generate_cwallet()
// free_cwallet(fetched); // 对应 fetch_wallet()
}
}
unsafe fn print_wallet(wallet: &CWallet) {
let a = CStr::from_ptr(wallet.public_addr);
let pa = a.to_str().unwrap();
println!("public address=> {}", pa);
unsafe fn print_wallet(cwallet: &CWallet) {
let msg = CStr::from_ptr(cwallet.msg_key);
let pmsg = msg.to_str().unwrap();
println!("msg=> {}", pmsg);
let pk = CStr::from_ptr(wallet.public_key);
let ppk = pk.to_str().unwrap();
println!("public key=> {}", ppk);
let m = CStr::from_ptr(cwallet.master_key);
let pm = m.to_str().unwrap();
println!("master key=> {}", pm);
let sk = CStr::from_ptr(wallet.private_key);
let psk = sk.to_str().unwrap();
println!("private key=> {}", psk);
let s = CStr::from_ptr(cwallet.second_key);
let ps = s.to_str().unwrap();
println!("second key=> {}", ps);
let b = CStr::from_ptr(cwallet.backup_key);
let pb = b.to_str().unwrap();
println!("backup key=> {}", pb);
}
unsafe fn cchar_str(cstr: *mut c_char) -> &'static str {
let msg = CStr::from_ptr(cstr);
msg.to_str().unwrap()
}

View File

@ -19,100 +19,77 @@ use crate::wallet::*;
#[repr(C)]
pub struct CWallet {
pub public_key: *mut c_char,
pub private_key: *mut c_char,
pub public_addr: *mut c_char,
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 generate_cwallet() -> CWallet {
pub unsafe extern "C" fn new_wallet(msg: *const c_char) -> CWallet {
println!("generating wallet");
let (secret_key, pub_key) = wallet_impl::generate_keypair();
let c_str = CStr::from_ptr(msg);
let str = c_str.to_str().unwrap();
let rust_wallet = wallet_impl::Wallet::new(str);
println!("rust_wallet: {:?}", &rust_wallet);
convert_to_cwallet(rust_wallet)
}
// println!("secret key: {}", &secret_key.to_string());
// println!("public key: {}", &pub_key.to_string());
//let pub_address = eth_wallet::public_key_address(&pub_key);
//println!("public address: {:?}", pub_address);
let rust_wallet = wallet_impl::Wallet::new(&secret_key, &pub_key);
#[no_mangle]
pub unsafe extern "C" fn restore_cwallet(msg: *const c_char) -> CWallet {
println!("generating wallet");
let c_str = CStr::from_ptr(msg);
let str = c_str.to_str().unwrap();
let rust_wallet = wallet_impl::Wallet::new(str);
println!("rust_wallet: {:?}", &rust_wallet);
convert_to_cwallet(rust_wallet)
}
#[no_mangle]
pub unsafe extern "C" fn free_cwallet(cw: CWallet) {
drop(CString::from_raw(cw.public_key));
drop(CString::from_raw(cw.private_key));
drop(CString::from_raw(cw.public_addr));
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 save_wallet(cw: &CWallet) {
let rwallet = convert_to_rwallet(cw);
wallet_impl::Wallet::save_keys(&rwallet, "wallet.json").unwrap();
}
#[no_mangle]
pub unsafe extern "C" fn fetch_cwallet() -> CWallet {
match wallet_impl::Wallet::retrieve_keys("wallet.json") {
Err(_) => {
let wallet = wallet_impl::Wallet {
secret_key: "".to_string(),
public_key: "".to_string(),
public_address: "".to_string(),
};
return convert_to_cwallet(wallet);
}
Ok(w) => return convert_to_cwallet(w),
};
}
#[no_mangle]
pub unsafe extern "C" fn sign() {
match wallet_impl::Wallet::retrieve_keys("wallet.json") {
Err(_) => {
println!("error sign");
}
Ok(w) => match w.sign("111") {
Err(err) => {
println!("error sign: {:?}", err);
}
Ok(sig) => {
println!("sig result: {:?}", sig);
}
},
};
}
#[no_mangle]
pub unsafe extern "C" fn sss_sign(msg: *const std::os::raw::c_char) {
let c_str = CStr::from_ptr(msg);
let str = c_str.to_str().unwrap();
match wallet_impl::Wallet::retrieve_keys("wallet.json") {
Err(_) => {
println!("error sign");
}
Ok(w) => {
w.sss_sign(&str);
}
};
pub unsafe extern "C" fn get_address(cw: CWallet) -> *mut c_char{
let rwallet = convert_to_rwallet(&cw);
let address = rwallet.get_address();
println!("raw address: {}", address.to_string());
let c_address = CString::new(address.to_string()).unwrap();
c_address.into_raw()
}
unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet {
// 转换Rust字符串数据为C的字符串并移交ownership
let pubkey = CString::new(rwallet.public_key).unwrap();
let c_pubkey: *mut c_char = pubkey.into_raw();
let seckey = CString::new(rwallet.secret_key).unwrap();
let c_seckey: *mut c_char = seckey.into_raw();
let pubaddr = CString::new(rwallet.public_address).unwrap();
let c_pubaddr: *mut c_char = pubaddr.into_raw();
let msgkey = CString::new(rwallet.msg_key).unwrap();
let c_msgkey: *mut c_char = msgkey.into_raw();
let masterkey = CString::new(rwallet.master_key).unwrap();
let c_masterkey: *mut c_char = masterkey.into_raw();
let secondkey = match rwallet.second_key {
Some(val) => {
CString::new(val).unwrap()
},
None => CString::new("").unwrap()
};
let c_secondkey: *mut c_char = secondkey.into_raw();
let backupkey = match rwallet.backup_key {
Some(val) => {
CString::new(val).unwrap()
},
None => CString::new("").unwrap()
};
let c_backupkey: *mut c_char = backupkey.into_raw();
//println!("crypto wallet address: {}", CStr::from_ptr(c_pubaddr).to_str().unwrap());
let cw = CWallet {
public_key: c_pubkey,
private_key: c_seckey,
public_addr: c_pubaddr,
msg_key: c_msgkey,
master_key: c_masterkey,
second_key: c_secondkey,
backup_key: c_backupkey,
};
//println!("crypto_wallet addr: {}", CStr::from_ptr(cw.public_addr).to_str().unwrap());
@ -121,17 +98,21 @@ unsafe fn convert_to_cwallet(rwallet: Wallet) -> CWallet {
}
unsafe fn convert_to_rwallet(cwallet: &CWallet) -> Wallet {
let a = CStr::from_ptr(cwallet.public_addr);
let pa = a.to_str().unwrap();
let msg = CStr::from_ptr(cwallet.msg_key);
let pmsg = msg.to_str().unwrap();
let pk = CStr::from_ptr(cwallet.public_key);
let ppk = pk.to_str().unwrap();
let m = CStr::from_ptr(cwallet.master_key);
let pm = m.to_str().unwrap();
let sk = CStr::from_ptr(cwallet.private_key);
let psk = sk.to_str().unwrap();
let s = CStr::from_ptr(cwallet.second_key);
let ps = s.to_str().unwrap();
let b = CStr::from_ptr(cwallet.backup_key);
let pb = b.to_str().unwrap();
Wallet {
secret_key: psk.to_string(),
public_key: ppk.to_string(),
public_address: pa.to_string(),
msg_key: pmsg.to_string(),
master_key: pm.to_string(),
second_key: Some(ps.to_string()),
backup_key: Some(pb.to_string())
}
}

View File

@ -7,10 +7,8 @@ use secp256k1::{Message, PublicKey, Secp256k1, SecretKey};
use serde::{Deserialize, Serialize};
use shamir_secret_sharing::num_bigint::BigInt;
use shamir_secret_sharing::ShamirSecretSharing as SSS;
use std::io::BufWriter;
use std::str;
use std::str::FromStr;
use std::{fs::OpenOptions, io::BufReader};
use tiny_keccak::keccak256;
use web3::types::{Address, H256};
@ -28,12 +26,38 @@ pub fn public_key_address(public_key: &PublicKey) -> Address {
Address::from_slice(&hash[12..])
}
pub fn get_public_key(secret_key: &str) -> PublicKey {
pub fn get_public_key(secret_key: &SecretKey) -> PublicKey {
let secp = Secp256k1::new();
let secret = SecretKey::from_str(secret_key).unwrap();
PublicKey::from_secret_key(&secp, &secret)
PublicKey::from_secret_key(&secp, secret_key)
}
pub fn get_sss(msg: &str) -> SSS {
let k_hash = keccak256(msg.as_bytes());
let s = hex::encode(&k_hash);
let pb = BigInt::parse_bytes(&s.as_bytes(), 16).unwrap();
SSS {
threshold: 2,
share_amount: 3,
prime: pb,
}
}
pub fn generate_sss_keypair(msg: &str, skey: &str) -> Vec<String> {
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<String> = Vec::new();
for (_i, v) in &shares {
shares_str.push(v.to_str_radix(16));
}
shares_str
}
pub fn hash_message<S>(message: S) -> H256
where
S: AsRef<[u8]>,
@ -48,45 +72,116 @@ where
#[derive(Serialize, Deserialize, Debug)]
pub struct Wallet {
pub secret_key: String,
pub public_key: String,
pub public_address: String,
pub msg_key: String,
pub master_key: String,
pub second_key: Option<String>,
pub backup_key: Option<String>,
}
impl Wallet {
pub fn new(secret_key: &SecretKey, public_key: &PublicKey) -> Self {
let addr: Address = public_key_address(&public_key);
println!("secret key: {:?}", secret_key);
pub fn new(msg: &str) -> Self{
let (secret_key, _pub_key) = generate_keypair();
let s = hex::encode(&secret_key.serialize_secret());
println!("{:?}", s);
let sk2 = "b8256097c1ff2bdd483ffb53d35203a8a7ff19547d65d97f2810732a27e80c1f";
let shares_str = generate_sss_keypair(msg, &sk2);
// let addr: Address = public_key_address(&pub_key);
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 {
secret_key: s,
public_key: public_key.to_string(),
public_address: format!("{:?}", addr),
msg_key: msg.to_string(),
master_key: shares_str.get(0).unwrap().to_string(),
second_key: second_key,
backup_key: backup_key
}
}
pub fn save_keys(&self, file_path: &str) -> Result<()> {
let file = OpenOptions::new()
.write(true)
.create(true)
.open(file_path)?;
let buf_writer = BufWriter::new(file);
serde_json::to_writer_pretty(buf_writer, self)?;
Ok(())
pub fn restore_wallet(msg: &str, _key_master: &str, _key_second: Option<&str>, _key_backup: Option<&str>) -> Self {
let key_second: Option<String> = match _key_second {
None => None,
Some(val) => Some(val.to_string())
};
let key_backup: Option<String> = match _key_backup {
None => None,
Some(val) => Some(val.to_string())
};
Wallet {
msg_key: msg.to_string(),
master_key: _key_master.to_string(),
second_key: key_second,
backup_key: key_backup
}
}
pub fn retrieve_keys(file_path: &str) -> Result<Wallet> {
let file = OpenOptions::new().read(true).open(file_path)?;
let buf_reader = BufReader::new(file);
let wallet: Wallet = serde_json::from_reader(buf_reader)?;;
let public_key = get_public_key(&wallet.secret_key);
println!("public key from secret: {:?}", public_key.to_string());
Ok(wallet)
pub fn reset_eallet(msg: &str, _key_master: &str, _key_second: Option<&str>, _key_backup: Option<&str>) -> Self{
let tmp_wallet = Wallet::restore_wallet(msg, _key_master, _key_second, _key_backup);
let secret_key = tmp_wallet.get_secret_key();
let s = hex::encode(&secret_key.serialize_secret());
let shares_str = generate_sss_keypair(msg, &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
}
}
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: usize;
let key_str_1: &str;
if let Some(val) = &self.second_key {
i = 2;
key_str_1 = val;
} else if let Some(val) = &self.backup_key {
i = 3;
key_str_1 = val;
} else {
println!("error");
i = 2;
key_str_1 = "";
}
let key1 = BigInt::parse_bytes(
&key_str_1.as_bytes(),
16,
)
.unwrap();
let kp1 = (i, key1);
let _tmp = vec![kp0, kp1];
let sss = get_sss(&self.msg_key);
let secret_b = sss.recover(&_tmp);
let s_key_str = secret_b.to_str_radix(16);
SecretKey::from_str(&s_key_str).expect("32 bytes, within curve order")
}
pub fn get_public_key(&self) -> PublicKey {
let s_key = self.get_secret_key();
get_public_key(&s_key)
}
pub fn get_address(&self) -> Address {
let public_key = self.get_public_key();
public_key_address(&public_key)
}
// pub fn retrieve_keys(file_path: &str) -> Result<Wallet> {
// let file = OpenOptions::new().read(true).open(file_path)?;
// let buf_reader = BufReader::new(file);
// let wallet: Wallet = serde_json::from_reader(buf_reader)?;;
// let public_key = get_public_key(&wallet.secret_key);
// println!("public key from secret: {:?}", public_key.to_string());
// Ok(wallet)
// }
pub fn sss_sign(&self, msg: &str) {
let k_hash = keccak256(msg.as_bytes());
println!("k_hash: {:?}", &k_hash);
@ -138,15 +233,14 @@ impl Wallet {
S: AsRef<[u8]>,
{
let secp = Secp256k1::new();
println!("secret key str: {:?}", self.secret_key);
let secret_key = self.get_secret_key();
let message = msg.as_ref();
let message_hash = hash_message(message.as_ref());
let pk = SecretKey::from_str(&self.secret_key).expect("32 bytes, within curve order");
// println!("secret key: {:?}", pk);
println!("secret key: {:?}", &secret_key);
let message_to_hash = Message::from_slice(message_hash.as_ref()).unwrap();
let (recovery_id, signature) = secp
.sign_ecdsa_recoverable(&message_to_hash, &pk)
.sign_ecdsa_recoverable(&message_to_hash, &secret_key)
.serialize_compact();
let mut s = hex::encode(signature);