poulpy/rlwe/src/encryption.rs
rlwe/src/encryption.rsRaw
1use base2k::{
2 AddNormal, Backend, FFT64, FillUniform, Module, ScalarZnxDftOps, ScalarZnxDftToRef, Scratch, VecZnx, VecZnxAlloc,
3 VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxToMut,
4 VecZnxToRef, ZnxInfos,
5};
6
7use sampling::source::Source;
8
9use crate::{elem::Infos, keys::SecretKey};
10
11pub trait EncryptSk<B: Backend, D, P> {
12 fn encrypt<S>(
13 module: &Module<B>,
14 res: &mut D,
15 pt: Option<&P>,
16 sk: &SecretKey<S>,
17 source_xa: &mut Source,
18 source_xe: &mut Source,
19 scratch: &mut Scratch,
20 sigma: f64,
21 bound: f64,
22 ) where
23 S: ScalarZnxDftToRef<B>;
24
25 fn encrypt_tmp_bytes(module: &Module<B>, size: usize) -> usize {
26 (module.vec_znx_big_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_big(1, size)
27 }
28}
29
30impl<C, P> EncryptSk<FFT64, C, P> for C
31where
32 C: VecZnxToMut + ZnxInfos + Infos<C>,
33 P: VecZnxToRef,
34{
35 fn encrypt<S>(
36 module: &Module<FFT64>,
37 ct: &mut C,
38 pt: Option<&P>,
39 sk: &SecretKey<S>,
40 source_xa: &mut Source,
41 source_xe: &mut Source,
42 scratch: &mut Scratch,
43 sigma: f64,
44 bound: f64,
45 ) where
46 S: ScalarZnxDftToRef<FFT64>,
47 {
48 let log_base2k: usize = ct.log_base2k();
49 let log_q: usize = ct.log_q();
50 let mut ct_mut: VecZnx<&mut [u8]> = ct.to_mut();
51 let size: usize = ct_mut.size();
52
53 // c1 = a
54 ct_mut.fill_uniform(log_base2k, 1, size, source_xa);
55
56 let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, size);
57
58 {
59 let (mut c0_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, size);
60 module.vec_znx_dft(&mut c0_dft, 0, &ct_mut, 1);
61
62 // c0_dft = DFT(a) * DFT(s)
63 module.svp_apply_inplace(&mut c0_dft, 0, &sk.data().to_ref(), 0);
64
65 // c0_big = IDFT(c0_dft)
66 module.vec_znx_idft_tmp_a(&mut c0_big, 0, &mut c0_dft, 0);
67 }
68
69 // c0_big = m - c0_big
70 if let Some(pt) = pt {
71 module.vec_znx_big_sub_small_b_inplace(&mut c0_big, 0, pt, 0);
72 }
73 // c0_big += e
74 c0_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound);
75
76 // c0 = norm(c0_big = -as + m + e)
77 module.vec_znx_big_normalize(log_base2k, &mut ct_mut, 0, &c0_big, 0, scratch_1);
78 }
79}
80
81pub trait EncryptZeroSk<B: Backend, D> {
82 fn encrypt_zero<S>(
83 module: &Module<B>,
84 res: &mut D,
85 sk: &SecretKey<S>,
86 source_xa: &mut Source,
87 source_xe: &mut Source,
88 scratch: &mut Scratch,
89 sigma: f64,
90 bound: f64,
91 ) where
92 S: ScalarZnxDftToRef<B>;
93
94 fn encrypt_zero_tmp_bytes(module: &Module<B>, size: usize) -> usize {
95 (module.bytes_of_vec_znx(1, size) | module.bytes_of_vec_znx_dft(1, size))
96 + module.bytes_of_vec_znx_big(1, size)
97 + module.bytes_of_vec_znx(1, size)
98 + module.vec_znx_big_normalize_tmp_bytes()
99 }
100}
101
102impl<C> EncryptZeroSk<FFT64, C> for C
103where
104 C: VecZnxDftToMut<FFT64> + ZnxInfos + Infos<C>,
105{
106 fn encrypt_zero<S>(
107 module: &Module<FFT64>,
108 ct: &mut C,
109 sk: &SecretKey<S>,
110 source_xa: &mut Source,
111 source_xe: &mut Source,
112 scratch: &mut Scratch,
113 sigma: f64,
114 bound: f64,
115 ) where
116 S: ScalarZnxDftToRef<FFT64>,
117 {
118 let log_base2k: usize = ct.log_base2k();
119 let log_q: usize = ct.log_q();
120 let mut ct_mut: VecZnxDft<&mut [u8], FFT64> = ct.to_mut();
121 let size: usize = ct_mut.size();
122
123 // ct[1] = DFT(a)
124 {
125 let (mut tmp_znx, _) = scratch.tmp_vec_znx(module, 1, size);
126 tmp_znx.fill_uniform(log_base2k, 1, size, source_xa);
127 module.vec_znx_dft(&mut ct_mut, 1, &tmp_znx, 0);
128 }
129
130 let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, size);
131
132 {
133 let (mut tmp_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, size);
134 // c0_dft = DFT(a) * DFT(s)
135 module.svp_apply(&mut tmp_dft, 0, &sk.data().to_ref(), 0, &ct_mut, 1);
136 // c0_big = IDFT(c0_dft)
137 module.vec_znx_idft_tmp_a(&mut c0_big, 0, &mut tmp_dft, 0);
138 }
139
140 // c0_big += e
141 c0_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound);
142
143 // c0 = norm(c0_big = -as + e)
144 let (mut tmp_znx, scratch_2) = scratch_1.tmp_vec_znx(module, 1, size);
145 module.vec_znx_big_normalize(log_base2k, &mut tmp_znx, 0, &c0_big, 0, scratch_2);
146 // ct[0] = DFT(-as + e)
147 module.vec_znx_dft(&mut ct_mut, 0, &tmp_znx, 0);
148 }
149}