arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/rlwe/src/encryption.rs
rlwe/src/encryption.rsRaw
  1use base2k::{
  2    AddNormal, Backend, FFT64, FillUniform, Module, ScalarZnxDftOps, ScalarZnxDftToRef, Scratch, VecZnx, VecZnxAlloc,
  3    VecZnxBigAlloc, VecZnxBigOps, VecZnxBigScratch, VecZnxDft, VecZnxDftAlloc, VecZnxDftOps, VecZnxDftToMut, VecZnxDftToRef,
  4    VecZnxToMut, VecZnxToRef, ZnxInfos,
  5};
  6
  7use sampling::source::Source;
  8
  9use crate::{
 10    elem::{CtVecZnx, CtVecZnxDft, PtVecZnx},
 11    keys::SecretKey,
 12};
 13
 14pub trait EncryptSk<B: Backend, D, P> {
 15    fn encrypt<S>(
 16        module: &Module<B>,
 17        res: &mut D,
 18        pt: Option<&P>,
 19        sk: &SecretKey<S>,
 20        source_xa: &mut Source,
 21        source_xe: &mut Source,
 22        scratch: &mut Scratch,
 23        sigma: f64,
 24        bound: f64,
 25    ) where
 26        S: ScalarZnxDftToRef<B>;
 27
 28    fn encrypt_tmp_bytes(module: &Module<B>, size: usize) -> usize {
 29        (module.vec_znx_big_normalize_tmp_bytes() | module.bytes_of_vec_znx_dft(1, size)) + module.bytes_of_vec_znx_big(1, size)
 30    }
 31}
 32
 33impl<C, P> EncryptSk<FFT64, CtVecZnx<C>, PtVecZnx<P>> for CtVecZnx<C>
 34where
 35    VecZnx<C>: VecZnxToMut + VecZnxToRef,
 36    VecZnx<P>: VecZnxToRef,
 37{
 38    fn encrypt<S>(
 39        module: &Module<FFT64>,
 40        ct: &mut CtVecZnx<C>,
 41        pt: Option<&PtVecZnx<P>>,
 42        sk: &SecretKey<S>,
 43        source_xa: &mut Source,
 44        source_xe: &mut Source,
 45        scratch: &mut Scratch,
 46        sigma: f64,
 47        bound: f64,
 48    ) where
 49        S: ScalarZnxDftToRef<FFT64>,
 50    {
 51        let log_base2k: usize = ct.log_base2k();
 52        let log_q: usize = ct.log_q();
 53        let mut ct_mut: VecZnx<&mut [u8]> = ct.data_mut().to_mut();
 54        let size: usize = ct_mut.size();
 55
 56        // c1 = a
 57        ct_mut.fill_uniform(log_base2k, 1, size, source_xa);
 58
 59        let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, size);
 60
 61        {
 62            let (mut c0_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, size);
 63            module.vec_znx_dft(&mut c0_dft, 0, &ct_mut, 1);
 64
 65            // c0_dft = DFT(a) * DFT(s)
 66            module.svp_apply_inplace(&mut c0_dft, 0, &sk.data().to_ref(), 0);
 67
 68            // c0_big = IDFT(c0_dft)
 69            module.vec_znx_idft_tmp_a(&mut c0_big, 0, &mut c0_dft, 0);
 70        }
 71
 72        // c0_big = m - c0_big
 73        if let Some(pt) = pt {
 74            module.vec_znx_big_sub_small_b_inplace(&mut c0_big, 0, &pt.data().to_ref(), 0);
 75        }
 76        // c0_big += e
 77        c0_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound);
 78
 79        // c0 = norm(c0_big = -as + m + e)
 80        module.vec_znx_big_normalize(log_base2k, &mut ct_mut, 0, &c0_big, 0, scratch_1);
 81    }
 82}
 83
 84pub trait EncryptZeroSk<B: Backend, D> {
 85    fn encrypt_zero<S>(
 86        module: &Module<B>,
 87        res: &mut D,
 88        sk: &SecretKey<S>,
 89        source_xa: &mut Source,
 90        source_xe: &mut Source,
 91        scratch: &mut Scratch,
 92        sigma: f64,
 93        bound: f64,
 94    ) where
 95        S: ScalarZnxDftToRef<B>;
 96
 97    fn encrypt_zero_tmp_bytes(module: &Module<B>, size: usize) -> usize {
 98        (module.bytes_of_vec_znx(1, size) | module.bytes_of_vec_znx_dft(1, size))
 99            + module.bytes_of_vec_znx_big(1, size)
100            + module.bytes_of_vec_znx(1, size)
101            + module.vec_znx_big_normalize_tmp_bytes()
102    }
103}
104
105impl<C> EncryptZeroSk<FFT64, CtVecZnxDft<C, FFT64>> for CtVecZnxDft<C, FFT64>
106where
107    VecZnxDft<C, FFT64>: VecZnxDftToMut<FFT64> + VecZnxDftToRef<FFT64>,
108{
109    fn encrypt_zero<S>(
110        module: &Module<FFT64>,
111        ct: &mut CtVecZnxDft<C, FFT64>,
112        sk: &SecretKey<S>,
113        source_xa: &mut Source,
114        source_xe: &mut Source,
115        scratch: &mut Scratch,
116        sigma: f64,
117        bound: f64,
118    ) where
119        S: ScalarZnxDftToRef<FFT64>,
120    {
121        let log_base2k: usize = ct.log_base2k();
122        let log_q: usize = ct.log_q();
123        let mut ct_mut: VecZnxDft<&mut [u8], FFT64> = ct.data_mut().to_mut();
124        let size: usize = ct_mut.size();
125
126        // ct[1] = DFT(a)
127        {
128            let (mut tmp_znx, _) = scratch.tmp_vec_znx(module, 1, size);
129            tmp_znx.fill_uniform(log_base2k, 1, size, source_xa);
130            module.vec_znx_dft(&mut ct_mut, 1, &tmp_znx, 0);
131        }
132
133        let (mut c0_big, scratch_1) = scratch.tmp_vec_znx_big(module, 1, size);
134
135        {
136            let (mut tmp_dft, _) = scratch_1.tmp_vec_znx_dft(module, 1, size);
137            // c0_dft = DFT(a) * DFT(s)
138            module.svp_apply(&mut tmp_dft, 0, &sk.data().to_ref(), 0, &ct_mut, 1);
139            // c0_big = IDFT(c0_dft)
140            module.vec_znx_idft_tmp_a(&mut c0_big, 0, &mut tmp_dft, 0);
141        }
142
143        // c0_big += e
144        c0_big.add_normal(log_base2k, 0, log_q, source_xe, sigma, bound);
145
146        // c0 = norm(c0_big = -as + e)
147        let (mut tmp_znx, scratch_2) = scratch_1.tmp_vec_znx(module, 1, size);
148        module.vec_znx_big_normalize(log_base2k, &mut tmp_znx, 0, &c0_big, 0, scratch_2);
149        // ct[0] = DFT(-as + e)
150        module.vec_znx_dft(&mut ct_mut, 0, &tmp_znx, 0);
151    }
152}