arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/blind_rotation/key.rs
core/src/blind_rotation/key.rsRaw
  1use backend::{Backend, FFT64, Module, ScalarZnx, ScalarZnxAlloc, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut};
  2use sampling::source::Source;
  3
  4use crate::{Distribution, FourierGLWESecret, GGSWCiphertext, Infos, LWESecret};
  5
  6pub struct BlindRotationKeyCGGI<B: Backend> {
  7    pub(crate) data: Vec<GGSWCiphertext<Vec<u8>, B>>,
  8    pub(crate) dist: Distribution,
  9}
 10
 11// pub struct BlindRotationKeyFHEW<B: Backend> {
 12//    pub(crate) data: Vec<GGSWCiphertext<Vec<u8>, B>>,
 13//    pub(crate) auto: Vec<GLWEAutomorphismKey<Vec<u8>, B>>,
 14//}
 15
 16impl BlindRotationKeyCGGI<FFT64> {
 17    pub fn allocate(module: &Module<FFT64>, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
 18        let mut data: Vec<GGSWCiphertext<Vec<u8>, FFT64>> = Vec::with_capacity(n_lwe);
 19        (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(module, basek, k, rows, 1, rank)));
 20        Self {
 21            data,
 22            dist: Distribution::NONE,
 23        }
 24    }
 25
 26    pub fn generate_from_sk_scratch_space(module: &Module<FFT64>, basek: usize, k: usize, rank: usize) -> usize {
 27        GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k, rank)
 28    }
 29
 30    pub fn generate_from_sk<DataSkGLWE, DataSkLWE>(
 31        &mut self,
 32        module: &Module<FFT64>,
 33        sk_glwe: &FourierGLWESecret<DataSkGLWE, FFT64>,
 34        sk_lwe: &LWESecret<DataSkLWE>,
 35        source_xa: &mut Source,
 36        source_xe: &mut Source,
 37        sigma: f64,
 38        scratch: &mut Scratch,
 39    ) where
 40        DataSkGLWE: AsRef<[u8]>,
 41        DataSkLWE: AsRef<[u8]>,
 42    {
 43        #[cfg(debug_assertions)]
 44        {
 45            assert_eq!(self.data.len(), sk_lwe.n());
 46            assert_eq!(sk_glwe.n(), module.n());
 47            assert_eq!(sk_glwe.rank(), self.data[0].rank());
 48            match sk_lwe.dist {
 49                Distribution::BinaryBlock(_)
 50                | Distribution::BinaryFixed(_)
 51                | Distribution::BinaryProb(_)
 52                | Distribution::ZERO => {}
 53                _ => panic!(
 54                    "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
 55                ),
 56            }
 57        }
 58
 59        self.dist = sk_lwe.dist;
 60
 61        let mut pt: ScalarZnx<Vec<u8>> = module.new_scalar_znx(1);
 62        let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data.to_ref();
 63
 64        self.data.iter_mut().enumerate().for_each(|(i, ggsw)| {
 65            pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
 66            ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, sigma, scratch);
 67        })
 68    }
 69
 70    pub(crate) fn block_size(&self) -> usize {
 71        match self.dist {
 72            Distribution::BinaryBlock(value) => value,
 73            _ => 1,
 74        }
 75    }
 76
 77    #[allow(dead_code)]
 78    pub(crate) fn n(&self) -> usize {
 79        self.data[0].n()
 80    }
 81
 82    #[allow(dead_code)]
 83    pub(crate) fn rows(&self) -> usize {
 84        self.data[0].rows()
 85    }
 86
 87    #[allow(dead_code)]
 88    pub(crate) fn k(&self) -> usize {
 89        self.data[0].k()
 90    }
 91
 92    #[allow(dead_code)]
 93    pub(crate) fn size(&self) -> usize {
 94        self.data[0].size()
 95    }
 96
 97    #[allow(dead_code)]
 98    pub(crate) fn rank(&self) -> usize {
 99        self.data[0].rank()
100    }
101
102    pub(crate) fn basek(&self) -> usize {
103        self.data[0].basek()
104    }
105}