poulpy/poulpy-core/src/tests/test_suite/encryption/gglwe_ct.rs
poulpy-core/src/tests/test_suite/encryption/gglwe_ct.rsRaw
1use poulpy_hal::{
2 api::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxFillUniform},
3 layouts::{Backend, Module, Scratch, ScratchOwned},
4 source::Source,
5};
6
7use crate::{
8 GGLWECompressedEncryptSk, GGLWEEncryptSk, GGLWEKeyswitch, GLWESwitchingKeyCompressedEncryptSk, GLWESwitchingKeyEncryptSk,
9 ScratchTakeCore,
10 decryption::GLWEDecrypt,
11 encryption::SIGMA,
12 layouts::{
13 GGLWE, GGLWECompressed, GGLWEInfos, GGLWELayout, GLWESecret, GLWESecretPreparedFactory, GLWESwitchingKey,
14 GLWESwitchingKeyCompressed, GLWESwitchingKeyDecompress, LWEInfos,
15 prepared::{GGLWEPreparedFactory, GLWESecretPrepared},
16 },
17 noise::GGLWENoise,
18};
19
20pub fn test_gglwe_switching_key_encrypt_sk<BE: Backend>(module: &Module<BE>)
21where
22 Module<BE>: GGLWEEncryptSk<BE>
23 + GGLWEPreparedFactory<BE>
24 + GGLWEKeyswitch<BE>
25 + GLWEDecrypt<BE>
26 + GLWESecretPreparedFactory<BE>
27 + GLWESwitchingKeyEncryptSk<BE>
28 + VecZnxFillUniform
29 + GGLWENoise<BE>,
30 ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
31 Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
32{
33 let n: usize = module.n();
34 let base2k: usize = 12;
35 let k_ksk: usize = 54;
36 let dsize: usize = k_ksk / base2k;
37 for rank_in in 1_usize..3 {
38 for rank_out in 1_usize..3 {
39 for di in 1_usize..dsize + 1 {
40 let dnum: usize = (k_ksk - di * base2k) / (di * base2k);
41
42 let gglwe_infos: GGLWELayout = GGLWELayout {
43 n: n.into(),
44 base2k: base2k.into(),
45 k: k_ksk.into(),
46 dnum: dnum.into(),
47 dsize: di.into(),
48 rank_in: rank_in.into(),
49 rank_out: rank_out.into(),
50 };
51
52 let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_infos);
53
54 let mut source_xs: Source = Source::new([0u8; 32]);
55 let mut source_xe: Source = Source::new([0u8; 32]);
56 let mut source_xa: Source = Source::new([0u8; 32]);
57
58 let mut scratch: ScratchOwned<BE> =
59 ScratchOwned::alloc(GLWESwitchingKey::encrypt_sk_tmp_bytes(module, &gglwe_infos));
60
61 let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into());
62 sk_in.fill_ternary_prob(0.5, &mut source_xs);
63
64 let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into());
65 sk_out.fill_ternary_prob(0.5, &mut source_xs);
66 let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, rank_out.into());
67 sk_out_prepared.prepare(module, &sk_out);
68
69 ksk.encrypt_sk(module, &sk_in, &sk_out, &mut source_xa, &mut source_xe, scratch.borrow());
70
71 let max_noise: f64 = SIGMA.log2() - (ksk.k().as_usize() as f64) + 0.5;
72
73 for row in 0..ksk.dnum().as_usize() {
74 for col in 0..ksk.rank_in().as_usize() {
75 let noise_have = ksk
76 .key
77 .noise(module, row, col, &sk_in.data, &sk_out_prepared, scratch.borrow())
78 .std()
79 .log2();
80
81 assert!(
82 noise_have < max_noise + 0.5,
83 "row:{row} col:{col} noise_have:{noise_have} > max_noise:{}",
84 max_noise + 0.5
85 );
86 }
87 }
88 }
89 }
90 }
91}
92
93pub fn test_gglwe_switching_key_compressed_encrypt_sk<BE: Backend>(module: &Module<BE>)
94where
95 Module<BE>: GGLWEEncryptSk<BE>
96 + GGLWEPreparedFactory<BE>
97 + GGLWEKeyswitch<BE>
98 + GLWEDecrypt<BE>
99 + GLWESecretPreparedFactory<BE>
100 + GLWESwitchingKeyEncryptSk<BE>
101 + GLWESwitchingKeyCompressedEncryptSk<BE>
102 + GLWESwitchingKeyDecompress
103 + GGLWENoise<BE>
104 + VecZnxFillUniform,
105 ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
106 Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
107{
108 let n: usize = module.n();
109 let base2k: usize = 12;
110 let k_ksk: usize = 54;
111 let max_dsize: usize = k_ksk / base2k;
112 for rank_in in 1_usize..3 {
113 for rank_out in 1_usize..3 {
114 for dsize in 1_usize..max_dsize {
115 let dnum: usize = (k_ksk - dsize * base2k) / (dsize * base2k);
116
117 let gglwe_infos: GGLWELayout = GGLWELayout {
118 n: n.into(),
119 base2k: base2k.into(),
120 k: k_ksk.into(),
121 dnum: dnum.into(),
122 dsize: dsize.into(),
123 rank_in: rank_in.into(),
124 rank_out: rank_out.into(),
125 };
126
127 let mut ksk_compressed: GLWESwitchingKeyCompressed<Vec<u8>> =
128 GLWESwitchingKeyCompressed::alloc_from_infos(&gglwe_infos);
129
130 let mut source_xs: Source = Source::new([0u8; 32]);
131 let mut source_xe: Source = Source::new([0u8; 32]);
132
133 let mut scratch: ScratchOwned<BE> =
134 ScratchOwned::alloc(GLWESwitchingKeyCompressed::encrypt_sk_tmp_bytes(module, &gglwe_infos));
135
136 let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into());
137 sk_in.fill_ternary_prob(0.5, &mut source_xs);
138
139 let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into());
140 sk_out.fill_ternary_prob(0.5, &mut source_xs);
141 let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, rank_out.into());
142 sk_out_prepared.prepare(module, &sk_out);
143
144 let seed_xa = [1u8; 32];
145
146 ksk_compressed.encrypt_sk(module, &sk_in, &sk_out, seed_xa, &mut source_xe, scratch.borrow());
147
148 let mut ksk: GLWESwitchingKey<Vec<u8>> = GLWESwitchingKey::alloc_from_infos(&gglwe_infos);
149 ksk.decompress(module, &ksk_compressed);
150
151 let max_noise: f64 = SIGMA.log2() - (ksk.k().as_usize() as f64) + 0.5;
152
153 for row in 0..ksk.dnum().as_usize() {
154 for col in 0..ksk.rank_in().as_usize() {
155 let noise_have = ksk
156 .key
157 .noise(module, row, col, &sk_in.data, &sk_out_prepared, scratch.borrow())
158 .std()
159 .log2();
160
161 assert!(
162 noise_have < max_noise + 0.5,
163 "row:{row} col:{col} noise_have:{noise_have} > max_noise:{}",
164 max_noise + 0.5
165 );
166 }
167 }
168 }
169 }
170 }
171}
172
173pub fn test_gglwe_compressed_encrypt_sk<BE: Backend>(module: &Module<BE>)
174where
175 Module<BE>: GGLWEEncryptSk<BE>
176 + GGLWEPreparedFactory<BE>
177 + GGLWEKeyswitch<BE>
178 + GLWEDecrypt<BE>
179 + GLWESecretPreparedFactory<BE>
180 + GLWESwitchingKeyEncryptSk<BE>
181 + GGLWECompressedEncryptSk<BE>
182 + GLWESwitchingKeyDecompress
183 + GGLWENoise<BE>
184 + VecZnxFillUniform,
185 ScratchOwned<BE>: ScratchOwnedAlloc<BE> + ScratchOwnedBorrow<BE>,
186 Scratch<BE>: ScratchAvailable + ScratchTakeCore<BE>,
187{
188 let n: usize = module.n();
189 let base2k: usize = 12;
190 let k_ksk: usize = 54;
191 let max_dsize: usize = k_ksk / base2k;
192 for rank_in in 1_usize..3 {
193 for rank_out in 1_usize..3 {
194 for dsize in 1_usize..max_dsize + 1 {
195 let dnum: usize = (k_ksk - dsize * base2k) / (dsize * base2k);
196
197 let gglwe_infos: GGLWELayout = GGLWELayout {
198 n: n.into(),
199 base2k: base2k.into(),
200 k: k_ksk.into(),
201 dnum: dnum.into(),
202 dsize: dsize.into(),
203 rank_in: rank_in.into(),
204 rank_out: rank_out.into(),
205 };
206
207 let mut ksk_compressed: GGLWECompressed<Vec<u8>> = GGLWECompressed::alloc_from_infos(&gglwe_infos);
208
209 let mut source_xs: Source = Source::new([0u8; 32]);
210 let mut source_xe: Source = Source::new([0u8; 32]);
211
212 let mut scratch: ScratchOwned<BE> =
213 ScratchOwned::alloc(GGLWECompressed::encrypt_sk_tmp_bytes(module, &gglwe_infos));
214
215 let mut sk_in: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_in.into());
216 sk_in.fill_ternary_prob(0.5, &mut source_xs);
217
218 let mut sk_out: GLWESecret<Vec<u8>> = GLWESecret::alloc(n.into(), rank_out.into());
219 sk_out.fill_ternary_prob(0.5, &mut source_xs);
220 let mut sk_out_prepared: GLWESecretPrepared<Vec<u8>, BE> = GLWESecretPrepared::alloc(module, rank_out.into());
221 sk_out_prepared.prepare(module, &sk_out);
222
223 let seed_xa = [1u8; 32];
224
225 ksk_compressed.encrypt_sk(
226 module,
227 &sk_in.data,
228 &sk_out_prepared,
229 seed_xa,
230 &mut source_xe,
231 scratch.borrow(),
232 );
233
234 let mut ksk: GGLWE<Vec<u8>> = GGLWE::alloc_from_infos(&gglwe_infos);
235 ksk.decompress(module, &ksk_compressed);
236
237 let max_noise: f64 = SIGMA.log2() - (ksk.k().as_usize() as f64) + 0.5;
238
239 for row in 0..ksk.dnum().as_usize() {
240 for col in 0..ksk.rank_in().as_usize() {
241 let noise_have = ksk
242 .noise(module, row, col, &sk_in.data, &sk_out_prepared, scratch.borrow())
243 .std()
244 .log2();
245
246 assert!(
247 noise_have < max_noise + 0.5,
248 "row:{row} col:{col} noise_have:{noise_have} > max_noise:{}",
249 max_noise + 0.5
250 );
251 }
252 }
253 }
254 }
255 }
256}