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().new_svp_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}