arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/glwe/decryption.rs
core/src/glwe/decryption.rsRaw
 1use backend::{
 2    FFT64, Module, ScalarZnxDftOps, Scratch, VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDftAlloc, VecZnxDftOps,
 3    ZnxZero,
 4};
 5
 6use crate::{FourierGLWESecret, GLWECiphertext, GLWEPlaintext, Infos};
 7
 8impl GLWECiphertext<Vec<u8>> {
 9    pub fn decrypt_scratch_space(module: &Module<FFT64>, basek: usize, k: usize) -> usize {
10        let size: usize = k.div_ceil(basek);
11        (module.vec_znx_big_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_big(1, size)
12    }
13}
14
15impl<DataSelf: AsRef<[u8]>> GLWECiphertext<DataSelf> {
16    pub fn decrypt<DataPt: AsMut<[u8]> + AsRef<[u8]>, DataSk: AsRef<[u8]>>(
17        &self,
18        module: &Module<FFT64>,
19        pt: &mut GLWEPlaintext<DataPt>,
20        sk: &FourierGLWESecret<DataSk, FFT64>,
21        scratch: &mut Scratch,
22    ) {
23        #[cfg(debug_assertions)]
24        {
25            assert_eq!(self.rank(), sk.rank());
26            assert_eq!(self.n(), module.n());
27            assert_eq!(pt.n(), module.n());
28            assert_eq!(sk.n(), module.n());
29        }
30
31        let cols: usize = self.rank() + 1;
32
33        let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, self.size()); // TODO optimize size when pt << ct
34        c0_big.zero();
35
36        {
37            (1..cols).for_each(|i| {
38                // ci_dft = DFT(a[i]) * DFT(s[i])
39                let (mut ci_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, self.size()); // TODO optimize size when pt << ct
40                module.vec_znx_dft(1, 0, &mut ci_dft, 0, &self.data, i);
41                module.svp_apply_inplace(&mut ci_dft, 0, &sk.data, i - 1);
42                let ci_big = module.vec_znx_idft_consume(ci_dft);
43
44                // c0_big += a[i] * s[i]
45                module.vec_znx_big_add_inplace(&mut c0_big, 0, &ci_big, 0);
46            });
47        }
48
49        // c0_big = (a * s) + (-a * s + m + e) = BIG(m + e)
50        module.vec_znx_big_add_small_inplace(&mut c0_big, 0, &self.data, 0);
51
52        // pt = norm(BIG(m + e))
53        module.vec_znx_big_normalize(self.basek(), &mut pt.data, 0, &mut c0_big, 0, scratch_1);
54
55        pt.basek = self.basek();
56        pt.k = pt.k().min(self.k());
57    }
58}