use crate::*;
use core::fmt::{Debug, Error};
use generic_array::{ArrayLength, GenericArray, typenum};
use rand_core::RngCore; use sm9_core::{G1, G2, Group, fast_pairing};
type NEnc = typenum::U64;
#[derive(Debug)]
pub struct Sm9EncappedKey(GenericArray<u8, NEnc>);
pub trait EncappedKey: AsRef<[u8]> + Debug + Sized {
type EncappedKeySize: ArrayLength;
type SharedSecretSize: ArrayLength;
type SenderPublicKey;
type RecipientPublicKey;
fn from_bytes(bytes: &GenericArray<u8, Self::EncappedKeySize>) -> Result<Self, Error>;
fn as_bytes(&self) -> &GenericArray<u8, Self::EncappedKeySize> {
GenericArray::from_slice(self.as_ref())
}
}
pub struct SharedSecret<EK: EncappedKey>(GenericArray<u8, EK::SharedSecretSize>);
impl<EK: EncappedKey> SharedSecret<EK> {
pub fn new(bytes: GenericArray<u8, EK::SharedSecretSize>) -> Self {
SharedSecret(bytes)
}
pub fn as_bytes(&self) -> &[u8] {
&self.0
}
}
impl EncappedKey for Sm9EncappedKey {
type SharedSecretSize = typenum::U384;
type EncappedKeySize = NEnc;
type SenderPublicKey = MasterPublicKey;
type RecipientPublicKey = GenericArray<u8, typenum::U128>;
fn from_bytes(bytes: &GenericArray<u8, Self::EncappedKeySize>) -> Result<Self, Error> {
Ok(Sm9EncappedKey(*bytes))
}
}
impl AsRef<[u8]> for Sm9EncappedKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
pub type Sm9SharedSecret = SharedSecret<Sm9EncappedKey>;
pub trait Encapsulator<EK: EncappedKey> {
fn try_encap<R: RngCore + ?Sized>(
&self,
csprng: &mut R,
recip_pubkey: &EK::RecipientPublicKey,
) -> Result<(EK, SharedSecret<EK>), Error>;
}
pub trait Decapsulator<EK: EncappedKey> {
fn try_decap(&self, encapped_key: &EK) -> Result<SharedSecret<EK>, Error>;
}
impl Encapsulator<Sm9EncappedKey> for <Sm9EncappedKey as EncappedKey>::SenderPublicKey {
fn try_encap<R: RngCore + ?Sized>(
&self,
csprng: &mut R,
recip_pubkey: &<Sm9EncappedKey as EncappedKey>::RecipientPublicKey,
) -> Result<(Sm9EncappedKey, Sm9SharedSecret), Error> {
let mut user_id = Vec::<u8>::new();
for b in recip_pubkey {
if *b != 0 {
user_id.push(*b);
} else {
break;
}
}
let mut z = Vec::<u8>::new();
z.extend_from_slice(user_id.as_ref());
z.push(SM9_HID_ENC);
let h1 = Sm9::hash_1(z.as_slice()).unwrap();
let g1 = G1::one() * h1;
let pube = self.to_g1().expect("MasterPublicKey error");
let q = g1 + pube;
let g = fast_pairing(pube, G2::one());
let r = Fn::random(csprng);
let c = r * q;
let w = g.pow(r);
let encapped_key =
Sm9EncappedKey::from_bytes(GenericArray::from_slice(c.to_slice().as_ref()))?;
let shared_secret = Sm9SharedSecret::new(*GenericArray::from_slice(w.to_slice().as_ref()));
Ok((encapped_key, shared_secret))
}
}
impl Decapsulator<Sm9EncappedKey> for UserPrivateKey {
fn try_decap(&self, encapped_key: &Sm9EncappedKey) -> Result<Sm9SharedSecret, Error> {
let de = self.to_g2().expect("UserPrivateKey error");
let c = G1::from_slice(encapped_key.as_ref()).unwrap();
let w = fast_pairing(c, de);
let shared_secret = Sm9SharedSecret::new(*GenericArray::from_slice(w.to_slice().as_ref()));
Ok(shared_secret)
}
}