arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/rlwe/src/encryptor.rs
rlwe/src/encryptor.rsRaw
  1use crate::ciphertext::Ciphertext;
  2use crate::elem::{Elem, ElemCommon, ElemVecZnx};
  3use crate::keys::SecretKey;
  4use crate::parameters::Parameters;
  5use crate::plaintext::Plaintext;
  6use base2k::sampling::Sampling;
  7use base2k::{
  8    Infos, Module, Scalar, SvpPPol, SvpPPolOps, VecZnx, VecZnxBig, VecZnxBigOps, VecZnxDft,
  9    VecZnxDftOps, VecZnxOps, VmpPMat, VmpPMatOps,
 10};
 11
 12use sampling::source::{Source, new_seed};
 13
 14impl Parameters {
 15    pub fn encrypt_rlwe_sk_tmp_bytes(&self, log_q: usize) -> usize {
 16        encrypt_rlwe_sk_tmp_bytes(self.module(), self.log_base2k(), log_q)
 17    }
 18    pub fn encrypt_rlwe_sk(
 19        &self,
 20        ct: &mut Ciphertext<VecZnx>,
 21        pt: Option<&Plaintext>,
 22        sk: &SvpPPol,
 23        source_xa: &mut Source,
 24        source_xe: &mut Source,
 25        tmp_bytes: &mut [u8],
 26    ) {
 27        encrypt_rlwe_sk(
 28            self.module(),
 29            &mut ct.0,
 30            pt.map(|pt| pt.at(0)),
 31            sk,
 32            source_xa,
 33            source_xe,
 34            self.xe(),
 35            tmp_bytes,
 36        )
 37    }
 38}
 39
 40pub struct EncryptorSk {
 41    sk: SvpPPol,
 42    source_xa: Source,
 43    source_xe: Source,
 44    initialized: bool,
 45    tmp_bytes: Vec<u8>,
 46}
 47
 48impl EncryptorSk {
 49    pub fn new(params: &Parameters, sk: Option<&SecretKey>) -> Self {
 50        let mut sk_svp_ppol: SvpPPol = params.module().new_svp_ppol();
 51        let mut initialized: bool = false;
 52        if let Some(sk) = sk {
 53            sk.prepare(params.module(), &mut sk_svp_ppol);
 54            initialized = true;
 55        }
 56        Self {
 57            sk: sk_svp_ppol,
 58            initialized,
 59            source_xa: Source::new(new_seed()),
 60            source_xe: Source::new(new_seed()),
 61            tmp_bytes: vec![0u8; params.encrypt_rlwe_sk_tmp_bytes(params.cols_qp())],
 62        }
 63    }
 64
 65    pub fn set_sk(&mut self, module: &Module, sk: &SecretKey) {
 66        sk.prepare(module, &mut self.sk);
 67        self.initialized = true;
 68    }
 69
 70    pub fn seed_source_xa(&mut self, seed: [u8; 32]) {
 71        self.source_xa = Source::new(seed)
 72    }
 73
 74    pub fn seed_source_xe(&mut self, seed: [u8; 32]) {
 75        self.source_xe = Source::new(seed)
 76    }
 77
 78    pub fn encrypt_rlwe_sk(
 79        &mut self,
 80        params: &Parameters,
 81        ct: &mut Ciphertext<VecZnx>,
 82        pt: Option<&Plaintext>,
 83    ) {
 84        assert!(
 85            self.initialized == true,
 86            "invalid call to [EncryptorSk.encrypt_rlwe_sk]: [EncryptorSk] has not been initialized with a [SecretKey]"
 87        );
 88        params.encrypt_rlwe_sk(
 89            ct,
 90            pt,
 91            &self.sk,
 92            &mut self.source_xa,
 93            &mut self.source_xe,
 94            &mut self.tmp_bytes,
 95        );
 96    }
 97
 98    pub fn encrypt_rlwe_sk_core(
 99        &self,
100        params: &Parameters,
101        ct: &mut Ciphertext<VecZnx>,
102        pt: Option<&Plaintext>,
103        source_xa: &mut Source,
104        source_xe: &mut Source,
105        tmp_bytes: &mut [u8],
106    ) {
107        assert!(
108            self.initialized == true,
109            "invalid call to [EncryptorSk.encrypt_rlwe_sk]: [EncryptorSk] has not been initialized with a [SecretKey]"
110        );
111        params.encrypt_rlwe_sk(ct, pt, &self.sk, source_xa, source_xe, tmp_bytes);
112    }
113}
114
115pub fn encrypt_rlwe_sk_tmp_bytes(module: &Module, log_base2k: usize, log_q: usize) -> usize {
116    module.bytes_of_vec_znx_dft((log_q + log_base2k - 1) / log_base2k)
117        + module.vec_znx_big_normalize_tmp_bytes()
118}
119pub fn encrypt_rlwe_sk(
120    module: &Module,
121    ct: &mut Elem<VecZnx>,
122    pt: Option<&VecZnx>,
123    sk: &SvpPPol,
124    source_xa: &mut Source,
125    source_xe: &mut Source,
126    sigma: f64,
127    tmp_bytes: &mut [u8],
128) {
129    encrypt_rlwe_sk_core::<0>(module, ct, pt, sk, source_xa, source_xe, sigma, tmp_bytes)
130}
131
132fn encrypt_rlwe_sk_core<const PT_POS: u8>(
133    module: &Module,
134    ct: &mut Elem<VecZnx>,
135    pt: Option<&VecZnx>,
136    sk: &SvpPPol,
137    source_xa: &mut Source,
138    source_xe: &mut Source,
139    sigma: f64,
140    tmp_bytes: &mut [u8],
141) {
142    let cols: usize = ct.cols();
143    let log_base2k: usize = ct.log_base2k();
144    let log_q: usize = ct.log_q();
145
146    assert!(
147        tmp_bytes.len() >= encrypt_rlwe_sk_tmp_bytes(module, log_base2k, log_q),
148        "invalid tmp_bytes: tmp_bytes={} < encrypt_rlwe_sk_tmp_bytes={}",
149        tmp_bytes.len(),
150        encrypt_rlwe_sk_tmp_bytes(module, log_base2k, log_q)
151    );
152
153    let log_q: usize = ct.log_q();
154    let log_base2k: usize = ct.log_base2k();
155    let c1: &mut VecZnx = ct.at_mut(1);
156
157    // c1 <- Z_{2^prec}[X]/(X^{N}+1)
158    module.fill_uniform(log_base2k, c1, cols, source_xa);
159
160    let (tmp_bytes_vec_znx_dft, tmp_bytes_normalize) =
161        tmp_bytes.split_at_mut(module.bytes_of_vec_znx_dft(cols));
162
163    // Scratch space for DFT values
164    let mut buf_dft: VecZnxDft = VecZnxDft::from_bytes_borrow(module, cols, tmp_bytes_vec_znx_dft);
165
166    // Applies buf_dft <- DFT(s) * DFT(c1)
167    module.svp_apply_dft(&mut buf_dft, sk, c1);
168
169    // Alias scratch space
170    let mut buf_big: VecZnxBig = buf_dft.as_vec_znx_big();
171
172    // buf_big = s x c1
173    module.vec_znx_idft_tmp_a(&mut buf_big, &mut buf_dft);
174
175    match PT_POS {
176        // c0 <- -s x c1 + m
177        0 => {
178            let c0: &mut VecZnx = ct.at_mut(0);
179            if let Some(pt) = pt {
180                module.vec_znx_big_sub_small_a_inplace(&mut buf_big, pt);
181                module.vec_znx_big_normalize(log_base2k, c0, &buf_big, tmp_bytes_normalize);
182            } else {
183                module.vec_znx_big_normalize(log_base2k, c0, &buf_big, tmp_bytes_normalize);
184                module.vec_znx_negate_inplace(c0);
185            }
186        }
187        // c1 <- c1 + m
188        1 => {
189            if let Some(pt) = pt {
190                module.vec_znx_add_inplace(c1, pt);
191                c1.normalize(log_base2k, tmp_bytes_normalize);
192            }
193            let c0: &mut VecZnx = ct.at_mut(0);
194            module.vec_znx_big_normalize(log_base2k, c0, &buf_big, tmp_bytes_normalize);
195            module.vec_znx_negate_inplace(c0);
196        }
197        _ => panic!("PT_POS must be 1 or 2"),
198    }
199
200    // c0 <- -s x c1 + m + e
201    module.add_normal(
202        log_base2k,
203        ct.at_mut(0),
204        log_q,
205        source_xe,
206        sigma,
207        (sigma * 6.0).ceil(),
208    );
209}
210
211impl Parameters {
212    pub fn encrypt_grlwe_sk_tmp_bytes(&self, rows: usize, log_q: usize) -> usize {
213        encrypt_grlwe_sk_tmp_bytes(self.module(), self.log_base2k(), rows, log_q)
214    }
215}
216
217pub fn encrypt_grlwe_sk_tmp_bytes(
218    module: &Module,
219    log_base2k: usize,
220    rows: usize,
221    log_q: usize,
222) -> usize {
223    let cols = (log_q + log_base2k - 1) / log_base2k;
224    Elem::<VecZnx>::bytes_of(module, log_base2k, log_q, 2)
225        + Plaintext::bytes_of(module, log_base2k, log_q)
226        + encrypt_rlwe_sk_tmp_bytes(module, log_base2k, log_q)
227        + module.vmp_prepare_tmp_bytes(rows, cols)
228}
229
230pub fn encrypt_grlwe_sk(
231    module: &Module,
232    ct: &mut Ciphertext<VmpPMat>,
233    m: &Scalar,
234    sk: &SvpPPol,
235    source_xa: &mut Source,
236    source_xe: &mut Source,
237    sigma: f64,
238    tmp_bytes: &mut [u8],
239) {
240    let log_q: usize = ct.log_q();
241    let log_base2k: usize = ct.log_base2k();
242    let (left, right) = ct.0.value.split_at_mut(1);
243    encrypt_grlwe_sk_core::<0>(
244        module,
245        log_base2k,
246        [&mut left[0], &mut right[0]],
247        log_q,
248        m,
249        sk,
250        source_xa,
251        source_xe,
252        sigma,
253        tmp_bytes,
254    )
255}
256
257impl Parameters {
258    pub fn encrypt_rgsw_sk_tmp_bytes(&self, rows: usize, log_q: usize) -> usize {
259        encrypt_rgsw_sk_tmp_bytes(self.module(), self.log_base2k(), rows, log_q)
260    }
261}
262
263pub fn encrypt_rgsw_sk_tmp_bytes(
264    module: &Module,
265    log_base2k: usize,
266    rows: usize,
267    log_q: usize,
268) -> usize {
269    let cols = (log_q + log_base2k - 1) / log_base2k;
270    Elem::<VecZnx>::bytes_of(module, log_base2k, log_q, 2)
271        + Plaintext::bytes_of(module, log_base2k, log_q)
272        + encrypt_rlwe_sk_tmp_bytes(module, log_base2k, log_q)
273        + module.vmp_prepare_tmp_bytes(rows, cols)
274}
275
276pub fn encrypt_rgsw_sk(
277    module: &Module,
278    ct: &mut Ciphertext<VmpPMat>,
279    m: &Scalar,
280    sk: &SvpPPol,
281    source_xa: &mut Source,
282    source_xe: &mut Source,
283    sigma: f64,
284    tmp_bytes: &mut [u8],
285) {
286    let log_q: usize = ct.log_q();
287    let log_base2k: usize = ct.log_base2k();
288
289    let (left, right) = ct.0.value.split_at_mut(2);
290    let (ll, lr) = left.split_at_mut(1);
291    let (rl, rr) = right.split_at_mut(1);
292
293    encrypt_grlwe_sk_core::<0>(
294        module,
295        log_base2k,
296        [&mut ll[0], &mut lr[0]],
297        log_q,
298        m,
299        sk,
300        source_xa,
301        source_xe,
302        sigma,
303        tmp_bytes,
304    );
305    encrypt_grlwe_sk_core::<1>(
306        module,
307        log_base2k,
308        [&mut rl[0], &mut rr[0]],
309        log_q,
310        m,
311        sk,
312        source_xa,
313        source_xe,
314        sigma,
315        tmp_bytes,
316    );
317}
318
319fn encrypt_grlwe_sk_core<const PT_POS: u8>(
320    module: &Module,
321    log_base2k: usize,
322    mut ct: [&mut VmpPMat; 2],
323    log_q: usize,
324    m: &Scalar,
325    sk: &SvpPPol,
326    source_xa: &mut Source,
327    source_xe: &mut Source,
328    sigma: f64,
329    tmp_bytes: &mut [u8],
330) {
331    let rows: usize = ct[0].rows();
332
333    let min_tmp_bytes_len = encrypt_grlwe_sk_tmp_bytes(module, log_base2k, rows, log_q);
334
335    assert!(
336        tmp_bytes.len() >= min_tmp_bytes_len,
337        "invalid tmp_bytes: tmp_bytes.len()={} < encrypt_grlwe_sk_tmp_bytes={}",
338        tmp_bytes.len(),
339        min_tmp_bytes_len
340    );
341
342    let bytes_of_elem: usize = Elem::<VecZnx>::bytes_of(module, log_base2k, log_q, 2);
343    let bytes_of_pt: usize = Plaintext::bytes_of(module, log_base2k, log_q);
344    let bytes_of_enc_sk: usize = encrypt_rlwe_sk_tmp_bytes(module, log_base2k, log_q);
345
346    let (tmp_bytes_pt, tmp_bytes) = tmp_bytes.split_at_mut(bytes_of_pt);
347    let (tmp_bytes_enc_sk, tmp_bytes) = tmp_bytes.split_at_mut(bytes_of_enc_sk);
348    let (tmp_bytes_elem, tmp_bytes_vmp_prepare_row) = tmp_bytes.split_at_mut(bytes_of_elem);
349
350    let mut tmp_elem: Elem<VecZnx> =
351        Elem::<VecZnx>::from_bytes_borrow(module, log_base2k, log_q, 2, tmp_bytes_elem);
352    let mut tmp_pt: Plaintext =
353        Plaintext::from_bytes_borrow(module, log_base2k, log_q, tmp_bytes_pt);
354
355    (0..rows).for_each(|row_i| {
356        // Sets the i-th row of the RLWE sample to m (i.e. m * 2^{-log_base2k*i})
357        tmp_pt.at_mut(0).at_mut(row_i).copy_from_slice(&m.raw());
358
359        // Encrypts RLWE(m * 2^{-log_base2k*i})
360        encrypt_rlwe_sk_core::<PT_POS>(
361            module,
362            &mut tmp_elem,
363            Some(tmp_pt.at(0)),
364            sk,
365            source_xa,
366            source_xe,
367            sigma,
368            tmp_bytes_enc_sk,
369        );
370
371        // Zeroes the ith-row of tmp_pt
372        tmp_pt.at_mut(0).at_mut(row_i).fill(0);
373
374        // GRLWE[row_i][0||1] = [-as + m * 2^{-i*log_base2k} + e*2^{-log_q} || a]
375        module.vmp_prepare_row(
376            ct[0],
377            tmp_elem.at(0).raw(),
378            row_i,
379            tmp_bytes_vmp_prepare_row,
380        );
381        module.vmp_prepare_row(
382            &mut ct[1],
383            tmp_elem.at(1).raw(),
384            row_i,
385            tmp_bytes_vmp_prepare_row,
386        );
387    });
388}