arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/blind_rotation/cggi_key.rs
poulpy-schemes/src/tfhe/blind_rotation/cggi_key.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        DFT, IDFTConsume, ScratchAvailable, SvpApplyInplace, TakeVecZnx, TakeVecZnxDft, VecZnxAddInplace, VecZnxAddNormal,
  4        VecZnxAddScalarInplace, VecZnxBigNormalize, VecZnxDftAllocBytes, VecZnxFillUniform, VecZnxNormalize,
  5        VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubABInplace, VmpPMatAlloc, VmpPrepare,
  6    },
  7    layouts::{Backend, DataMut, DataRef, Module, ScalarZnx, ScalarZnxToRef, Scratch, ZnxView, ZnxViewMut},
  8    source::Source,
  9};
 10
 11use std::marker::PhantomData;
 12
 13use poulpy_core::{
 14    Distribution,
 15    layouts::{
 16        GGSWCiphertext, LWESecret,
 17        compressed::GGSWCiphertextCompressed,
 18        prepared::{GGSWCiphertextPrepared, GLWESecretPrepared},
 19    },
 20};
 21
 22use crate::tfhe::blind_rotation::{
 23    BlindRotationKey, BlindRotationKeyAlloc, BlindRotationKeyCompressed, BlindRotationKeyEncryptSk, BlindRotationKeyPrepared,
 24    BlindRotationKeyPreparedAlloc, CGGI,
 25};
 26
 27impl BlindRotationKeyAlloc for BlindRotationKey<Vec<u8>, CGGI> {
 28    fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
 29        let mut data: Vec<GGSWCiphertext<Vec<u8>>> = Vec::with_capacity(n_lwe);
 30        (0..n_lwe).for_each(|_| data.push(GGSWCiphertext::alloc(n_gglwe, basek, k, rows, 1, rank)));
 31        Self {
 32            keys: data,
 33            dist: Distribution::NONE,
 34            _phantom: PhantomData,
 35        }
 36    }
 37}
 38
 39impl BlindRotationKey<Vec<u8>, CGGI> {
 40    pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
 41    where
 42        Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes,
 43    {
 44        GGSWCiphertext::encrypt_sk_scratch_space(module, basek, k, rank)
 45    }
 46}
 47
 48impl<D: DataMut, B: Backend> BlindRotationKeyEncryptSk<B> for BlindRotationKey<D, CGGI>
 49where
 50    Module<B>: VecZnxAddScalarInplace
 51        + VecZnxDftAllocBytes
 52        + VecZnxBigNormalize<B>
 53        + DFT<B>
 54        + SvpApplyInplace<B>
 55        + IDFTConsume<B>
 56        + VecZnxNormalizeTmpBytes
 57        + VecZnxFillUniform
 58        + VecZnxSubABInplace
 59        + VecZnxAddInplace
 60        + VecZnxNormalizeInplace<B>
 61        + VecZnxAddNormal
 62        + VecZnxNormalize<B>
 63        + VecZnxSub,
 64    Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
 65{
 66    fn encrypt_sk<DataSkGLWE, DataSkLWE>(
 67        &mut self,
 68        module: &Module<B>,
 69        sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
 70        sk_lwe: &LWESecret<DataSkLWE>,
 71        source_xa: &mut Source,
 72        source_xe: &mut Source,
 73        scratch: &mut Scratch<B>,
 74    ) where
 75        DataSkGLWE: DataRef,
 76        DataSkLWE: DataRef,
 77    {
 78        #[cfg(debug_assertions)]
 79        {
 80            assert_eq!(self.keys.len(), sk_lwe.n());
 81            assert!(sk_glwe.n() <= module.n());
 82            assert_eq!(sk_glwe.rank(), self.keys[0].rank());
 83            match sk_lwe.dist() {
 84                Distribution::BinaryBlock(_)
 85                | Distribution::BinaryFixed(_)
 86                | Distribution::BinaryProb(_)
 87                | Distribution::ZERO => {}
 88                _ => panic!(
 89                    "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
 90                ),
 91            }
 92        }
 93
 94        self.dist = sk_lwe.dist();
 95
 96        let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
 97        let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
 98
 99        self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
100            pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
101            ggsw.encrypt_sk(module, &pt, sk_glwe, source_xa, source_xe, scratch);
102        });
103    }
104}
105
106impl<B: Backend> BlindRotationKeyPreparedAlloc<B> for BlindRotationKeyPrepared<Vec<u8>, CGGI, B>
107where
108    Module<B>: VmpPMatAlloc<B> + VmpPrepare<B>,
109{
110    fn alloc(module: &Module<B>, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
111        let mut data: Vec<GGSWCiphertextPrepared<Vec<u8>, B>> = Vec::with_capacity(n_lwe);
112        (0..n_lwe).for_each(|_| {
113            data.push(GGSWCiphertextPrepared::alloc(
114                module, basek, k, rows, 1, rank,
115            ))
116        });
117        Self {
118            data,
119            dist: Distribution::NONE,
120            x_pow_a: None,
121            _phantom: PhantomData,
122        }
123    }
124}
125
126impl BlindRotationKeyCompressed<Vec<u8>, CGGI> {
127    pub fn alloc(n_gglwe: usize, n_lwe: usize, basek: usize, k: usize, rows: usize, rank: usize) -> Self {
128        let mut data: Vec<GGSWCiphertextCompressed<Vec<u8>>> = Vec::with_capacity(n_lwe);
129        (0..n_lwe).for_each(|_| {
130            data.push(GGSWCiphertextCompressed::alloc(
131                n_gglwe, basek, k, rows, 1, rank,
132            ))
133        });
134        Self {
135            keys: data,
136            dist: Distribution::NONE,
137            _phantom: PhantomData,
138        }
139    }
140
141    pub fn generate_from_sk_scratch_space<B: Backend>(module: &Module<B>, basek: usize, k: usize, rank: usize) -> usize
142    where
143        Module<B>: VecZnxNormalizeTmpBytes + VecZnxDftAllocBytes,
144    {
145        GGSWCiphertextCompressed::encrypt_sk_scratch_space(module, basek, k, rank)
146    }
147}
148
149impl<D: DataMut> BlindRotationKeyCompressed<D, CGGI> {
150    #[allow(clippy::too_many_arguments)]
151    pub fn encrypt_sk<DataSkGLWE, DataSkLWE, B: Backend>(
152        &mut self,
153        module: &Module<B>,
154        sk_glwe: &GLWESecretPrepared<DataSkGLWE, B>,
155        sk_lwe: &LWESecret<DataSkLWE>,
156        seed_xa: [u8; 32],
157        source_xe: &mut Source,
158        scratch: &mut Scratch<B>,
159    ) where
160        DataSkGLWE: DataRef,
161        DataSkLWE: DataRef,
162        Module<B>: VecZnxAddScalarInplace
163            + VecZnxDftAllocBytes
164            + VecZnxBigNormalize<B>
165            + DFT<B>
166            + SvpApplyInplace<B>
167            + IDFTConsume<B>
168            + VecZnxNormalizeTmpBytes
169            + VecZnxFillUniform
170            + VecZnxSubABInplace
171            + VecZnxAddInplace
172            + VecZnxNormalizeInplace<B>
173            + VecZnxAddNormal
174            + VecZnxNormalize<B>
175            + VecZnxSub,
176        Scratch<B>: TakeVecZnxDft<B> + ScratchAvailable + TakeVecZnx,
177    {
178        #[cfg(debug_assertions)]
179        {
180            assert_eq!(self.keys.len(), sk_lwe.n());
181            assert!(sk_glwe.n() <= module.n());
182            assert_eq!(sk_glwe.rank(), self.keys[0].rank());
183            match sk_lwe.dist() {
184                Distribution::BinaryBlock(_)
185                | Distribution::BinaryFixed(_)
186                | Distribution::BinaryProb(_)
187                | Distribution::ZERO => {}
188                _ => panic!(
189                    "invalid GLWESecret distribution: must be BinaryBlock, BinaryFixed or BinaryProb (or ZERO for debugging)"
190                ),
191            }
192        }
193
194        self.dist = sk_lwe.dist();
195
196        let mut pt: ScalarZnx<Vec<u8>> = ScalarZnx::alloc(sk_glwe.n(), 1);
197        let sk_ref: ScalarZnx<&[u8]> = sk_lwe.data().to_ref();
198
199        let mut source_xa: Source = Source::new(seed_xa);
200
201        self.keys.iter_mut().enumerate().for_each(|(i, ggsw)| {
202            pt.at_mut(0, 0)[0] = sk_ref.at(0, 0)[i];
203            ggsw.encrypt_sk(
204                module,
205                &pt,
206                sk_glwe,
207                source_xa.new_seed(),
208                source_xe,
209                scratch,
210            );
211        });
212    }
213}