修改钱包
This commit is contained in:
parent
8cea569438
commit
4b872279df
@ -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()
|
||||
}
|
||||
|
143
src/lib.rs
143
src/lib.rs
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user