poulpy/poulpy-schemes/src/bin_fhe/circuit_bootstrapping/key.rs
poulpy-schemes/src/bin_fhe/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::bin_fhe::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 brk_layout: BlindRotationKeyLayout,
31 pub atk_layout: GLWEAutomorphismKeyLayout,
32 pub tsk_layout: 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.atk_layout
42 }
43
44 fn brk_infos(&self) -> BlindRotationKeyLayout {
45 self.brk_layout
46 }
47
48 fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
49 self.tsk_layout
50 }
51}
52
53pub trait CircuitBootstrappingKeyEncryptSk<BRA: BlindRotationAlgo, BE: Backend> {
54 fn circuit_bootstrapping_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
55 where
56 A: CircuitBootstrappingKeyInfos;
57
58 #[allow(clippy::too_many_arguments)]
59 fn circuit_bootstrapping_key_encrypt_sk<D, S0, S1>(
60 &self,
61 res: &mut CircuitBootstrappingKey<D, BRA>,
62 sk_lwe: &S0,
63 sk_glwe: &S1,
64 source_xa: &mut Source,
65 source_xe: &mut Source,
66 scratch: &mut Scratch<BE>,
67 ) where
68 D: DataMut,
69 S0: LWESecretToRef + GetDistribution + LWEInfos,
70 S1: GLWESecretToRef + GLWEInfos + GetDistribution;
71}
72
73impl<BRA: BlindRotationAlgo> CircuitBootstrappingKey<Vec<u8>, BRA> {
74 pub fn alloc_from_infos<A>(infos: &A) -> Self
75 where
76 A: CircuitBootstrappingKeyInfos,
77 BlindRotationKey<Vec<u8>, BRA>: BlindRotationKeyFactory<BRA>,
78 {
79 let atk_infos: &GLWEAutomorphismKeyLayout = &infos.atk_infos();
80 let brk_infos: &BlindRotationKeyLayout = &infos.brk_infos();
81 let trk_infos: &GGLWEToGGSWKeyLayout = &infos.tsk_infos();
82 let gal_els: Vec<i64> = trace_galois_elements(atk_infos.log_n(), 2 * atk_infos.n().as_usize() as i64);
83
84 Self {
85 brk: <BlindRotationKey<Vec<u8>, BRA> as BlindRotationKeyFactory<BRA>>::blind_rotation_key_alloc(brk_infos),
86 atk: gal_els
87 .iter()
88 .map(|&gal_el| {
89 let key = GLWEAutomorphismKey::alloc_from_infos(atk_infos);
90 (gal_el, key)
91 })
92 .collect(),
93 tsk: GGLWEToGGSWKey::alloc_from_infos(trk_infos),
94 }
95 }
96}
97
98pub struct CircuitBootstrappingKey<D: Data, BRA: BlindRotationAlgo> {
99 pub(crate) brk: BlindRotationKey<D, BRA>,
100 pub(crate) tsk: GGLWEToGGSWKey<Vec<u8>>,
101 pub(crate) atk: HashMap<i64, GLWEAutomorphismKey<Vec<u8>>>,
102}
103
104impl<D: DataMut, BRA: BlindRotationAlgo> CircuitBootstrappingKey<D, BRA> {
105 pub fn encrypt_sk<M, S0, S1, BE: Backend>(
106 &mut self,
107 module: &M,
108 sk_lwe: &S0,
109 sk_glwe: &S1,
110 source_xa: &mut Source,
111 source_xe: &mut Source,
112 scratch: &mut Scratch<BE>,
113 ) where
114 S0: LWESecretToRef + GetDistribution + LWEInfos,
115 S1: GLWESecretToRef + GLWEInfos + GetDistribution,
116 M: CircuitBootstrappingKeyEncryptSk<BRA, BE>,
117 {
118 module.circuit_bootstrapping_key_encrypt_sk(self, sk_lwe, sk_glwe, source_xa, source_xe, scratch);
119 }
120}
121
122impl<BRA: BlindRotationAlgo, BE: Backend> CircuitBootstrappingKeyEncryptSk<BRA, BE> for Module<BE>
123where
124 Self: GGLWEToGGSWKeyEncryptSk<BE>
125 + BlindRotationKeyEncryptSk<BRA, BE>
126 + GLWEAutomorphismKeyEncryptSk<BE>
127 + GLWESecretPreparedFactory<BE>,
128 Scratch<BE>: ScratchTakeCore<BE>,
129{
130 fn circuit_bootstrapping_key_encrypt_sk_tmp_bytes<A>(&self, infos: &A) -> usize
131 where
132 A: CircuitBootstrappingKeyInfos,
133 {
134 self.glwe_automorphism_key_encrypt_sk_tmp_bytes(&infos.atk_infos())
135 .max(self.blind_rotation_key_encrypt_sk_tmp_bytes(&infos.brk_infos()))
136 .max(self.gglwe_to_ggsw_key_encrypt_sk_tmp_bytes(&infos.tsk_infos()))
137 }
138
139 fn circuit_bootstrapping_key_encrypt_sk<D, S0, S1>(
140 &self,
141 res: &mut CircuitBootstrappingKey<D, BRA>,
142 sk_lwe: &S0,
143 sk_glwe: &S1,
144 source_xa: &mut Source,
145 source_xe: &mut Source,
146 scratch: &mut Scratch<BE>,
147 ) where
148 D: DataMut,
149 S0: LWESecretToRef + GetDistribution + LWEInfos,
150 S1: GLWESecretToRef + GLWEInfos + GetDistribution,
151 {
152 let brk_infos: &BlindRotationKeyLayout = &res.brk_infos();
153 let atk_infos: &GLWEAutomorphismKeyLayout = &res.atk_infos();
154 let tsk_infos: &GGLWEToGGSWKeyLayout = &res.tsk_infos();
155
156 assert_eq!(sk_lwe.n(), brk_infos.n_lwe());
157 assert_eq!(sk_glwe.n(), brk_infos.n_glwe());
158 assert_eq!(sk_glwe.n(), atk_infos.n());
159 assert_eq!(sk_glwe.n(), tsk_infos.n());
160
161 assert!(sk_glwe.dist() != &Distribution::NONE);
162
163 for (p, atk) in res.atk.iter_mut() {
164 atk.encrypt_sk(self, *p, sk_glwe, source_xa, source_xe, scratch);
165 }
166
167 let mut sk_glwe_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(self, brk_infos.rank());
168 sk_glwe_prepared.prepare(self, sk_glwe);
169
170 res.brk.encrypt_sk(
171 self,
172 &sk_glwe_prepared,
173 sk_lwe,
174 source_xa,
175 source_xe,
176 scratch,
177 );
178
179 res.tsk
180 .encrypt_sk(self, sk_glwe, source_xa, source_xe, scratch);
181 }
182}
183
184impl<D: DataRef, BRA: BlindRotationAlgo> CircuitBootstrappingKeyInfos for CircuitBootstrappingKey<D, BRA> {
185 fn block_size(&self) -> usize {
186 self.brk.block_size()
187 }
188
189 fn atk_infos(&self) -> GLWEAutomorphismKeyLayout {
190 let (_, atk) = self.atk.iter().next().expect("atk is empty");
191 GLWEAutomorphismKeyLayout {
192 n: atk.n(),
193 base2k: atk.base2k(),
194 k: atk.k(),
195 dnum: atk.dnum(),
196 dsize: atk.dsize(),
197 rank: atk.rank(),
198 }
199 }
200
201 fn brk_infos(&self) -> BlindRotationKeyLayout {
202 BlindRotationKeyLayout {
203 n_glwe: self.brk.n_glwe(),
204 n_lwe: self.brk.n_lwe(),
205 base2k: self.brk.base2k(),
206 k: self.brk.k(),
207 dnum: self.brk.dnum(),
208 rank: self.brk.rank(),
209 }
210 }
211
212 fn tsk_infos(&self) -> GGLWEToGGSWKeyLayout {
213 GGLWEToGGSWKeyLayout {
214 n: self.tsk.n(),
215 base2k: self.tsk.base2k(),
216 k: self.tsk.k(),
217 dnum: self.tsk.dnum(),
218 dsize: self.tsk.dsize(),
219 rank: self.tsk.rank(),
220 }
221 }
222}