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