poulpy/poulpy-core/src/encryption/ggsw_ct.rs
poulpy-core/src/encryption/ggsw_ct.rsRaw
1use poulpy_hal::{
2 api::{VecZnxAddScalarInplace, VecZnxDftBytesOf, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes},
3 layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, VecZnx, ZnxZero},
4 source::Source,
5};
6
7use crate::{
8 SIGMA,
9 encryption::glwe_ct::GLWEEncryptSkInternal,
10 layouts::{
11 GGSW, GGSWInfos, GGSWToMut, GLWE, GLWEInfos, LWEInfos,
12 prepared::{GLWESecretPrepared, GLWESecretPreparedToRef},
13 },
14};
15
16impl GGSW<Vec<u8>> {
17 pub fn encrypt_sk_scratch_space<B: Backend, A>(module: &Module<B>, infos: &A) -> usize
18 where
19 A: GGSWInfos,
20 Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftBytesOf,
21 {
22 let size = infos.size();
23 GLWE::encrypt_sk_scratch_space(module, &infos.glwe_layout())
24 + VecZnx::bytes_of(module.n(), (infos.rank() + 1).into(), size)
25 + VecZnx::bytes_of(module.n(), 1, size)
26 + module.bytes_of_vec_znx_dft((infos.rank() + 1).into(), size)
27 }
28}
29
30pub trait GGSWEncryptSk<B: Backend> {
31 fn ggsw_encrypt_sk<R, P, S>(
32 &self,
33 res: &mut R,
34 pt: &P,
35 sk: &S,
36 source_xa: &mut Source,
37 source_xe: &mut Source,
38 scratch: &mut Scratch<B>,
39 ) where
40 R: GGSWToMut,
41 P: ScalarZnxToRef,
42 S: GLWESecretPreparedToRef<B>;
43}
44
45impl<B: Backend> GGSWEncryptSk<B> for Module<B>
46where
47 Module<B>: GLWEEncryptSkInternal<B> + VecZnxAddScalarInplace + VecZnxNormalizeInplace<B>,
48 Scratch<B>:,
49{
50 fn ggsw_encrypt_sk<R, P, S>(
51 &self,
52 res: &mut R,
53 pt: &P,
54 sk: &S,
55 source_xa: &mut Source,
56 source_xe: &mut Source,
57 scratch: &mut Scratch<B>,
58 ) where
59 R: GGSWToMut,
60 P: ScalarZnxToRef,
61 S: GLWESecretPreparedToRef<B>,
62 {
63 let res: &mut GGSW<&mut [u8]> = &mut res.to_mut();
64 let pt: &ScalarZnx<&[u8]> = &pt.to_ref();
65 let sk: &GLWESecretPrepared<&[u8], B> = &sk.to_ref();
66
67 #[cfg(debug_assertions)]
68 {
69 use poulpy_hal::layouts::ZnxInfos;
70
71 assert_eq!(res.rank(), sk.rank());
72 assert_eq!(res.n(), self.n() as u32);
73 assert_eq!(pt.n(), self.n());
74 assert_eq!(sk.n(), self.n() as u32);
75 }
76
77 let k: usize = res.k().into();
78 let base2k: usize = res.base2k().into();
79 let rank: usize = res.rank().into();
80 let dsize: usize = res.dsize().into();
81 let cols: usize = (rank + 1).into();
82
83 let (mut tmp_pt, scratch_1) = scratch.take_glwe_pt(&res.glwe_layout());
84
85 for row_i in 0..res.dnum().into() {
86 tmp_pt.data.zero();
87 // Adds the scalar_znx_pt to the i-th limb of the vec_znx_pt
88 self.vec_znx_add_scalar_inplace(&mut tmp_pt.data, 0, (dsize - 1) + row_i * dsize, pt, 0);
89 self.vec_znx_normalize_inplace(base2k, &mut tmp_pt.data, 0, scratch_1);
90 for col_j in 0..rank + 1 {
91 self.glwe_encrypt_sk_internal(
92 base2k,
93 k,
94 res.at_mut(row_i, col_j).data_mut(),
95 cols,
96 false,
97 Some((&tmp_pt, col_j)),
98 sk,
99 source_xa,
100 source_xe,
101 SIGMA,
102 scratch_1,
103 );
104 }
105 }
106 }
107}
108
109impl<DataSelf: DataMut> GGSW<DataSelf> {
110 #[allow(clippy::too_many_arguments)]
111 pub fn encrypt_sk<DataPt: DataRef, DataSk: DataRef, B: Backend>(
112 &mut self,
113 module: &Module<B>,
114 pt: &ScalarZnx<DataPt>,
115 sk: &GLWESecretPrepared<DataSk, B>,
116 source_xa: &mut Source,
117 source_xe: &mut Source,
118 scratch: &mut Scratch<B>,
119 ) where
120 Module<B>: GGSWEncryptSk<B>,
121 {
122 module.ggsw_encrypt_sk(self, pt, sk, source_xa, source_xe, scratch);
123 }
124}