From a282e88126eeb53c01159197a742930c73254a13 Mon Sep 17 00:00:00 2001 From: Rasoul Akhavan Mahdavi Date: Fri, 17 Oct 2025 19:56:10 -0400 Subject: [PATCH] remaining in encryption + noise --- poulpy-core/src/decryption/glwe_ct.rs | 8 +- poulpy-core/src/decryption/mod.rs | 3 + .../src/encryption/compressed/gglwe_tsk.rs | 105 ++++----- .../src/encryption/compressed/ggsw_ct.rs | 95 ++++---- .../src/encryption/compressed/glwe_ct.rs | 89 ++++---- poulpy-core/src/encryption/glwe_pk.rs | 12 +- poulpy-core/src/noise/gglwe_ct.rs | 131 ++++++++--- poulpy-core/src/noise/ggsw_ct.rs | 212 ++++++++++-------- poulpy-core/src/noise/glwe_ct.rs | 180 +++++++++++---- 9 files changed, 527 insertions(+), 308 deletions(-) diff --git a/poulpy-core/src/decryption/glwe_ct.rs b/poulpy-core/src/decryption/glwe_ct.rs index 99c7d0f..f40d765 100644 --- a/poulpy-core/src/decryption/glwe_ct.rs +++ b/poulpy-core/src/decryption/glwe_ct.rs @@ -7,7 +7,7 @@ use poulpy_hal::{ }; use crate::layouts::{ - GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToMut, GLWEToMut, LWEInfos, + GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToMut, GLWEToRef, LWEInfos, prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }; @@ -55,14 +55,14 @@ where (self.vec_znx_normalize_tmp_bytes() | self.bytes_of_vec_znx_dft(1, size)) + self.bytes_of_vec_znx_dft(1, size) } - fn glwe_decrypt(&self, res: &mut R, pt: &mut P, sk: &S, scratch: &mut Scratch) + fn glwe_decrypt(&self, res: &R, pt: &mut P, sk: &S, scratch: &mut Scratch) where - R: GLWEToMut, + R: GLWEToRef, P: GLWEPlaintextToMut, S: GLWESecretPreparedToRef, Scratch: ScratchTakeBasic, { - let res: &mut GLWE<&mut [u8]> = &mut res.to_mut(); + let res: &GLWE<&[u8]> = &res.to_ref(); let pt: &mut GLWEPlaintext<&mut [u8]> = &mut pt.to_ref(); let sk: &GLWESecretPrepared<&[u8], BE> = &sk.to_ref(); diff --git a/poulpy-core/src/decryption/mod.rs b/poulpy-core/src/decryption/mod.rs index 8165d78..03e5fd4 100644 --- a/poulpy-core/src/decryption/mod.rs +++ b/poulpy-core/src/decryption/mod.rs @@ -1,2 +1,5 @@ mod glwe_ct; mod lwe_ct; + +pub use glwe_ct::*; +pub use lwe_ct::*; diff --git a/poulpy-core/src/encryption/compressed/gglwe_tsk.rs b/poulpy-core/src/encryption/compressed/gglwe_tsk.rs index 5843030..5f88e42 100644 --- a/poulpy-core/src/encryption/compressed/gglwe_tsk.rs +++ b/poulpy-core/src/encryption/compressed/gglwe_tsk.rs @@ -11,6 +11,7 @@ use poulpy_hal::{ use crate::{ ScratchTakeCore, encryption::compressed::gglwe_ksk::GLWESwitchingKeyCompressedEncryptSk, + encryption::gglwe_tsk::TensorKeyEncryptSk, layouts::{ GGLWEInfos, GLWEInfos, GLWESecret, GLWESecretToRef, GetDist, LWEInfos, Rank, TensorKey, compressed::{TensorKeyCompressed, TensorKeyCompressedToMut}, @@ -18,58 +19,81 @@ use crate::{ }; impl TensorKeyCompressed> { - pub fn encrypt_sk_tmp_bytes(module: &Module, infos: &A) -> usize + pub fn encrypt_sk_tmp_bytes(module: &M, infos: &A) -> usize where A: GGLWEInfos, - Module: ModuleN - + SvpPPolBytesOf - + SvpPPolAlloc - + VecZnxNormalizeTmpBytes - + VecZnxDftBytesOf - + VecZnxNormalizeTmpBytes - + VecZnxBigBytesOf, + M: GGLWETensorKeyCompressedEncryptSk, { - TensorKey::encrypt_sk_tmp_bytes(module, infos) + module.gglwe_tensor_key_compressed_encrypt_sk_tmp_bytes(infos) } } -pub trait GGLWETensorKeyCompressedEncryptSk { +impl TensorKeyCompressed { + pub fn encrypt_sk( + &mut self, + module: &Module, + sk: &GLWESecret, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch, + ) where + GLWESecret: GetDist, + Module: GGLWETensorKeyCompressedEncryptSk, + { + module.gglwe_tensor_key_encrypt_sk(self, sk, seed_xa, source_xe, scratch); + } +} + +pub trait GGLWETensorKeyCompressedEncryptSk { + + fn gglwe_tensor_key_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where + A: GGLWEInfos; + fn gglwe_tensor_key_encrypt_sk( &self, res: &mut R, sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where R: TensorKeyCompressedToMut, S: GLWESecretToRef + GetDist; } -impl GGLWETensorKeyCompressedEncryptSk for Module +impl GGLWETensorKeyCompressedEncryptSk for Module where - Module: ModuleN - + GLWESwitchingKeyCompressedEncryptSk - + VecZnxDftApply - + SvpApplyDftToDft - + VecZnxIdftApplyTmpA - + VecZnxBigNormalize - + SvpPrepare - + SvpPPolAllocBytesImpl + Module: ModuleN + + GLWESwitchingKeyCompressedEncryptSk + + TensorKeyEncryptSk + + VecZnxDftApply + + SvpApplyDftToDft + + VecZnxIdftApplyTmpA + + VecZnxBigNormalize + + SvpPrepare + + SvpPPolAllocBytesImpl + SvpPPolBytesOf - + VecZnxDftAllocBytesImpl - + VecZnxBigAllocBytesImpl + + VecZnxDftAllocBytesImpl + + VecZnxBigAllocBytesImpl + VecZnxDftBytesOf + VecZnxBigBytesOf, - Scratch: ScratchTakeBasic + ScratchTakeCore, + Scratch: ScratchTakeBasic + ScratchTakeCore, { + fn gglwe_tensor_key_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where + A: GGLWEInfos + { + self.tensor_key_encrypt_sk_tmp_bytes(infos) + } + fn gglwe_tensor_key_encrypt_sk( &self, res: &mut R, sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where R: TensorKeyCompressedToMut, S: GLWESecretToRef + GetDist, @@ -130,35 +154,4 @@ where } } } -} - -impl TensorKeyCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk: &GLWESecret, - seed_xa: [u8; 32], - source_xe: &mut Source, - scratch: &mut Scratch, - ) where - GLWESecret: GetDist, - Module: GGLWETensorKeyCompressedEncryptSk, - { - module.gglwe_tensor_key_encrypt_sk(self, sk, seed_xa, source_xe, scratch); - } -} - -impl TensorKeyCompressed { - pub fn encrypt_sk( - &mut self, - module: &Module, - sk: &GLWESecret, - seed_xa: [u8; 32], - source_xe: &mut Source, - scratch: &mut Scratch, - ) where - Module: GGLWETensorKeyCompressedEncryptSk, - { - module.gglwe_tensor_key_encrypt_sk(self, sk, seed_xa, source_xe, scratch); - } -} +} \ No newline at end of file diff --git a/poulpy-core/src/encryption/compressed/ggsw_ct.rs b/poulpy-core/src/encryption/compressed/ggsw_ct.rs index 6595e15..ef122d8 100644 --- a/poulpy-core/src/encryption/compressed/ggsw_ct.rs +++ b/poulpy-core/src/encryption/compressed/ggsw_ct.rs @@ -1,49 +1,52 @@ use poulpy_hal::{ - api::{ModuleN, VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes}, + api::{ModuleN, VecZnxAddScalarInplace, VecZnxNormalizeInplace}, layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxZero}, source::Source, }; use crate::{ ScratchTakeCore, - encryption::{SIGMA, glwe_ct::GLWEEncryptSkInternal}, + encryption::{SIGMA, ggsw_ct::GGSWEncryptSk, glwe_ct::GLWEEncryptSkInternal}, layouts::{ - GGSW, GGSWInfos, GLWEInfos, LWEInfos, + GGSWInfos, GLWEInfos, LWEInfos, compressed::{GGSWCompressed, GGSWCompressedToMut}, prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, }, }; impl GGSWCompressed> { - pub fn encrypt_sk_tmp_bytes(module: &Module, infos: &A) -> usize + pub fn encrypt_sk_tmp_bytes(module: &M, infos: &A) -> usize where A: GGSWInfos, - Module: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, + M: GGSWCompressedEncryptSk, { - GGSW::encrypt_sk_tmp_bytes(module, infos) + module.ggsw_compressed_encrypt_sk_tmp_bytes(infos) } } -pub trait GGSWCompressedEncryptSk { - fn ggsw_compressed_encrypt_sk( - &self, - res: &mut R, - pt: &P, - sk: &S, +impl GGSWCompressed { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &ScalarZnx, + sk: &GLWESecretPrepared, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where - R: GGSWCompressedToMut, - P: ScalarZnxToRef, - S: GLWESecretPreparedToRef; + Module: GGSWCompressedEncryptSk, + { + module.ggsw_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); + } } -impl GGSWCompressedEncryptSk for Module -where - Module: ModuleN + GLWEEncryptSkInternal + VecZnxAddScalarInplace + VecZnxNormalizeInplace, - Scratch: ScratchTakeCore, -{ + +pub trait GGSWCompressedEncryptSk { + fn ggsw_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where + A: GGSWInfos; + fn ggsw_compressed_encrypt_sk( &self, res: &mut R, @@ -51,14 +54,39 @@ where sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where R: GGSWCompressedToMut, P: ScalarZnxToRef, - S: GLWESecretPreparedToRef, + S: GLWESecretPreparedToRef; +} + +impl GGSWCompressedEncryptSk for Module +where + Module: ModuleN + GLWEEncryptSkInternal + GGSWEncryptSk + VecZnxAddScalarInplace + VecZnxNormalizeInplace, + Scratch: ScratchTakeCore, +{ + fn ggsw_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where A: GGSWInfos, + { + self.ggsw_encrypt_sk_tmp_bytes(infos) + } + + fn ggsw_compressed_encrypt_sk( + &self, + res: &mut R, + pt: &P, + sk: &S, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch, + ) where + R: GGSWCompressedToMut, + P: ScalarZnxToRef, + S: GLWESecretPreparedToRef, { let res: &mut GGSWCompressed<&mut [u8]> = &mut res.to_mut(); - let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref(); + let sk: &GLWESecretPrepared<&[u8], BE> = &sk.to_ref(); let pt: &ScalarZnx<&[u8]> = &pt.to_ref(); #[cfg(debug_assertions)] @@ -111,21 +139,4 @@ where } } } -} - -impl GGSWCompressed { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &ScalarZnx, - sk: &GLWESecretPrepared, - seed_xa: [u8; 32], - source_xe: &mut Source, - scratch: &mut Scratch, - ) where - Module: GGSWCompressedEncryptSk, - { - module.ggsw_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); - } -} +} \ No newline at end of file diff --git a/poulpy-core/src/encryption/compressed/glwe_ct.rs b/poulpy-core/src/encryption/compressed/glwe_ct.rs index f04a07a..0e9fca5 100644 --- a/poulpy-core/src/encryption/compressed/glwe_ct.rs +++ b/poulpy-core/src/encryption/compressed/glwe_ct.rs @@ -5,7 +5,7 @@ use poulpy_hal::{ }; use crate::{ - encryption::{SIGMA, glwe_ct::GLWEEncryptSkInternal}, + encryption::{SIGMA, glwe_ct::{GLWEEncryptSk, GLWEEncryptSkInternal}}, layouts::{ GLWE, GLWEInfos, GLWEPlaintext, GLWEPlaintextToRef, LWEInfos, compressed::{GLWECompressed, GLWECompressedToMut}, @@ -14,34 +14,38 @@ use crate::{ }; impl GLWECompressed> { - pub fn encrypt_sk_tmp_bytes(module: &Module, infos: &A) -> usize + pub fn encrypt_sk_tmp_bytes(module: &M, infos: &A) -> usize where A: GLWEInfos, - Module: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf, + M: GLWECompressedEncryptSk, { - GLWE::encrypt_sk_tmp_bytes(module, infos) + module.glwe_compressed_encrypt_sk_tmp_bytes(infos) } } -pub trait GLWECompressedEncryptSk { - fn glwe_compressed_encrypt_sk( - &self, - res: &mut R, - pt: &P, - sk: &S, +impl GLWECompressed { + #[allow(clippy::too_many_arguments)] + pub fn encrypt_sk( + &mut self, + module: &Module, + pt: &GLWEPlaintext, + sk: &GLWESecretPrepared, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where - R: GLWECompressedToMut, - P: GLWEPlaintextToRef, - S: GLWESecretPreparedToRef; + Module: GLWECompressedEncryptSk, + { + module.glwe_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); + } } -impl GLWECompressedEncryptSk for Module -where - Module: GLWEEncryptSkInternal, -{ + +pub trait GLWECompressedEncryptSk { + fn glwe_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where + A: GLWEInfos; + fn glwe_compressed_encrypt_sk( &self, res: &mut R, @@ -49,11 +53,37 @@ where sk: &S, seed_xa: [u8; 32], source_xe: &mut Source, - scratch: &mut Scratch, + scratch: &mut Scratch, ) where R: GLWECompressedToMut, P: GLWEPlaintextToRef, - S: GLWESecretPreparedToRef, + S: GLWESecretPreparedToRef; +} + +impl GLWECompressedEncryptSk for Module +where + Module: GLWEEncryptSkInternal + GLWEEncryptSk, +{ + + fn glwe_compressed_encrypt_sk_tmp_bytes(&self, infos: &A) -> usize + where + A: GLWEInfos, + { + self.glwe_encrypt_sk_tmp_bytes(infos) + } + + fn glwe_compressed_encrypt_sk( + &self, + res: &mut R, + pt: &P, + sk: &S, + seed_xa: [u8; 32], + source_xe: &mut Source, + scratch: &mut Scratch, + ) where + R: GLWECompressedToMut, + P: GLWEPlaintextToRef, + S: GLWESecretPreparedToRef, { let res: &mut GLWECompressed<&mut [u8]> = &mut res.to_mut(); let mut source_xa: Source = Source::new(seed_xa); @@ -75,21 +105,4 @@ where res.seed = seed_xa; } -} - -impl GLWECompressed { - #[allow(clippy::too_many_arguments)] - pub fn encrypt_sk( - &mut self, - module: &Module, - pt: &GLWEPlaintext, - sk: &GLWESecretPrepared, - seed_xa: [u8; 32], - source_xe: &mut Source, - scratch: &mut Scratch, - ) where - Module: GLWECompressedEncryptSk, - { - module.glwe_compressed_encrypt_sk(self, pt, sk, seed_xa, source_xe, scratch); - } -} +} \ No newline at end of file diff --git a/poulpy-core/src/encryption/glwe_pk.rs b/poulpy-core/src/encryption/glwe_pk.rs index e4fad50..f35457f 100644 --- a/poulpy-core/src/encryption/glwe_pk.rs +++ b/poulpy-core/src/encryption/glwe_pk.rs @@ -14,24 +14,24 @@ use crate::{ }; impl GLWEPublicKey { - pub fn generate( + pub fn generate( &mut self, - module: &Module, - sk: &GLWESecretPrepared, + module: &Module, + sk: &GLWESecretPrepared, source_xa: &mut Source, source_xe: &mut Source, ) where - Module: GLWEPublicKeyGenerate, + Module: GLWEPublicKeyGenerate, { module.glwe_public_key_generate(self, sk, source_xa, source_xe); } } -pub trait GLWEPublicKeyGenerate { +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; + S: GLWESecretPreparedToRef; } impl GLWEPublicKeyGenerate for Module diff --git a/poulpy-core/src/noise/gglwe_ct.rs b/poulpy-core/src/noise/gglwe_ct.rs index 516a210..e1cefbf 100644 --- a/poulpy-core/src/noise/gglwe_ct.rs +++ b/poulpy-core/src/noise/gglwe_ct.rs @@ -1,49 +1,120 @@ use poulpy_hal::{ api::{ - ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, - VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeTmpBytes, - VecZnxSubScalarInplace, + ScratchOwnedAlloc, ScratchOwnedBorrow, ScratchTakeBasic, VecZnxSubScalarInplace, }, - layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, ZnxZero}, - oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, + layouts::{Backend, DataRef, Module, Scratch, ScratchOwned, ScalarZnx, ScalarZnxToRef, ZnxZero}, + oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, VecZnxSubScalarInplaceImpl}, }; -use crate::layouts::{GGLWE, GGLWEInfos, GLWE, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::layouts::{ + GGLWE, GGLWEToRef, GGLWEInfos, GLWEPlaintext, LWEInfos, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, +}; +use crate::decryption::GLWEDecryption; impl GGLWE { - pub fn assert_noise( + + pub fn assert_noise( &self, - module: &Module, - sk: &GLWESecretPrepared, + module: &M, + sk_prepared: &GLWESecretPrepared, pt_want: &ScalarZnx, max_noise: f64, ) where DataSk: DataRef, DataWant: DataRef, - Module: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply - + SvpApplyDftToDftInplace - + VecZnxIdftApplyConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes - + VecZnxSubScalarInplace, - B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + M: GGLWENoise, + BE: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow + VecZnxSubScalarInplaceImpl, { - let dsize: usize = self.dsize().into(); - let base2k: usize = self.base2k().into(); + module.gglwe_assert_noise(self, sk_prepared, pt_want, max_noise); + } - let mut scratch: ScratchOwned = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); - let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - (0..self.rank_in().into()).for_each(|col_i| { - (0..self.dnum().into()).for_each(|row_i| { - self.at(row_i, col_i) - .decrypt(module, &mut pt, sk, scratch.borrow()); + // pub fn assert_noise( + // &self, + // module: &Module, + // sk: &GLWESecretPrepared, + // pt_want: &ScalarZnx, + // max_noise: f64, + // ) where + // DataSk: DataRef, + // DataWant: DataRef, + // Module: VecZnxDftBytesOf + // + VecZnxBigBytesOf + // + VecZnxDftApply + // + SvpApplyDftToDftInplace + // + VecZnxIdftApplyConsume + // + VecZnxBigAddInplace + // + VecZnxBigAddSmallInplace + // + VecZnxBigNormalize + // + VecZnxNormalizeTmpBytes + // + VecZnxSubScalarInplace, + // B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + // { + // let dsize: usize = self.dsize().into(); + // let base2k: usize = self.base2k().into(); - module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, col_i); + // let mut scratch: ScratchOwned = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); + // let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); + + // (0..self.rank_in().into()).for_each(|col_i| { + // (0..self.dnum().into()).for_each(|row_i| { + // self.at(row_i, col_i) + // .decrypt(module, &mut pt, sk, scratch.borrow()); + + // module.vec_znx_sub_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, col_i); + + // let noise_have: f64 = pt.data.std(base2k, 0).log2(); + + // println!("noise_have: {noise_have}"); + + // assert!( + // noise_have <= max_noise, + // "noise_have: {noise_have} > max_noise: {max_noise}" + // ); + + // pt.data.zero(); + // }); + // }); + // } +} + + +pub trait GGLWENoise { + fn gglwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) + where + R: GGLWEToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow + VecZnxSubScalarInplaceImpl; +} + +impl GGLWENoise for Module +where + Module: GLWEDecryption, + Scratch: ScratchTakeBasic + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, +{ + fn gglwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) + where + R: GGLWEToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow + VecZnxSubScalarInplaceImpl, + { + + let res: &GGLWE<&[u8]> = &res.to_ref(); + + let dsize: usize = res.dsize().into(); + let base2k: usize = res.base2k().into(); + + let mut scratch: ScratchOwned = ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res)); + let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res); + + (0..res.rank_in().into()).for_each(|col_i| { + (0..res.dnum().into()).for_each(|row_i| { + self.glwe_decrypt(&res.at(row_i, col_i), &mut pt, sk_prepared, scratch.borrow()); + + self.vec_znx_sub_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, col_i); let noise_have: f64 = pt.data.std(base2k, 0).log2(); @@ -58,4 +129,4 @@ impl GGLWE { }); }); } -} +} \ No newline at end of file diff --git a/poulpy-core/src/noise/ggsw_ct.rs b/poulpy-core/src/noise/ggsw_ct.rs index 92f806b..1a00f4d 100644 --- a/poulpy-core/src/noise/ggsw_ct.rs +++ b/poulpy-core/src/noise/ggsw_ct.rs @@ -4,62 +4,118 @@ use poulpy_hal::{ VecZnxBigAddSmallInplace, VecZnxBigAlloc, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxBigNormalizeTmpBytes, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxIdftApplyTmpA, VecZnxNormalizeTmpBytes, VecZnxSubInplace, + ScratchTakeBasic, }, - layouts::{Backend, DataRef, Module, ScalarZnx, ScratchOwned, VecZnxBig, VecZnxDft, ZnxZero}, + layouts::{Backend, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ScratchOwned, VecZnxBig, VecZnxDft, ZnxZero}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{GGSW, GGSWInfos, GLWE, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::layouts::{GGSW, GGSWInfos, GLWEInfos, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared, GGSWToRef}; +use crate::layouts::prepared::GLWESecretPreparedToRef; +use crate::decryption::GLWEDecryption; impl GGSW { - pub fn assert_noise( + pub fn assert_noise( &self, - module: &Module, - sk_prepared: &GLWESecretPrepared, + module: &M, + sk_prepared: &GLWESecretPrepared, pt_want: &ScalarZnx, - max_noise: F, + max_noise: F ) where DataSk: DataRef, DataScalar: DataRef, - Module: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply - + SvpApplyDftToDftInplace - + VecZnxIdftApplyConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes - + VecZnxBigAlloc - + VecZnxDftAlloc - + VecZnxBigNormalizeTmpBytes - + VecZnxIdftApplyTmpA - + VecZnxAddScalarInplace - + VecZnxSubInplace, - B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + M: GGSWNoise, + BE: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, F: Fn(usize) -> f64, { - let base2k: usize = self.base2k().into(); - let dsize: usize = self.dsize().into(); + module.ggsw_assert_noise(self, sk_prepared, pt_want, max_noise); + } - let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - let mut pt_dft: VecZnxDft, B> = module.vec_znx_dft_alloc(1, self.size()); - let mut pt_big: VecZnxBig, B> = module.vec_znx_big_alloc(1, self.size()); + pub fn print_noise( + &self, + module: &M, + sk_prepared: &GLWESecretPrepared, + pt_want: &ScalarZnx, + ) where + DataSk: DataRef, + DataScalar: DataRef, + M: GGSWNoise, + BE: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, + { + module.ggsw_print_noise(self, sk_prepared, pt_want); + } +} - let mut scratch: ScratchOwned = - ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self) | module.vec_znx_normalize_tmp_bytes()); +pub trait GGSWNoise { + fn ggsw_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: F) + where + R: GGSWToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, + F: Fn(usize) -> f64; - (0..(self.rank() + 1).into()).for_each(|col_j| { - (0..self.dnum().into()).for_each(|row_i| { - module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0); + fn ggsw_print_noise(&self, res: &R, sk_prepared: &S, pt_want: &P) + where + R: GGSWToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow; +} + +impl GGSWNoise for Module +where + Module: VecZnxDftBytesOf + + VecZnxBigBytesOf + + VecZnxDftApply + + SvpApplyDftToDftInplace + + VecZnxIdftApplyConsume + + VecZnxBigAddInplace + + VecZnxBigAddSmallInplace + + VecZnxBigNormalize + + VecZnxNormalizeTmpBytes + + VecZnxBigAlloc + + VecZnxDftAlloc + + VecZnxBigNormalizeTmpBytes + + VecZnxIdftApplyTmpA + + VecZnxAddScalarInplace + + VecZnxSubInplace + + GLWEDecryption, + Scratch: ScratchTakeBasic, +{ + fn ggsw_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: F) + where + R: GGSWToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, + F: Fn(usize) -> f64, + { + + let res: &GGSW<&[u8]> = &res.to_ref(); + let sk_prepared: &GLWESecretPrepared<&[u8], BE> = &sk_prepared.to_ref(); + + let base2k: usize = res.base2k().into(); + let dsize: usize = res.dsize().into(); + + let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res); + let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res); + let mut pt_dft: VecZnxDft, BE> = self.vec_znx_dft_alloc(1, res.size()); + let mut pt_big: VecZnxBig, BE> = self.vec_znx_big_alloc(1, res.size()); + + let mut scratch: ScratchOwned = + ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res) | self.vec_znx_normalize_tmp_bytes()); + + (0..(res.rank() + 1).into()).for_each(|col_j| { + (0..res.dnum().into()).for_each(|row_i| { + self.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0); // mul with sk[col_j-1] if col_j > 0 { - module.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0); - module.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); - module.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0); - module.vec_znx_big_normalize( + self.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0); + self.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); + self.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0); + self.vec_znx_big_normalize( base2k, &mut pt.data, 0, @@ -70,10 +126,9 @@ impl GGSW { ); } - self.at(row_i, col_j) - .decrypt(module, &mut pt_have, sk_prepared, scratch.borrow()); + self.glwe_decrypt(&res.at(row_i, col_j), &mut pt_have, sk_prepared, scratch.borrow()); - module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0); + self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0); let std_pt: f64 = pt_have.data.std(base2k, 0).log2(); let noise: f64 = max_noise(col_j); @@ -81,57 +136,40 @@ impl GGSW { pt.data.zero(); }); - }); + }); } -} -impl GGSW { - pub fn print_noise( - &self, - module: &Module, - sk_prepared: &GLWESecretPrepared, - pt_want: &ScalarZnx, - ) where - DataSk: DataRef, - DataScalar: DataRef, - Module: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply - + SvpApplyDftToDftInplace - + VecZnxIdftApplyConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes - + VecZnxBigAlloc - + VecZnxDftAlloc - + VecZnxBigNormalizeTmpBytes - + VecZnxIdftApplyTmpA - + VecZnxAddScalarInplace - + VecZnxSubInplace, - B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + fn ggsw_print_noise(&self, res: &R, sk_prepared: &S, pt_want: &P) + where + R: GGSWToRef, + S: GLWESecretPreparedToRef, + P: ScalarZnxToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, { - let base2k: usize = self.base2k().into(); - let dsize: usize = self.dsize().into(); + let res: &GGSW<&[u8]> = &res.to_ref(); + let sk_prepared: &GLWESecretPrepared<&[u8], BE> = &sk_prepared.to_ref(); - let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - let mut pt_dft: VecZnxDft, B> = module.vec_znx_dft_alloc(1, self.size()); - let mut pt_big: VecZnxBig, B> = module.vec_znx_big_alloc(1, self.size()); + let base2k: usize = res.base2k().into(); + let dsize: usize = res.dsize().into(); - let mut scratch: ScratchOwned = - ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self) | module.vec_znx_normalize_tmp_bytes()); + let mut pt: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res); + let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res); + let mut pt_dft: VecZnxDft, BE> = self.vec_znx_dft_alloc(1, res.size()); + let mut pt_big: VecZnxBig, BE> = self.vec_znx_big_alloc(1, res.size()); - (0..(self.rank() + 1).into()).for_each(|col_j| { - (0..self.dnum().into()).for_each(|row_i| { - module.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0); + let mut scratch: ScratchOwned = + ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res) | self.vec_znx_normalize_tmp_bytes()); + + (0..(res.rank() + 1).into()).for_each(|col_j| { + (0..res.dnum().into()).for_each(|row_i| { + self.vec_znx_add_scalar_inplace(&mut pt.data, 0, (dsize - 1) + row_i * dsize, pt_want, 0); // mul with sk[col_j-1] if col_j > 0 { - module.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0); - module.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); - module.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0); - module.vec_znx_big_normalize( + self.vec_znx_dft_apply(1, 0, &mut pt_dft, 0, &pt.data, 0); + self.svp_apply_dft_to_dft_inplace(&mut pt_dft, 0, &sk_prepared.data, col_j - 1); + self.vec_znx_idft_apply_tmpa(&mut pt_big, 0, &mut pt_dft, 0); + self.vec_znx_big_normalize( base2k, &mut pt.data, 0, @@ -142,15 +180,13 @@ impl GGSW { ); } - self.at(row_i, col_j) - .decrypt(module, &mut pt_have, sk_prepared, scratch.borrow()); - module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0); + self.glwe_decrypt(&res.at(row_i, col_j), &mut pt_have, sk_prepared, scratch.borrow()); + self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt.data, 0); let std_pt: f64 = pt_have.data.std(base2k, 0).log2(); println!("col: {col_j} row: {row_i}: {std_pt}"); pt.data.zero(); - // println!(">>>>>>>>>>>>>>>>"); }); }); - } -} + } +} \ No newline at end of file diff --git a/poulpy-core/src/noise/glwe_ct.rs b/poulpy-core/src/noise/glwe_ct.rs index 40b86d9..16986b5 100644 --- a/poulpy-core/src/noise/glwe_ct.rs +++ b/poulpy-core/src/noise/glwe_ct.rs @@ -2,67 +2,159 @@ use poulpy_hal::{ api::{ ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDftInplace, VecZnxBigAddInplace, VecZnxBigAddSmallInplace, VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxDftApply, VecZnxDftBytesOf, VecZnxIdftApplyConsume, VecZnxNormalizeInplace, - VecZnxNormalizeTmpBytes, VecZnxSubInplace, + VecZnxNormalizeTmpBytes, VecZnxSubInplace, ScratchTakeBasic, }, layouts::{Backend, DataRef, Module, Scratch, ScratchOwned}, oep::{ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl}, }; -use crate::layouts::{GLWE, GLWEPlaintext, LWEInfos, prepared::GLWESecretPrepared}; +use crate::{ + decryption::GLWEDecryption, + layouts::{ + GLWE, GLWEPlaintext, GLWEPlaintextToRef, GLWEToRef, LWEInfos, + prepared::{GLWESecretPrepared, GLWESecretPreparedToRef}, + }, +}; impl GLWE { - pub fn noise( - &self, - module: &Module, - sk_prepared: &GLWESecretPrepared, - pt_want: &GLWEPlaintext, - scratch: &mut Scratch, - ) -> f64 + pub fn noise(&self, module: &M, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> f64 where - DataSk: DataRef, - DataPt: DataRef, - B: Backend, - Module: VecZnxDftApply - + VecZnxSubInplace - + VecZnxNormalizeInplace - + SvpApplyDftToDftInplace - + VecZnxIdftApplyConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize, - Scratch:, + M: GLWENoise, + S: GLWESecretPreparedToRef, + P: GLWEPlaintextToRef, { - let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); - self.decrypt(module, &mut pt_have, sk_prepared, scratch); - module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0); - module.vec_znx_normalize_inplace(self.base2k().into(), &mut pt_have.data, 0, scratch); - pt_have.data.std(self.base2k().into(), 0).log2() + module.glwe_noise(self, sk_prepared, pt_want, scratch) } + // pub fn noise( + // &self, + // module: &Module, + // sk_prepared: &GLWESecretPrepared, + // pt_want: &GLWEPlaintext, + // scratch: &mut Scratch, + // ) -> f64 + // where + // DataSk: DataRef, + // DataPt: DataRef, + // B: Backend, + // Module: VecZnxDftApply + // + VecZnxSubInplace + // + VecZnxNormalizeInplace + // + SvpApplyDftToDftInplace + // + VecZnxIdftApplyConsume + // + VecZnxBigAddInplace + // + VecZnxBigAddSmallInplace + // + VecZnxBigNormalize, + // Scratch:, + // { + // let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(module, self); + // self.decrypt(module, &mut pt_have, sk_prepared, scratch); + // module.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0); + // module.vec_znx_normalize_inplace(self.base2k().into(), &mut pt_have.data, 0, scratch); + // pt_have.data.std(self.base2k().into(), 0).log2() + // } - pub fn assert_noise( + pub fn assert_noise( &self, - module: &Module, - sk_prepared: &GLWESecretPrepared, + module: &M, + sk_prepared: &GLWESecretPrepared, pt_want: &GLWEPlaintext, max_noise: f64, ) where DataSk: DataRef, DataPt: DataRef, - Module: VecZnxDftBytesOf - + VecZnxBigBytesOf - + VecZnxDftApply - + SvpApplyDftToDftInplace - + VecZnxIdftApplyConsume - + VecZnxBigAddInplace - + VecZnxBigAddSmallInplace - + VecZnxBigNormalize - + VecZnxNormalizeTmpBytes - + VecZnxSubInplace - + VecZnxNormalizeInplace, - B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + M: GLWENoise, + BE: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, { - let mut scratch: ScratchOwned = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); - let noise_have: f64 = self.noise(module, sk_prepared, pt_want, scratch.borrow()); + module.glwe_assert_noise(self, sk_prepared, pt_want, max_noise); + } + + // pub fn assert_noise( + // &self, + // module: &Module, + // sk_prepared: &GLWESecretPrepared, + // pt_want: &GLWEPlaintext, + // max_noise: f64, + // ) where + // DataSk: DataRef, + // DataPt: DataRef, + // Module: VecZnxDftBytesOf + // + VecZnxBigBytesOf + // + VecZnxDftApply + // + SvpApplyDftToDftInplace + // + VecZnxIdftApplyConsume + // + VecZnxBigAddInplace + // + VecZnxBigAddSmallInplace + // + VecZnxBigNormalize + // + VecZnxNormalizeTmpBytes + // + VecZnxSubInplace + // + VecZnxNormalizeInplace, + // B: Backend + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl, + // { + // let mut scratch: ScratchOwned = ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, self)); + // let noise_have: f64 = self.noise(module, sk_prepared, pt_want, scratch.borrow()); + // assert!(noise_have <= max_noise, "{noise_have} {max_noise}"); + // } +} + + +pub trait GLWENoise { + fn glwe_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> f64 + where + R: GLWEToRef, + S: GLWESecretPreparedToRef, + P: GLWEPlaintextToRef; + + fn glwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) + where + R: GLWEToRef, + S: GLWESecretPreparedToRef, + P: GLWEPlaintextToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow; +} + +impl GLWENoise for Module +where + Module: VecZnxDftBytesOf + + VecZnxBigBytesOf + + VecZnxDftApply + + SvpApplyDftToDftInplace + + VecZnxIdftApplyConsume + + VecZnxBigAddInplace + + VecZnxBigAddSmallInplace + + VecZnxBigNormalize + + VecZnxNormalizeTmpBytes + + VecZnxSubInplace + + VecZnxNormalizeInplace + + GLWEDecryption, + Scratch: ScratchTakeBasic + ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, +{ + fn glwe_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, scratch: &mut Scratch) -> f64 + where + R: GLWEToRef, + S: GLWESecretPreparedToRef, + P: GLWEPlaintextToRef, + { + let res_ref: &GLWE<&[u8]> = &res.to_ref(); + + let pt_want: &GLWEPlaintext<&[u8]> = &pt_want.to_ref(); + + let mut pt_have: GLWEPlaintext> = GLWEPlaintext::alloc_from_infos(self, res_ref); + self.glwe_decrypt(res, &mut pt_have, sk_prepared, scratch); + self.vec_znx_sub_inplace(&mut pt_have.data, 0, &pt_want.data, 0); + self.vec_znx_normalize_inplace(res_ref.base2k().into(), &mut pt_have.data, 0, scratch); + pt_have.data.std(res_ref.base2k().into(), 0).log2() + } + + fn glwe_assert_noise(&self, res: &R, sk_prepared: &S, pt_want: &P, max_noise: f64) + where + R: GLWEToRef, + S: GLWESecretPreparedToRef, + P: GLWEPlaintextToRef, + BE: ScratchOwnedAllocImpl + ScratchOwnedBorrowImpl + ScratchOwnedBorrow, + { + let res: &GLWE<&[u8]> = &res.to_ref(); + let mut scratch: ScratchOwned = ScratchOwned::alloc(self.glwe_decrypt_tmp_bytes(res)); + let noise_have: f64 = self.glwe_noise(res, sk_prepared, pt_want, scratch.borrow()); assert!(noise_have <= max_noise, "{noise_have} {max_noise}"); } -} +} \ No newline at end of file