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