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