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