use core::fmt::{Debug, Display};
use crate::*;
use generic_array::{ArrayLength, GenericArray, typenum};
use rand::rng;
use sm3::{Digest, Sm3};
use sm9_core::{G1, G2, Group, fast_pairing};
use zeroize::{Zeroize, ZeroizeOnDrop};
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Error;
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "error key exchanging!")
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq, ZeroizeOnDrop)]
pub struct Secret<N: ArrayLength>(GenericArray<u8, N>);
impl<N: ArrayLength> Zeroize for Secret<N> {
fn zeroize(&mut self) {
self.0.as_mut_slice().zeroize();
}
}
impl<N: ArrayLength> Secret<N> {
pub fn new(bytes: GenericArray<u8, N>) -> Self {
Secret(bytes)
}
pub fn from_slice(slice: &[u8]) -> Self {
Secret(GenericArray::<u8, N>::from_slice(slice).clone())
}
pub const fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
}
pub type SharedSecret = Secret<typenum::U16>;
pub type EphemeralSecret = Secret<typenum::U64>;
pub type ComfirmableSecret = Secret<typenum::U32>;
#[derive(Clone, Debug)]
pub struct KeyExchanger {
public_key: MasterPublicKey,
user_key: UserPrivateKey,
user_id: Vec<u8>,
is_initiator: bool,
r: Fn,
peer_id: Vec<u8>,
ra: EphemeralSecret,
rb: EphemeralSecret,
s1: ComfirmableSecret,
s2: ComfirmableSecret,
}
impl KeyExchanger {
pub fn new(
user_id: &[u8],
user_key: &UserPrivateKey,
public_key: &MasterPublicKey,
is_initiator: bool,
) -> Result<Self, Error> {
if public_key.is_ok() && !user_id.is_empty() && user_key.is_ok() {
let mut id = Vec::<u8>::new();
id.extend_from_slice(user_id);
Ok(Self {
public_key: public_key.clone(),
user_id: id,
user_key: user_key.clone(),
is_initiator,
r: Fn::zero(),
peer_id: Vec::<u8>::new(),
ra: EphemeralSecret::default(),
rb: EphemeralSecret::default(),
s1: ComfirmableSecret::default(),
s2: ComfirmableSecret::default(),
})
} else {
Err(Error)
}
}
pub fn generate_ephemeral_secret(&mut self, peer_id: &[u8]) -> Result<EphemeralSecret, Error> {
self.peer_id.clear();
self.peer_id.extend_from_slice(peer_id);
let mut z = Vec::<u8>::new();
z.extend_from_slice(peer_id);
z.push(SM9_HID_ENC);
let h1 = Sm9::hash_1(z.as_slice()).unwrap();
let g1 = G1::one() * h1;
let pube = self.public_key.to_g1().ok_or(Error).unwrap();
let q = g1 + pube;
let rng = &mut rng();
let r = Fn::random(rng);
self.r = r;
let ra = (r * q).to_slice();
self.ra = EphemeralSecret::from_slice(ra.as_ref());
Ok(self.ra.clone())
}
pub fn generate_shared_secret(&mut self, es: &EphemeralSecret) -> Result<SharedSecret, Error> {
if self.peer_id.is_empty() {
Err(Error)
} else {
let sk;
if self.is_initiator {
self.rb = EphemeralSecret::new(es.0);
let rb = G1::from_slice(self.rb.as_slice()).unwrap();
let g1 = fast_pairing(self.public_key.to_g1().unwrap(), G2::one()).pow(self.r);
let g2 = fast_pairing(rb, self.user_key.to_g2().unwrap());
let g3 = g2.pow(self.r);
let mut z = Vec::<u8>::new();
z.extend(&self.user_id);
z.extend(&self.peer_id);
z.extend_from_slice(self.ra.as_slice());
z.extend_from_slice(self.rb.as_slice());
z.extend_from_slice(&[g1.to_slice(), g2.to_slice(), g3.to_slice()].concat());
sk = Sm9::kdf(z.as_ref(), 16).expect("klen maybe error");
let mut u = Vec::<u8>::new();
u.extend_from_slice(g2.to_slice().as_ref());
u.extend_from_slice(g3.to_slice().as_ref());
u.extend(&self.user_id);
u.extend(&self.peer_id);
u.extend_from_slice(self.ra.as_slice());
u.extend_from_slice(self.rb.as_slice());
let mut sm3 = Sm3::new();
sm3.update(u);
let ha2 = sm3.finalize();
let mut v = Vec::<u8>::new();
v.extend_from_slice(g1.to_slice().as_ref());
v.extend_from_slice(ha2.as_slice());
let mut sm3 = Sm3::new();
sm3.update([0x82u8]);
sm3.update(v.clone());
let ha = sm3.finalize();
self.s1 = ComfirmableSecret::from_slice(ha.as_slice());
let mut sm3 = Sm3::new();
sm3.update([0x83u8]);
sm3.update(v);
let ha = sm3.finalize();
self.s2 = ComfirmableSecret::from_slice(ha.as_slice());
} else {
self.rb = EphemeralSecret::new(es.0);
let rb = G1::from_slice(self.rb.as_slice()).unwrap();
let g1 = fast_pairing(rb, self.user_key.to_g2().unwrap());
let g2 = fast_pairing(self.public_key.to_g1().unwrap(), G2::one()).pow(self.r);
let g3 = g1.pow(self.r);
let mut z = Vec::<u8>::new();
z.extend(&self.peer_id);
z.extend(&self.user_id);
z.extend_from_slice(self.rb.as_slice());
z.extend_from_slice(self.ra.as_slice());
z.extend_from_slice(&[g1.to_slice(), g2.to_slice(), g3.to_slice()].concat());
sk = Sm9::kdf(z.as_ref(), 16).expect("klen maybe error");
let mut u = Vec::<u8>::new();
u.extend_from_slice(g2.to_slice().as_ref());
u.extend_from_slice(g3.to_slice().as_ref());
u.extend(&self.peer_id);
u.extend(&self.user_id);
u.extend_from_slice(self.rb.as_slice());
u.extend_from_slice(self.ra.as_slice());
let mut sm3 = Sm3::new();
sm3.update(u);
let ha2 = sm3.finalize();
let mut v = Vec::<u8>::new();
v.extend_from_slice(g1.to_slice().as_ref());
v.extend_from_slice(ha2.as_slice());
let mut sm3 = Sm3::new();
sm3.update([0x82u8]);
sm3.update(v.clone());
let ha = sm3.finalize();
self.s1 = ComfirmableSecret::from_slice(ha.as_slice());
let mut sm3 = Sm3::new();
sm3.update([0x83u8]);
sm3.update(v);
let ha = sm3.finalize();
self.s2 = ComfirmableSecret::from_slice(ha.as_slice());
}
Ok(SharedSecret::from_slice(sk.as_ref()))
}
}
pub fn generate_comfirmable_secret(&self) -> Result<ComfirmableSecret, Error> {
if self.s1 == ComfirmableSecret::default() {
Err(Error)
} else if self.is_initiator {
Ok(self.s2.clone())
} else {
Ok(self.s1.clone())
}
}
pub fn comfirm(&self, cs: &ComfirmableSecret) -> Result<bool, Error> {
if self.s1 == ComfirmableSecret::default() {
Err(Error)
} else if self.is_initiator {
Ok(self.s1 == *cs)
} else {
Ok(self.s2 == *cs)
}
}
}