arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/rlwe/src/decryptor.rs
rlwe/src/decryptor.rsRaw
 1use crate::{
 2    ciphertext::Ciphertext,
 3    elem::{Elem, ElemCommon},
 4    keys::SecretKey,
 5    parameters::Parameters,
 6    plaintext::Plaintext,
 7};
 8use base2k::{Module, SvpPPol, SvpPPolOps, VecZnx, VecZnxBigOps, VecZnxDft, VecZnxDftOps};
 9use std::cmp::min;
10
11pub struct Decryptor {
12    #[warn(dead_code)]
13    sk: SvpPPol,
14}
15
16impl Decryptor {
17    pub fn new(params: &Parameters, sk: &SecretKey) -> Self {
18        let mut sk_svp_ppol: SvpPPol = params.module().new_svp_ppol();
19        sk.prepare(params.module(), &mut sk_svp_ppol);
20        Self { sk: sk_svp_ppol }
21    }
22}
23
24pub fn decrypt_rlwe_tmp_byte(module: &Module, limbs: usize) -> usize {
25    module.bytes_of_vec_znx_dft(limbs) + module.vec_znx_big_normalize_tmp_bytes()
26}
27
28impl Parameters {
29    pub fn decrypt_rlwe_tmp_byte(&self, log_q: usize) -> usize {
30        decrypt_rlwe_tmp_byte(
31            self.module(),
32            (log_q + self.log_base2k() - 1) / self.log_base2k(),
33        )
34    }
35
36    pub fn decrypt_rlwe(
37        &self,
38        res: &mut Plaintext,
39        ct: &Ciphertext<VecZnx>,
40        sk: &SvpPPol,
41        tmp_bytes: &mut [u8],
42    ) {
43        decrypt_rlwe(self.module(), &mut res.0, &ct.0, sk, tmp_bytes)
44    }
45}
46
47pub fn decrypt_rlwe(
48    module: &Module,
49    res: &mut Elem<VecZnx>,
50    a: &Elem<VecZnx>,
51    sk: &SvpPPol,
52    tmp_bytes: &mut [u8],
53) {
54    let cols: usize = a.cols();
55
56    assert!(
57        tmp_bytes.len() >= decrypt_rlwe_tmp_byte(module, cols),
58        "invalid tmp_bytes: tmp_bytes.len()={} < decrypt_rlwe_tmp_byte={}",
59        tmp_bytes.len(),
60        decrypt_rlwe_tmp_byte(module, cols)
61    );
62
63    let (tmp_bytes_vec_znx_dft, tmp_bytes_normalize) =
64        tmp_bytes.split_at_mut(module.bytes_of_vec_znx_dft(cols));
65
66    let mut res_dft: VecZnxDft = VecZnxDft::from_bytes_borrow(module, cols, tmp_bytes_vec_znx_dft);
67    let mut res_big: base2k::VecZnxBig = res_dft.as_vec_znx_big();
68
69    // res_dft <- DFT(ct[1]) * DFT(sk)
70    module.svp_apply_dft(&mut res_dft, sk, a.at(1));
71    // res_big <- ct[1] x sk
72    module.vec_znx_idft_tmp_a(&mut res_big, &mut res_dft);
73    // res_big <- ct[1] x sk + ct[0]
74    module.vec_znx_big_add_small_inplace(&mut res_big, a.at(0));
75    // res <- normalize(ct[1] x sk + ct[0])
76    module.vec_znx_big_normalize(a.log_base2k(), res.at_mut(0), &res_big, tmp_bytes_normalize);
77
78    res.log_base2k = a.log_base2k();
79    res.log_q = min(res.log_q(), a.log_q());
80    res.log_scale = a.log_scale();
81}