#![allow(
clippy::unreadable_literal,
clippy::upper_case_acronyms,
dead_code,
non_camel_case_types,
non_snake_case,
non_upper_case_globals,
overflowing_literals,
unused_variables,
unused_assignments
)]
use lazy_static::lazy_static;
#[allow(unused_imports)]
use pem::Pem;
use rustc_hex::ToHex;
use wedpr_l_crypto_signature_sm2::WedprSm2p256v1;
use wedpr_l_libsm::sm2::signature::SigCtx;
use wedpr_l_utils::traits::Signature;
use wedpr_l_crypto_signature_secp256k1::WedprSecp256k1Recover;
use crate::bcossdk::bcosclientconfig::BcosCryptoKind;
use crate::bcossdk::commonhash::{CommonHash, HashType};
use crate::bcossdk::fileutils;
use crate::bcossdk::kisserror::{KissErrKind, KissError};
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct BcosAccount {
pub privkey: Vec<u8>,
pub pubkey: Vec<u8>,
pub address: Vec<u8>,
}
impl BcosAccount {
pub fn to_hexdetail(&self) -> String {
let str = format!(
"address: {}\nprivkey: {}\npubkey: {}",
self.address.to_hex(),
self.privkey.to_hex(),
self.pubkey.to_hex()
);
str
}
}
pub fn save_key_to_pem(key: &Vec<u8>, pemfile: &str) -> Result<(), KissError> {
let content = Pem {
tag: String::from("PRIVATE KEY"),
contents: key.clone(),
};
fileutils::write_all(pemfile, pem::encode(&content).into())
}
pub fn load_key_from_pem(pemfile: &str) -> Result<Vec<u8>, KissError> {
let key = fileutils::read_all(pemfile)?;
let pemres = pem::parse(key);
match pemres {
Ok(pem) => Ok(pem.contents),
Err(e) => {
kisserr!(KissErrKind::EFormat, "load pem {:?} error {:?}", pemfile, e)
}
}
}
fn address_from_pubkey(pubkey: &Vec<u8>, hashtype: &HashType) -> Vec<u8> {
let mut actpubkey = pubkey.clone();
if pubkey.len() == 65{
actpubkey = actpubkey[1..].to_vec(); }
let hash = CommonHash::hash(&actpubkey, hashtype);
let addressbytes = hash[12..].to_vec();
addressbytes
}
pub trait IBcosAccountUtil {
fn create_random(&self) -> BcosAccount;
fn from_privkey_bytes(&self, privkey: &Vec<u8>) -> Result<BcosAccount, KissError>;
fn from_pem(&self, pemfile: &str) -> Result<BcosAccount, KissError>;
}
#[derive(Default, Debug)]
pub struct EcdsaAccountUtil {}
lazy_static! {
static ref WEDPRSM2:WedprSecp256k1Recover = WedprSecp256k1Recover::default();
}
impl IBcosAccountUtil for EcdsaAccountUtil {
fn create_random(&self) -> BcosAccount {
let (pubkey,secret_key) = WEDPRSM2.generate_keypair();
let address = address_from_pubkey(&pubkey,&HashType::KECCAK);
BcosAccount {
privkey: secret_key,
pubkey: pubkey,
address: address,
}
}
fn from_privkey_bytes(&self, privkey: &Vec<u8>) -> Result<BcosAccount, KissError> {
let keyresult = WEDPRSM2.derive_public_key(privkey);
match keyresult {
Ok(pubkey) => {
let account = BcosAccount {
privkey: privkey.clone(),
pubkey: pubkey.clone(),
address: address_from_pubkey(&pubkey,&HashType::KECCAK),
};
Ok(account)
}
Err(e) => {
kisserr!(KissErrKind::Error, "from privakey to pub key error {:?}", e)
}
}
}
fn from_pem(&self, pemfile: &str) -> Result<BcosAccount, KissError> {
let key = load_key_from_pem(pemfile)?;
self.from_privkey_bytes(&key)
}
}
lazy_static! {
static ref SM2_CTX: SigCtx = SigCtx::new();
static ref WEDPR_SM2 : WedprSm2p256v1= WedprSm2p256v1::default();
}
#[derive(Default, Debug)]
pub struct GMAccountUtil {}
impl IBcosAccountUtil for GMAccountUtil {
fn create_random(&self) -> BcosAccount {
let (pubkey, privkey) = WEDPR_SM2.generate_keypair();
BcosAccount {
privkey: privkey,
pubkey: pubkey.clone(),
address: address_from_pubkey(&pubkey, &HashType::WEDRP_SM3),
}
}
fn from_privkey_bytes(&self, privkey: &Vec<u8>) -> Result<BcosAccount, KissError> {
let secret_key = match SM2_CTX.load_seckey(&privkey.as_ref()) {
Ok(v) => v,
Err(_) => {
return kisserr!(KissErrKind::EFormat, "SM2_CTX.load_seckey");
}
};
let derived_public_key = SM2_CTX.pk_from_sk(&secret_key);
let mut pubkey = SM2_CTX.serialize_pubkey(&derived_public_key, false);
printlnex!("pubkey is {:?}", pubkey);
if pubkey.len() == 65 {
pubkey = pubkey[1..].to_vec();
}
let address = address_from_pubkey(&pubkey, &HashType::WEDRP_SM3);
let account = BcosAccount {
privkey: privkey.clone(),
pubkey: pubkey,
address: address,
};
Ok(account)
}
fn from_pem(&self, pemfile: &str) -> Result<BcosAccount, KissError> {
let key = load_key_from_pem(pemfile)?;
self.from_privkey_bytes(&key)
}
}
pub fn create_account(cryptokind: &BcosCryptoKind) -> BcosAccount {
match cryptokind {
BcosCryptoKind::ECDSA => EcdsaAccountUtil::default().create_random(),
BcosCryptoKind::GM => GMAccountUtil::default().create_random(),
}
}
pub fn account_from_pem(
pemfile: &str,
cryptokind: &BcosCryptoKind,
) -> Result<BcosAccount, KissError> {
match cryptokind {
BcosCryptoKind::ECDSA => {
let accountutil = EcdsaAccountUtil::default();
accountutil.from_pem(pemfile)
}
BcosCryptoKind::GM => {
let accountutil = GMAccountUtil::default();
accountutil.from_pem(pemfile)
}
}
}
pub fn account_from_privkey(
keybytes: &Vec<u8>,
cryptokind: BcosCryptoKind,
) -> Result<BcosAccount, KissError> {
match cryptokind {
BcosCryptoKind::ECDSA => {
let accountutil = EcdsaAccountUtil::default();
accountutil.from_privkey_bytes(keybytes)
}
BcosCryptoKind::GM => {
let accountutil = GMAccountUtil::default();
accountutil.from_privkey_bytes(keybytes)
}
}
}
pub fn test_account() {
let fixkey = "82dcd33c98a23d5d06f9331554e14ab4044a1d71b169b7a38b61c214f0690f80";
let accountresult =
EcdsaAccountUtil::default().from_privkey_bytes(&hex::decode(String::from(fixkey)).unwrap());
let account = accountresult.unwrap();
println!("account : {:?}", account);
let pemfile = "sdk/test.pem";
let res = save_key_to_pem(&account.privkey, pemfile);
let loadres = load_key_from_pem(pemfile);
let accountload = EcdsaAccountUtil::default().from_privkey_bytes(&loadres.unwrap());
println!("load result {:?}", accountload);
println!("account in hex : {:?}", account.to_hexdetail());
}