use poulpy_hal::{ api::{ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxDftBytesOf, VecZnxNormalizeTmpBytes}, layouts::{Backend, DataMut, DataRef, Module, ScratchOwned}, source::Source, }; use crate::{ encryption::glwe_ct::GLWEEncryptZeroSk, layouts::{ GLWE, GLWEPublicKey, GLWEPublicKeyToMut, prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }, }; pub trait GLWEPublicKeyGenerate { fn glwe_public_key_generate(&self, res: &mut R, sk: &S, source_xa: &mut Source, source_xe: &mut Source) where R: GLWEPublicKeyToMut, S: GLWESecretPreparedToRef; } impl GLWEPublicKeyGenerate for Module where Module: GLWEEncryptZeroSk + VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, ScratchOwned: ScratchOwnedAlloc + ScratchOwnedBorrow, { fn glwe_public_key_generate(&self, res: &mut R, sk: &S, source_xa: &mut Source, source_xe: &mut Source) where R: GLWEPublicKeyToMut, S: GLWESecretPreparedToRef, { let res: &mut GLWEPublicKey<&mut [u8]> = &mut res.to_mut(); let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref(); #[cfg(debug_assertions)] { use crate::{Distribution, layouts::LWEInfos}; assert_eq!(res.n(), self.n() as u32); assert_eq!(sk.n(), self.n() as u32); if sk.dist == Distribution::NONE { panic!("invalid sk: SecretDistribution::NONE") } } // Its ok to allocate scratch space here since pk is usually generated only once. let mut scratch: ScratchOwned = ScratchOwned::alloc(GLWE::encrypt_sk_tmp_bytes(self, res)); let mut tmp: GLWE> = GLWE::alloc_from_infos(res); tmp.encrypt_zero_sk(self, sk, source_xa, source_xe, scratch.borrow()); res.dist = sk.dist; } } impl GLWEPublicKey { pub fn generate( &mut self, module: &Module, sk: &GLWESecretPrepared, source_xa: &mut Source, source_xe: &mut Source, ) where Module: GLWEPublicKeyGenerate, { module.glwe_public_key_generate(self, sk, source_xa, source_xe); } }