arnaucube
arnaucube/poulpyPublic Self-hosted repository
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}