use crate::params::params::{R3_BYTES, SECRETKEYS_BYTES};
use crate::{
encode::r3,
poly::{r3::R3, rq::Rq},
};
use super::kem_error::KemErrors;
#[derive(Clone)]
pub struct PrivKey(pub R3, pub R3);
impl PrivKey {
pub fn compute(f: &Rq, g: &R3) -> Result<Self, KemErrors> {
let ginv = g.recip().map_err(KemErrors::PolyErrors)?;
Ok(PrivKey(f.r3_from_rq(), ginv))
}
pub fn to_bytes(&self) -> [u8; SECRETKEYS_BYTES] {
let mut sk = [0u8; SECRETKEYS_BYTES];
sk[..R3_BYTES].copy_from_slice(&self.1.to_bytes());
sk[R3_BYTES..].copy_from_slice(&self.0.to_bytes());
sk
}
pub fn import(sk: &[u8; SECRETKEYS_BYTES]) -> Result<Self, KemErrors> {
let ginv_bytes: [u8; R3_BYTES] = sk[..R3_BYTES]
.try_into()
.or(Err(KemErrors::InvalidR3GInvrBytes))?;
let f_bytes: [u8; R3_BYTES] = sk[R3_BYTES..]
.try_into()
.or(Err(KemErrors::InvalidR3FBytes))?;
let ginv = R3::from(r3::r3_decode(&ginv_bytes));
let f = R3::from(r3::r3_decode(&f_bytes));
Ok(PrivKey(f, ginv))
}
}
impl TryFrom<[u8; SECRETKEYS_BYTES]> for PrivKey {
type Error = KemErrors;
fn try_from(value: [u8; SECRETKEYS_BYTES]) -> Result<Self, Self::Error> {
Self::import(&value)
}
}
#[cfg(test)]
mod test_private_key {
use super::*;
use crate::rng::{random_small, short_random};
#[test]
fn test_import_export() {
let mut rng = rand::rng();
for _ in 0..2 {
let f: Rq = Rq::from(short_random(&mut rng).unwrap());
let g: R3 = R3::from(random_small(&mut rng));
let secret_key = match PrivKey::compute(&f, &g) {
Ok(sk) => sk,
Err(_) => continue,
};
let bytes = secret_key.to_bytes();
let new_secret_key = match PrivKey::import(&bytes) {
Ok(v) => v,
Err(_) => continue,
};
assert_eq!(new_secret_key.0.coeffs, secret_key.0.coeffs);
assert_eq!(new_secret_key.1.coeffs, secret_key.1.coeffs);
}
}
}