arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/encryption/gglwe_ct.rs
poulpy-core/src/encryption/gglwe_ct.rsRaw
  1use poulpy_hal::{
  2    api::{ModuleN, ScratchAvailable, VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes},
  3    // oep::SvpPPolAllocBytesImpl,
  4    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxZero},
  5    source::Source,
  6};
  7
  8use crate::{
  9    encryption::glwe_ct::GLWEEncryptSk, layouts::GLWEInfos, ScratchTakeCore,
 10    layouts::{
 11        GGLWE, GGLWEInfos, GGLWEToMut, GLWE, GLWEPlaintext, LWEInfos,
 12        prepared::{GLWESecretPrepared, GLWESecretPreparedToRef},
 13    },
 14};
 15
 16impl GGLWE<Vec<u8>> {
 17
 18    pub fn encrypt_sk_tmp_bytes<M, A, BE: Backend>(module: &M, infos: &A) -> usize
 19    where
 20        A: GGLWEInfos,
 21        M: GGLWEEncryptSk<BE>,
 22    {
 23        module.gglwe_encrypt_sk_tmp_bytes(infos)
 24    }
 25
 26    pub fn encrypt_pk_tmp_bytes<M, A, BE: Backend>(module: &M, infos: &A) -> usize
 27    where
 28        A: GGLWEInfos,
 29        M: GGLWEEncryptSk<BE>,
 30    {
 31        module.gglwe_encrypt_sk_tmp_bytes(infos)
 32    }
 33}
 34
 35pub trait GGLWEEncryptSk<B: Backend> {
 36
 37    fn gglwe_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
 38    where
 39        A: GGLWEInfos;
 40
 41    fn gglwe_encrypt_pk_tmp_bytes<A>(&self, infos: &A) -> usize
 42        where
 43            A: GGLWEInfos;        
 44
 45    fn gglwe_encrypt_sk<R, P, S>(
 46        &self,
 47        res: &mut R,
 48        pt: &P,
 49        sk: &S,
 50        source_xa: &mut Source,
 51        source_xe: &mut Source,
 52        scratch: &mut Scratch<B>,
 53    ) where
 54        R: GGLWEToMut,
 55        P: ScalarZnxToRef,
 56        S: GLWESecretPreparedToRef<B>;
 57}
 58
 59impl<B: Backend> GGLWEEncryptSk<B> for Module<B>
 60where
 61    Module<B>: ModuleN
 62        + GLWEEncryptSk<B>
 63        + VecZnxNormalizeTmpBytes
 64        + VecZnxDftBytesOf
 65        + VecZnxAddScalarInplace
 66        + VecZnxNormalizeInplace<B>,
 67    // + SvpPPolAllocBytesImpl<B>,
 68    Scratch<B>: ScratchAvailable + ScratchTakeCore<B>,
 69{
 70    fn gglwe_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
 71    where
 72        A: GGLWEInfos,
 73    {
 74        GLWE::encrypt_sk_tmp_bytes(self, &infos.glwe_layout())
 75            + (GLWEPlaintext::bytes_of_from_infos(self, &infos.glwe_layout()) | self.vec_znx_normalize_tmp_bytes())
 76    }
 77
 78    fn gglwe_encrypt_pk_tmp_bytes<A>(&self, _infos: &A) -> usize
 79    where
 80        A: GGLWEInfos,
 81    {
 82        unimplemented!()
 83        // TODO: Is this correct?
 84        // GLWE::encrypt_pk_tmp_bytes(self, &infos.glwe_layout())
 85        //     + (GLWEPlaintext::bytes_of_from_infos(self, &infos.glwe_layout()) | self.vec_znx_normalize_tmp_bytes())
 86
 87    }
 88
 89    fn gglwe_encrypt_sk<R, P, S>(
 90        &self,
 91        res: &mut R,
 92        pt: &P,
 93        sk: &S,
 94        source_xa: &mut Source,
 95        source_xe: &mut Source,
 96        scratch: &mut Scratch<B>,
 97    ) where
 98        R: GGLWEToMut,
 99        P: ScalarZnxToRef,
100        S: GLWESecretPreparedToRef<B>,
101    {
102        let res: &mut GGLWE<&mut [u8]> = &mut res.to_mut();
103        let pt: &ScalarZnx<&[u8]> = &pt.to_ref();
104
105        #[cfg(debug_assertions)]
106        {
107            use poulpy_hal::layouts::ZnxInfos;
108            let sk: GLWESecretPrepared<&[u8], B> = sk.to_ref();
109
110            assert_eq!(
111                res.rank_in(),
112                pt.cols() as u32,
113                "res.rank_in(): {} != pt.cols(): {}",
114                res.rank_in(),
115                pt.cols()
116            );
117            assert_eq!(
118                res.rank_out(),
119                sk.rank(),
120                "res.rank_out(): {} != sk.rank(): {}",
121                res.rank_out(),
122                sk.rank()
123            );
124            assert_eq!(res.n(), sk.n());
125            assert_eq!(pt.n() as u32, sk.n());
126            assert!(
127                scratch.available() >= GGLWE::encrypt_sk_tmp_bytes(self, res),
128                "scratch.available: {} < GGLWECiphertext::encrypt_sk_tmp_bytes(self, res.rank()={}, res.size()={}): {}",
129                scratch.available(),
130                res.rank_out(),
131                res.size(),
132                GGLWE::encrypt_sk_tmp_bytes(self, res)
133            );
134            assert!(
135                res.dnum().0 * res.dsize().0 * res.base2k().0 <= res.k().0,
136                "res.dnum() : {} * res.dsize() : {} * res.base2k() : {} = {} >= res.k() = {}",
137                res.dnum(),
138                res.dsize(),
139                res.base2k(),
140                res.dnum().0 * res.dsize().0 * res.base2k().0,
141                res.k()
142            );
143        }
144
145        let dnum: usize = res.dnum().into();
146        let dsize: usize = res.dsize().into();
147        let base2k: usize = res.base2k().into();
148        let rank_in: usize = res.rank_in().into();
149
150        let (mut tmp_pt, scrach_1) = scratch.take_glwe_pt(self, &res.glwe_layout());
151        // For each input column (i.e. rank) produces a GGLWE ciphertext of rank_out+1 columns
152        //
153        // Example for ksk rank 2 to rank 3:
154        //
155        // (-(a0*s0 + a1*s1 + a2*s2) + s0', a0, a1, a2)
156        // (-(b0*s0 + b1*s1 + b2*s2) + s0', b0, b1, b2)
157        //
158        // Example ksk rank 2 to rank 1
159        //
160        // (-(a*s) + s0, a)
161        // (-(b*s) + s1, b)
162
163        for col_i in 0..rank_in {
164            for row_i in 0..dnum {
165                // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
166                tmp_pt.data.zero(); // zeroes for next iteration
167                self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, col_i);
168                self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scrach_1);
169                self.glwe_encrypt_sk(
170                    &mut res.at_mut(row_i, col_i),
171                    &tmp_pt,
172                    sk,
173                    source_xa,
174                    source_xe,
175                    scrach_1,
176                );
177            }
178        }
179    }
180}
181
182impl<DataSelf: DataMut> GGLWE<DataSelf> {
183    #[allow(clippy::too_many_arguments)]
184    pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
185        &mut self,
186        module: &Module<B>,
187        pt: &ScalarZnx<DataPt>,
188        sk: &GLWESecretPrepared<DataSk, B>,
189        source_xa: &mut Source,
190        source_xe: &mut Source,
191        scratch: &mut Scratch<B>,
192    ) where
193        Module<B>: GGLWEEncryptSk<B>,
194    {
195        module.gglwe_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch);
196    }
197}