poulpy/rlwe/src/encryption.rs
rlwe/src/encryption.rsRaw
1use base2k::{
2 AddNormal, Backend, FillUniform, Module, VecZnxDftOps, ScalarZnxDftOps, ScalarZnxDftToRef, VecZnxBigOps, Scratch, VecZnx, VecZnxToMut, VecZnxToRef, ZnxInfos, FFT64
3};
4
5use sampling::source::Source;
6
7use crate::{
8 elem::{CipherVecZnx, Plaintext},
9 keys::SecretKey,
10};
11
12pub trait EncryptSk<B: Backend, D> {
13 fn encrypt<P, S>(
14 module: &Module<B>,
15 res: &mut D,
16 pt: Option<&Plaintext<P>>,
17 sk: &SecretKey<S>,
18 source_xa: &mut Source,
19 source_xe: &mut Source,
20 scratch: &mut Scratch,
21 sigma: f64,
22 bound: f64,
23 ) where
24 P: VecZnxToRef,
25 S: ScalarZnxDftToRef<B>;
26}
27
28impl<C> EncryptSk<FFT64, CipherVecZnx<C>> for CipherVecZnx<C>
29where
30 VecZnx<C>: VecZnxToMut + VecZnxToRef,
31{
32 fn encrypt<P, S>(
33 module: &Module<FFT64>,
34 ct: &mut CipherVecZnx<C>,
35 pt: Option<&Plaintext<P>>,
36 sk: &SecretKey<S>,
37 source_xa: &mut Source,
38 source_xe: &mut Source,
39 scratch: &mut Scratch,
40 sigma: f64,
41 bound: f64,
42 ) where
43 P: VecZnxToRef,
44 S: ScalarZnxDftToRef<FFT64>,
45 {
46 let log_base2k: usize = ct.log_base2k();
47 let log_q: usize = ct.log_q();
48 let mut ct_mut: VecZnx<&mut [u8]> = ct.data_mut().to_mut();
49 let size: usize = ct_mut.size();
50
51 ct_mut.fill_uniform(log_base2k, 1, size, source_xa);
52
53 // c1_dft = DFT(a) * DFT(s)
54 let (mut c1_dft, scratch_1) = scratch.tmp_vec_znx_dft(module, 1, size);
55 module.svp_apply(&mut c1_dft, 0, &sk.data().to_ref(), 0, &ct_mut, 1);
56
57 // c1_big = IDFT(c1_dft)
58 let (mut c1_big, scratch_2) = scratch_1.tmp_vec_znx_big(module, 1, size);
59 module.vec_znx_idft_tmp_a(&mut c1_big, 0, &mut c1_dft, 0);
60
61 // c1_big = m - c1_big
62 if let Some(pt) = pt {
63 module.vec_znx_big_sub_small_b_inplace(&mut c1_big, 0, &pt.data().to_ref(), 0);
64 }
65 // c1_big += e
66 c1_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound);
67
68 // c0 = norm(c1_big)
69 module.vec_znx_big_normalize(log_base2k, &mut ct_mut, 0, &c1_big, 0, scratch_2);
70 }
71}