arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/bin_fhe/bdd_arithmetic/key.rs
poulpy-schemes/src/bin_fhe/bdd_arithmetic/key.rsRaw
  1use crate::bin_fhe::bdd_arithmetic::FheUintPreparedDebug;
  2use crate::bin_fhe::circuit_bootstrapping::CircuitBootstrappingKeyInfos;
  3use crate::bin_fhe::{
  4    bdd_arithmetic::{FheUint, UnsignedInteger},
  5    blind_rotation::{BlindRotationAlgo, BlindRotationKey, BlindRotationKeyFactory},
  6    circuit_bootstrapping::{
  7        CircuitBootstrappingKey, CircuitBootstrappingKeyEncryptSk, CircuitBootstrappingKeyLayout,
  8        CircuitBootstrappingKeyPrepared, CircuitBootstrappingKeyPreparedFactory,
  9    },
 10};
 11
 12use poulpy_core::GLWESwitchingKeyEncryptSk;
 13use poulpy_core::layouts::{
 14    GGLWEInfos, GLWEAutomorphismKeyHelper, GLWEAutomorphismKeyPrepared, GLWESecret, GLWESwitchingKey, GLWESwitchingKeyLayout,
 15    GLWESwitchingKeyPrepared,
 16};
 17use poulpy_core::{
 18    GLWEToLWESwitchingKeyEncryptSk, GetDistribution, ScratchTakeCore,
 19    layouts::{
 20        GLWEInfos, GLWESecretToRef, GLWEToLWEKey, GLWEToLWEKeyLayout, GLWEToLWEKeyPreparedFactory, LWEInfos, LWESecretToRef,
 21        prepared::GLWEToLWEKeyPrepared,
 22    },
 23};
 24use poulpy_hal::{
 25    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
 26    source::Source,
 27};
 28
 29pub trait BDDKeyInfos {
 30    fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout;
 31    fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout;
 32    fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout>;
 33}
 34
 35#[derive(Debug, Clone, Copy)]
 36pub struct BDDKeyLayout {
 37    pub cbt: CircuitBootstrappingKeyLayout,
 38    pub ks_glwe: Option<GLWESwitchingKeyLayout>,
 39    pub ks_lwe: GLWEToLWEKeyLayout,
 40}
 41
 42impl BDDKeyInfos for BDDKeyLayout {
 43    fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
 44        self.cbt
 45    }
 46
 47    fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
 48        self.ks_glwe
 49    }
 50
 51    fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
 52        self.ks_lwe
 53    }
 54}
 55
 56pub struct BDDKey<D, BRA>
 57where
 58    D: Data,
 59    BRA: BlindRotationAlgo,
 60{
 61    pub(crate) cbt: CircuitBootstrappingKey<D, BRA>,
 62    pub(crate) ks_glwe: Option<GLWESwitchingKey<D>>,
 63    pub(crate) ks_lwe: GLWEToLWEKey<D>,
 64}
 65
 66impl<BRA: BlindRotationAlgo> BDDKey<Vec<u8>, BRA>
 67where
 68    BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
 69{
 70    pub fn alloc_from_infos<A>(infos: &A) -> Self
 71    where
 72        A: BDDKeyInfos,
 73    {
 74        Self {
 75            cbt: CircuitBootstrappingKey::alloc_from_infos(&infos.cbt_infos()),
 76            ks_glwe: infos
 77                .ks_glwe_infos()
 78                .as_ref()
 79                .map(GLWESwitchingKey::alloc_from_infos),
 80            ks_lwe: GLWEToLWEKey::alloc_from_infos(&infos.ks_lwe_infos()),
 81        }
 82    }
 83}
 84
 85pub trait BDDKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> {
 86    fn bdd_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
 87    where
 88        A: BDDKeyInfos;
 89
 90    fn bdd_key_encrypt_sk<D, S0, S1>(
 91        &self,
 92        res: &mut BDDKey<D, BRA>,
 93        sk_lwe: &S0,
 94        sk_glwe: &S1,
 95        source_xa: &mut Source,
 96        source_xe: &mut Source,
 97        scratch: &mut Scratch<BE>,
 98    ) where
 99        D: DataMut,
100        S0: LWESecretToRef + GetDistribution + LWEInfos,
101        S1: GLWESecretToRef + GetDistribution + GLWEInfos;
102}
103
104impl<BE: Backend, BRA: BlindRotationAlgo> BDDKeyEncryptSk<BRA, BE> for Module<BE>
105where
106    Self: CircuitBootstrappingKeyEncryptSk<BRA, BE> + GLWEToLWESwitchingKeyEncryptSk<BE> + GLWESwitchingKeyEncryptSk<BE>,
107    Scratch<BE>: ScratchTakeCore<BE>,
108{
109    fn bdd_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
110    where
111        A: BDDKeyInfos,
112    {
113        self.circuit_bootstrapping_key_encrypt_sk_tmp_bytes(&infos.cbt_infos())
114            .max(self.glwe_to_lwe_key_encrypt_sk_tmp_bytes(&infos.ks_lwe_infos()))
115    }
116
117    fn bdd_key_encrypt_sk<D, S0, S1>(
118        &self,
119        res: &mut BDDKey<D, BRA>,
120        sk_lwe: &S0,
121        sk_glwe: &S1,
122        source_xa: &mut Source,
123        source_xe: &mut Source,
124        scratch: &mut Scratch<BE>,
125    ) where
126        D: DataMut,
127        S0: LWESecretToRef + GetDistribution + LWEInfos,
128        S1: GLWESecretToRef + GetDistribution + GLWEInfos,
129    {
130        if let Some(key) = &mut res.ks_glwe {
131            let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(sk_glwe.n(), key.rank_out());
132            sk_out.fill_ternary_prob(0.5, source_xe);
133            key.encrypt_sk(self, sk_glwe, &sk_out, source_xa, source_xe, scratch);
134            res.ks_lwe
135                .encrypt_sk(self, sk_lwe, &sk_out, source_xa, source_xe, scratch);
136        } else {
137            res.ks_lwe
138                .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
139        }
140
141        res.cbt
142            .encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
143    }
144}
145
146impl<D: DataMut, BRA: BlindRotationAlgo> BDDKey<D, BRA> {
147    pub fn encrypt_sk<S0, S1, M, BE: Backend>(
148        &mut self,
149        module: &M,
150        sk_lwe: &S0,
151        sk_glwe: &S1,
152        source_xa: &mut Source,
153        source_xe: &mut Source,
154        scratch: &mut Scratch<BE>,
155    ) where
156        S0: LWESecretToRef + GetDistribution + LWEInfos,
157        S1: GLWESecretToRef + GetDistribution + GLWEInfos,
158        M: BDDKeyEncryptSk<BRA, BE>,
159        Scratch<BE>: ScratchTakeCore<BE>,
160    {
161        module.bdd_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
162    }
163}
164
165pub struct BDDKeyPrepared<D, BRA, BE>
166where
167    D: Data,
168    BRA: BlindRotationAlgo,
169    BE: Backend,
170{
171    pub(crate) cbt: CircuitBootstrappingKeyPrepared<D, BRA, BE>,
172    pub(crate) ks_glwe: Option<GLWESwitchingKeyPrepared<D, BE>>,
173    pub(crate) ks_lwe: GLWEToLWEKeyPrepared<D, BE>,
174}
175
176impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyInfos for BDDKeyPrepared<D, BRA, BE> {
177    fn cbt_infos(&self) -> CircuitBootstrappingKeyLayout {
178        CircuitBootstrappingKeyLayout {
179            layout_brk: self.cbt.brk_infos(),
180            layout_atk: self.cbt.atk_infos(),
181            layout_tsk: self.cbt.tsk_infos(),
182        }
183    }
184    fn ks_glwe_infos(&self) -> Option<GLWESwitchingKeyLayout> {
185        self.ks_glwe.as_ref().map(|ks_glwe| GLWESwitchingKeyLayout {
186            n: ks_glwe.n(),
187            base2k: ks_glwe.base2k(),
188            k: ks_glwe.k(),
189            rank_in: ks_glwe.rank_in(),
190            rank_out: ks_glwe.rank_out(),
191            dnum: ks_glwe.dnum(),
192            dsize: ks_glwe.dsize(),
193        })
194    }
195    fn ks_lwe_infos(&self) -> GLWEToLWEKeyLayout {
196        GLWEToLWEKeyLayout {
197            n: self.ks_lwe.n(),
198            base2k: self.ks_lwe.base2k(),
199            k: self.ks_lwe.k(),
200            rank_in: self.ks_lwe.rank_in(),
201            dnum: self.ks_lwe.dnum(),
202        }
203    }
204}
205
206impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> GLWEAutomorphismKeyHelper<GLWEAutomorphismKeyPrepared<D, BE>, BE>
207    for BDDKeyPrepared<D, BRA, BE>
208{
209    fn automorphism_key_infos(&self) -> poulpy_core::layouts::GGLWELayout {
210        self.cbt.automorphism_key_infos()
211    }
212
213    fn get_automorphism_key(&self, k: i64) -> Option<&GLWEAutomorphismKeyPrepared<D, BE>> {
214        self.cbt.get_automorphism_key(k)
215    }
216}
217
218pub trait BDDKeyPreparedFactory<BRA: BlindRotationAlgo, BE: Backend>
219where
220    Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWEKeyPreparedFactory<BE>,
221{
222    fn alloc_bdd_key_from_infos<A>(&self, infos: &A) -> BDDKeyPrepared<Vec<u8>, BRA, BE>
223    where
224        A: BDDKeyInfos,
225    {
226        let ks_glwe = if let Some(ks_glwe_infos) = &infos.ks_glwe_infos() {
227            Some(GLWESwitchingKeyPrepared::alloc_from_infos(
228                self,
229                ks_glwe_infos,
230            ))
231        } else {
232            None
233        };
234
235        BDDKeyPrepared {
236            cbt: CircuitBootstrappingKeyPrepared::alloc_from_infos(self, &infos.cbt_infos()),
237            ks_glwe,
238            ks_lwe: GLWEToLWEKeyPrepared::alloc_from_infos(self, &infos.ks_lwe_infos()),
239        }
240    }
241
242    fn prepare_bdd_key_tmp_bytes<A>(&self, infos: &A) -> usize
243    where
244        A: BDDKeyInfos,
245    {
246        self.circuit_bootstrapping_key_prepare_tmp_bytes(&infos.cbt_infos())
247            .max(self.prepare_glwe_to_lwe_key_tmp_bytes(&infos.ks_lwe_infos()))
248    }
249
250    fn prepare_bdd_key<DM, DR>(&self, res: &mut BDDKeyPrepared<DM, BRA, BE>, other: &BDDKey<DR, BRA>, scratch: &mut Scratch<BE>)
251    where
252        DM: DataMut,
253        DR: DataRef,
254        Scratch<BE>: ScratchTakeCore<BE>,
255    {
256        res.cbt.prepare(self, &other.cbt, scratch);
257
258        if let Some(key_prep) = &mut res.ks_glwe {
259            if let Some(other) = &other.ks_glwe {
260                key_prep.prepare(self, other, scratch);
261            } else {
262                panic!("incompatible keys: res has Some(ks_glwe) but other has none")
263            }
264        }
265
266        res.ks_lwe.prepare(self, &other.ks_lwe, scratch);
267    }
268}
269impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPreparedFactory<BRA, BE> for Module<BE> where
270    Self: Sized + CircuitBootstrappingKeyPreparedFactory<BRA, BE> + GLWEToLWEKeyPreparedFactory<BE>
271{
272}
273
274impl<BRA: BlindRotationAlgo, BE: Backend> BDDKeyPrepared<Vec<u8>, BRA, BE> {
275    pub fn alloc_from_infos<M, A>(module: &M, infos: &A) -> Self
276    where
277        M: BDDKeyPreparedFactory<BRA, BE>,
278        A: BDDKeyInfos,
279    {
280        module.alloc_bdd_key_from_infos(infos)
281    }
282}
283
284impl<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> BDDKeyHelper<D, BRA, BE> for BDDKeyPrepared<D, BRA, BE> {
285    fn get_cbt_key(
286        &self,
287    ) -> (
288        &CircuitBootstrappingKeyPrepared<D, BRA, BE>,
289        Option<&GLWESwitchingKeyPrepared<D, BE>>,
290        &GLWEToLWEKeyPrepared<D, BE>,
291    ) {
292        (&self.cbt, self.ks_glwe.as_ref(), &self.ks_lwe)
293    }
294}
295
296pub trait BDDKeyHelper<D: DataRef, BRA: BlindRotationAlgo, BE: Backend> {
297    #[allow(clippy::type_complexity)]
298    fn get_cbt_key(
299        &self,
300    ) -> (
301        &CircuitBootstrappingKeyPrepared<D, BRA, BE>,
302        Option<&GLWESwitchingKeyPrepared<D, BE>>,
303        &GLWEToLWEKeyPrepared<D, BE>,
304    );
305}
306
307pub trait FheUintPrepareDebug<BRA: BlindRotationAlgo, T: UnsignedInteger, BE: Backend> {
308    fn fhe_uint_debug_prepare<DM, DR0, DR1>(
309        &self,
310        res: &mut FheUintPreparedDebug<DM, T>,
311        bits: &FheUint<DR0, T>,
312        key: &BDDKeyPrepared<DR1, BRA, BE>,
313        scratch: &mut Scratch<BE>,
314    ) where
315        DM: DataMut,
316        DR0: DataRef,
317        DR1: DataRef;
318}