arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rs
poulpy-schemes/src/tfhe/circuit_bootstrapping/key.rsRaw
  1use poulpy_core::{
  2    Distribution, GGLWEToGGSWKeyEncryptSk, GLWEAutomorphismKeyEncryptSk, GetDistribution, ScratchTakeCore,
  3    layouts::{
  4        GGLWEInfos, GGLWEToGGSWKey, GGLWEToGGSWKeyLayout, GGSWInfos, GLWEAutomorphismKey, GLWEAutomorphismKeyLayout, GLWEInfos,
  5        GLWESecretPreparedFactory, GLWESecretToRef, LWEInfos, LWESecretToRef, prepared::GLWESecretPrepared,
  6    },
  7    trace_galois_elements,
  8};
  9use std::collections::HashMap;
 10
 11use poulpy_hal::{
 12    layouts::{Backend, Data, DataMut, DataRef, Module, Scratch},
 13    source::Source,
 14};
 15
 16use crate::tfhe::blind_rotation::{
 17    BlindRotationAlgo, BlindRotationKey, BlindRotationKeyEncryptSk, BlindRotationKeyFactory, BlindRotationKeyInfos,
 18    BlindRotationKeyLayout,
 19};
 20
 21pub trait CircuitBootstrappingKeyInfos {
 22    fn block_size(&self) -> usize;
 23    fn brk_infos(&self) -> BlindRotationKeyLayout;
 24    fn atk_infos(&self) -> GLWEAutomorphismKeyLayout;
 25    fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout;
 26}
 27
 28#[derive(Debug, Clone, Copy)]
 29pub struct CircuitBootstrappingKeyLayout {
 30    pub layout_brk: BlindRotationKeyLayout,
 31    pub layout_atk: GLWEAutomorphismKeyLayout,
 32    pub layout_tsk: GGLWEToGGSWKeyLayout,
 33}
 34
 35impl CircuitBootstrappingKeyInfos for CircuitBootstrappingKeyLayout {
 36    fn block_size(&self) -> usize {
 37        unimplemented!("unimplemented for CircuitBootstrappingKeyLayout")
 38    }
 39
 40    fn atk_infos(&self) -> GLWEAutomorphismKeyLayout {
 41        self.layout_atk
 42    }
 43
 44    fn brk_infos(&self) -> BlindRotationKeyLayout {
 45        self.layout_brk
 46    }
 47
 48    fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
 49        self.layout_tsk
 50    }
 51}
 52
 53pub trait CircuitBootstrappingKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> {
 54    #[allow(clippy::too_many_arguments)]
 55    fn circuit_bootstrapping_key_encrypt_sk<D, S0, S1>(
 56        &self,
 57        res: &mut CircuitBootstrappingKey<D, BRA>,
 58        sk_lwe: &S0,
 59        sk_glwe: &S1,
 60        source_xa: &mut Source,
 61        source_xe: &mut Source,
 62        scratch: &mut Scratch<BE>,
 63    ) where
 64        D: DataMut,
 65        S0: LWESecretToRef + GetDistribution + LWEInfos,
 66        S1: GLWESecretToRef + GLWEInfos + GetDistribution;
 67}
 68
 69impl<BRA: BlindRotationAlgo> CircuitBootstrappingKey<Vec<u8>, BRA> {
 70    pub fn alloc_from_infos<A>(infos: &A) -> Self
 71    where
 72        A: CircuitBootstrappingKeyInfos,
 73        BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
 74    {
 75        let atk_infos: &GLWEAutomorphismKeyLayout = &infos.atk_infos();
 76        let brk_infos: &BlindRotationKeyLayout = &infos.brk_infos();
 77        let trk_infos: &GGLWEToGGSWKeyLayout = &infos.tsk_infos();
 78        let gal_els: Vec<i64> = trace_galois_elements(atk_infos.log_n(), 2 * atk_infos.n().as_usize() as i64);
 79
 80        Self {
 81            brk: <BlindRotationKey<Vec<u8>, BRA> as BlindRotationKeyFactory<BRA>>::blind_rotation_key_alloc(brk_infos),
 82            atk: gal_els
 83                .iter()
 84                .map(|&gal_el| {
 85                    let key = GLWEAutomorphismKey::alloc_from_infos(atk_infos);
 86                    (gal_el, key)
 87                })
 88                .collect(),
 89            tsk: GGLWEToGGSWKey::alloc_from_infos(trk_infos),
 90        }
 91    }
 92}
 93
 94pub struct CircuitBootstrappingKey<D: Data, BRA: BlindRotationAlgo> {
 95    pub(crate) brk: BlindRotationKey<D, BRA>,
 96    pub(crate) tsk: GGLWEToGGSWKey<Vec<u8>>,
 97    pub(crate) atk: HashMap<i64, GLWEAutomorphismKey<Vec<u8>>>,
 98}
 99
100impl<D: DataMut, BRA: BlindRotationAlgo> CircuitBootstrappingKey<D, BRA> {
101    pub fn encrypt_sk<M, S0, S1, BE: Backend>(
102        &mut self,
103        module: &M,
104        sk_lwe: &S0,
105        sk_glwe: &S1,
106        source_xa: &mut Source,
107        source_xe: &mut Source,
108        scratch: &mut Scratch<BE>,
109    ) where
110        S0: LWESecretToRef + GetDistribution + LWEInfos,
111        S1: GLWESecretToRef + GLWEInfos + GetDistribution,
112        M: CircuitBootstrappingKeyEncryptSk<BRA, BE>,
113    {
114        module.circuit_bootstrapping_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
115    }
116}
117
118impl<BRA: BlindRotationAlgo, BE: Backend> CircuitBootstrappingKeyEncryptSk<BRA, BE> for Module<BE>
119where
120    Self: GGLWEToGGSWKeyEncryptSk<BE>
121        + BlindRotationKeyEncryptSk<BRA, BE>
122        + GLWEAutomorphismKeyEncryptSk<BE>
123        + GLWESecretPreparedFactory<BE>,
124    Scratch<BE>: ScratchTakeCore<BE>,
125{
126    fn circuit_bootstrapping_key_encrypt_sk<D, S0, S1>(
127        &self,
128        res: &mut CircuitBootstrappingKey<D, BRA>,
129        sk_lwe: &S0,
130        sk_glwe: &S1,
131        source_xa: &mut Source,
132        source_xe: &mut Source,
133        scratch: &mut Scratch<BE>,
134    ) where
135        D: DataMut,
136        S0: LWESecretToRef + GetDistribution + LWEInfos,
137        S1: GLWESecretToRef + GLWEInfos + GetDistribution,
138    {
139        let brk_infos: &BlindRotationKeyLayout = &res.brk_infos();
140        let atk_infos: &GLWEAutomorphismKeyLayout = &res.atk_infos();
141        let tsk_infos: &GGLWEToGGSWKeyLayout = &res.tsk_infos();
142
143        assert_eq!(sk_lwe.n(), brk_infos.n_lwe());
144        assert_eq!(sk_glwe.n(), brk_infos.n_glwe());
145        assert_eq!(sk_glwe.n(), atk_infos.n());
146        assert_eq!(sk_glwe.n(), tsk_infos.n());
147
148        assert!(sk_glwe.dist() != &Distribution::NONE);
149
150        for (p, atk) in res.atk.iter_mut() {
151            atk.encrypt_sk(self, *p, sk_glwe, source_xa, source_xe, scratch);
152        }
153
154        let mut sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(self, brk_infos.rank());
155        sk_glwe_prepared.prepare(self, sk_glwe);
156
157        res.brk.encrypt_sk(
158            self,
159            &sk_glwe_prepared,
160            sk_lwe,
161            source_xa,
162            source_xe,
163            scratch,
164        );
165
166        res.tsk
167            .encrypt_sk(self, sk_glwe, source_xa, source_xe, scratch);
168    }
169}
170
171impl<D: DataRef, BRA: BlindRotationAlgo> CircuitBootstrappingKeyInfos for CircuitBootstrappingKey<D, BRA> {
172    fn block_size(&self) -> usize {
173        self.brk.block_size()
174    }
175
176    fn atk_infos(&self) -> GLWEAutomorphismKeyLayout {
177        let (_, atk) = self.atk.iter().next().expect("atk is empty");
178        GLWEAutomorphismKeyLayout {
179            n: atk.n(),
180            base2k: atk.base2k(),
181            k: atk.k(),
182            dnum: atk.dnum(),
183            dsize: atk.dsize(),
184            rank: atk.rank(),
185        }
186    }
187
188    fn brk_infos(&self) -> BlindRotationKeyLayout {
189        BlindRotationKeyLayout {
190            n_glwe: self.brk.n_glwe(),
191            n_lwe: self.brk.n_lwe(),
192            base2k: self.brk.base2k(),
193            k: self.brk.k(),
194            dnum: self.brk.dnum(),
195            rank: self.brk.rank(),
196        }
197    }
198
199    fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
200        GGLWEToGGSWKeyLayout {
201            n: self.tsk.n(),
202            base2k: self.tsk.base2k(),
203            k: self.tsk.k(),
204            dnum: self.tsk.dnum(),
205            dsize: self.tsk.dsize(),
206            rank: self.tsk.rank(),
207        }
208    }
209}