poulpy/rlwe/src/encryptor.rs
rlwe/src/encryptor.rsRaw
1use crate::ciphertext::Ciphertext;
2use crate::elem::Elem;
3use crate::keys::SecretKey;
4use crate::parameters::Parameters;
5use crate::plaintext::Plaintext;
6use base2k::sampling::Sampling;
7use base2k::{Module, SvpPPol, SvpPPolOps, VecZnx, VecZnxBig, VecZnxDft};
8use sampling::source::Source;
9
10pub struct EncryptorSk {
11 pub sk: SvpPPol,
12}
13
14impl EncryptorSk {
15 pub fn new(params: &Parameters, sk: &SecretKey) -> Self {
16 let mut sk_svp_ppol: SvpPPol = params.module().svp_new_ppol();
17 params.module().svp_prepare(&mut sk_svp_ppol, &sk.0);
18 Self { sk: sk_svp_ppol }
19 }
20
21 pub fn encrypt_rlwe_sk(
22 &self,
23 params: &Parameters,
24 ct: &mut Ciphertext,
25 pt: Option<&Plaintext>,
26 xa_source: &mut Source,
27 xe_source: &mut Source,
28 tmp_bytes: &mut [u8],
29 ) {
30 params.encrypt_rlwe_sk(ct, pt, &self.sk, xa_source, xe_source, tmp_bytes);
31 }
32}
33
34impl Parameters {
35 pub fn encrypt_rlwe_sk_tmp_bytes(&self, limbs: usize) -> usize {
36 encrypt_rlwe_sk_tmp_bytes(self.module(), limbs)
37 }
38
39 pub fn encrypt_rlwe_sk(
40 &self,
41 ct: &mut Ciphertext,
42 pt: Option<&Plaintext>,
43 sk: &SvpPPol,
44 xa_source: &mut Source,
45 xe_source: &mut Source,
46 tmp_bytes: &mut [u8],
47 ) {
48 encrypt_rlwe_sk(
49 self.module(),
50 &mut ct.0,
51 pt.map(|pt| &pt.0),
52 sk,
53 xa_source,
54 xe_source,
55 self.xe(),
56 tmp_bytes,
57 )
58 }
59}
60
61pub fn encrypt_rlwe_sk_tmp_bytes(module: &Module, limbs: usize) -> usize {
62 module.bytes_of_vec_znx_dft(limbs) + module.vec_znx_big_normalize_tmp_bytes()
63}
64
65pub fn encrypt_rlwe_sk(
66 module: &Module,
67 ct: &mut Elem,
68 pt: Option<&Elem>,
69 sk: &SvpPPol,
70 xa_source: &mut Source,
71 xe_source: &mut Source,
72 sigma: f64,
73 tmp_bytes: &mut [u8],
74) {
75 let limbs: usize = ct.limbs();
76
77 assert!(
78 tmp_bytes.len() >= encrypt_rlwe_sk_tmp_bytes(module, limbs),
79 "invalid tmp_bytes: tmp_bytes={} < encrypt_rlwe_sk_tmp_bytes={}",
80 tmp_bytes.len(),
81 encrypt_rlwe_sk_tmp_bytes(module, limbs)
82 );
83
84 let log_q: usize = ct.log_q();
85 let log_base2k: usize = ct.log_base2k();
86 let c1: &mut VecZnx = ct.at_mut(1);
87
88 // c1 <- Z_{2^prec}[X]/(X^{N}+1)
89 c1.fill_uniform(limbs, log_base2k, xa_source);
90
91 let bytes_of_vec_znx_dft = module.bytes_of_vec_znx_dft(limbs);
92
93 // Scratch space for DFT values
94 let mut buf_dft: VecZnxDft =
95 VecZnxDft::from_bytes(limbs, &mut tmp_bytes[..bytes_of_vec_znx_dft]);
96
97 // Applies buf_dft <- s * c1
98 module.svp_apply_dft(&mut buf_dft, sk, c1);
99
100 // Alias scratch space
101 let mut buf_big: VecZnxBig = buf_dft.as_vec_znx_big();
102
103 if let Some(pt) = pt {
104 // buf_big <- m - buf_big
105 module.vec_znx_big_sub_small_a_inplace(&mut buf_big, pt.at(0));
106 };
107
108 let carry: &mut [u8] = &mut tmp_bytes[bytes_of_vec_znx_dft..];
109
110 // c0 <- normalize(buf_big) + e
111 let c0: &mut VecZnx = ct.at_mut(0);
112 module.vec_znx_big_normalize(log_base2k, c0, &buf_big, carry);
113 c0.add_normal(log_base2k, log_q, xe_source, sigma, (sigma * 6.0).ceil());
114}