arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/encryption/compressed/gglwe_ct.rs
core/src/encryption/compressed/gglwe_ct.rsRaw
  1use backend::hal::{
  2    api::{ScratchAvailable, TakeVecZnx, TakeVecZnxDft, VecZnxAddScalarInplace, VecZnxNormalizeInplace, ZnxZero},
  3    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, Scratch},
  4};
  5use sampling::source::Source;
  6
  7use crate::{
  8    TakeGLWEPt,
  9    encryption::glwe_encrypt_sk_internal,
 10    layouts::{GGLWECiphertext, Infos, compressed::GGLWECiphertextCompressed, prepared::GLWESecretPrepared},
 11};
 12
 13use crate::trait_families::{GGLWEEncryptSkFamily, GGLWESwitchingKeyEncryptSkFamily};
 14
 15impl GGLWECiphertextCompressed<Vec<u8>> {
 16    pub fn encrypt_sk_scratch_space<B: Backend>(module: &Module<B>, n: usize, basek: usize, k: usize) -> usize
 17    where
 18        Module<B>: GGLWESwitchingKeyEncryptSkFamily<B>,
 19    {
 20        GGLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k)
 21    }
 22}
 23
 24impl<D: DataMut> GGLWECiphertextCompressed<D> {
 25    pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
 26        &mut self,
 27        module: &Module<B>,
 28        pt: &ScalarZnx<DataPt>,
 29        sk: &GLWESecretPrepared<DataSk, B>,
 30        seed: [u8; 32],
 31        source_xe: &mut Source,
 32        sigma: f64,
 33        scratch: &mut Scratch<B>,
 34    ) where
 35        Module<B>: GGLWEEncryptSkFamily<B> + VecZnxAddScalarInplace,
 36        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
 37    {
 38        #[cfg(debug_assertions)]
 39        {
 40            use backend::hal::api::ZnxInfos;
 41
 42            assert_eq!(
 43                self.rank_in(),
 44                pt.cols(),
 45                "self.rank_in(): {} != pt.cols(): {}",
 46                self.rank_in(),
 47                pt.cols()
 48            );
 49            assert_eq!(
 50                self.rank_out(),
 51                sk.rank(),
 52                "self.rank_out(): {} != sk.rank(): {}",
 53                self.rank_out(),
 54                sk.rank()
 55            );
 56            assert_eq!(self.n(), sk.n());
 57            assert_eq!(pt.n(), sk.n());
 58            assert!(
 59                scratch.available()
 60                    >= GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k()),
 61                "scratch.available: {} < GGLWECiphertext::encrypt_sk_scratch_space(module, self.rank()={}, self.size()={}): {}",
 62                scratch.available(),
 63                self.rank(),
 64                self.size(),
 65                GGLWECiphertextCompressed::encrypt_sk_scratch_space(module, sk.n(), self.basek(), self.k())
 66            );
 67            assert!(
 68                self.rows() * self.digits() * self.basek() <= self.k(),
 69                "self.rows() : {} * self.digits() : {} * self.basek() : {} = {} >= self.k() = {}",
 70                self.rows(),
 71                self.digits(),
 72                self.basek(),
 73                self.rows() * self.digits() * self.basek(),
 74                self.k()
 75            );
 76        }
 77
 78        let rows: usize = self.rows();
 79        let digits: usize = self.digits();
 80        let basek: usize = self.basek();
 81        let k: usize = self.k();
 82        let rank_in: usize = self.rank_in();
 83        let cols: usize = self.rank_out() + 1;
 84
 85        let mut source_xa = Source::new(seed);
 86
 87        let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(sk.n(), basek, k);
 88        (0..rank_in).for_each(|col_i| {
 89            (0..rows).for_each(|row_i| {
 90                // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
 91                tmp_pt.data.zero(); // zeroes for next iteration
 92                module.vec_znx_add_scalar_inplace(
 93                    &mut tmp_pt.data,
 94                    0,
 95                    (digits - 1) + row_i * digits,
 96                    pt,
 97                    col_i,
 98                );
 99                module.vec_znx_normalize_inplace(basek, &mut tmp_pt.data, 0, scrach_1);
100
101                let (seed, mut source_xa_tmp) = source_xa.branch();
102                self.seed[col_i * rows + row_i] = seed;
103
104                glwe_encrypt_sk_internal(
105                    module,
106                    self.basek(),
107                    self.k(),
108                    &mut self.at_mut(row_i, col_i).data,
109                    cols,
110                    true,
111                    Some((&tmp_pt, 0)),
112                    sk,
113                    &mut source_xa_tmp,
114                    source_xe,
115                    sigma,
116                    scrach_1,
117                );
118            });
119        });
120    }
121}