arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/poulpy-core/src/tests/test_suite/encryption/glwe_ct.rs
poulpy-core/src/tests/test_suite/encryption/glwe_ct.rsRaw
  1use poulpy_hal::{
  2    api::{
  3        ScratchOwnedAlloc, ScratchOwnedBorrow, SvpApplyDftToDft, SvpApplyDftToDftInplace, SvpPPolAlloc, SvpPPolBytesOf,
  4        SvpPrepare, VecZnxAddInplace, VecZnxAddNormal, VecZnxBigAddInplace, VecZnxBigAddNormal, VecZnxBigAddSmallInplace,
  5        VecZnxBigBytesOf, VecZnxBigNormalize, VecZnxCopy, VecZnxDftAlloc, VecZnxDftApply, VecZnxDftBytesOf, VecZnxFillUniform,
  6        VecZnxIdftApplyConsume, VecZnxNormalize, VecZnxNormalizeInplace, VecZnxNormalizeTmpBytes, VecZnxSub, VecZnxSubInplace,
  7    },
  8    layouts::{Backend, Module, ScratchOwned},
  9    oep::{
 10        ScratchAvailableImpl, ScratchOwnedAllocImpl, ScratchOwnedBorrowImpl, TakeScalarZnxImpl, TakeSvpPPolImpl,
 11        TakeVecZnxBigImpl, TakeVecZnxDftImpl, TakeVecZnxImpl,
 12    },
 13    source::Source,
 14};
 15
 16use crate::{
 17    encryption::SIGMA,
 18    layouts::{
 19        GLWE, GLWELayout, GLWEPlaintext, GLWEPlaintextLayout, GLWEPublicKey, GLWESecret, LWEInfos,
 20        compressed::{Decompress, GLWECompressed},
 21        prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared, PrepareAlloc},
 22    },
 23    operations::GLWEOperations,
 24};
 25
 26pub fn test_glwe_encrypt_sk<B>(module: &Module<B>)
 27where
 28    Module<B>: VecZnxDftBytesOf
 29        + VecZnxBigBytesOf
 30        + VecZnxDftApply<B>
 31        + SvpApplyDftToDftInplace<B>
 32        + VecZnxIdftApplyConsume<B>
 33        + VecZnxBigAddInplace<B>
 34        + VecZnxBigAddSmallInplace<B>
 35        + VecZnxBigNormalize<B>
 36        + VecZnxNormalizeTmpBytes
 37        + SvpPrepare<B>
 38        + SvpPPolBytesOf
 39        + SvpPPolAlloc<B>
 40        + SvpApplyDftToDft<B>
 41        + VecZnxBigAddNormal<B>
 42        + VecZnxFillUniform
 43        + VecZnxSubInplace
 44        + VecZnxAddInplace
 45        + VecZnxNormalizeInplace<B>
 46        + VecZnxAddNormal
 47        + VecZnxNormalize<B>
 48        + VecZnxSub,
 49    B: Backend
 50        + TakeVecZnxDftImpl<B>
 51        + TakeVecZnxBigImpl<B>
 52        + TakeSvpPPolImpl<B>
 53        + ScratchOwnedAllocImpl<B>
 54        + ScratchOwnedBorrowImpl<B>
 55        + ScratchAvailableImpl<B>
 56        + TakeScalarZnxImpl<B>
 57        + TakeVecZnxImpl<B>,
 58{
 59    let base2k: usize = 8;
 60    let k_ct: usize = 54;
 61    let k_pt: usize = 30;
 62
 63    for rank in 1_usize..3 {
 64        let n: usize = module.n();
 65
 66        let glwe_infos: GLWELayout = GLWELayout {
 67            n: n.into(),
 68            base2k: base2k.into(),
 69            k: k_ct.into(),
 70            rank: rank.into(),
 71        };
 72
 73        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
 74            n: n.into(),
 75            base2k: base2k.into(),
 76            k: k_pt.into(),
 77        };
 78
 79        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos);
 80        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos);
 81        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos);
 82
 83        let mut source_xs: Source = Source::new([0u8; 32]);
 84        let mut source_xe: Source = Source::new([0u8; 32]);
 85        let mut source_xa: Source = Source::new([0u8; 32]);
 86
 87        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
 88            GLWE::encrypt_sk_scratch_space(module, &glwe_infos) | GLWE::decrypt_scratch_space(module, &glwe_infos),
 89        );
 90
 91        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos);
 92        sk.fill_ternary_prob(0.5, &mut source_xs);
 93        let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
 94
 95        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
 96
 97        ct.encrypt_sk(
 98            module,
 99            &pt_want,
100            &sk_prepared,
101            &mut source_xa,
102            &mut source_xe,
103            scratch.borrow(),
104        );
105
106        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
107
108        pt_want.sub_inplace_ab(module, &pt_have);
109
110        let noise_have: f64 = pt_want.data.std(base2k, 0) * (ct.k().as_u32() as f64).exp2();
111        let noise_want: f64 = SIGMA;
112
113        assert!(noise_have <= noise_want + 0.2);
114    }
115}
116
117pub fn test_glwe_compressed_encrypt_sk<B>(module: &Module<B>)
118where
119    Module<B>: VecZnxDftBytesOf
120        + VecZnxBigBytesOf
121        + VecZnxDftApply<B>
122        + SvpApplyDftToDftInplace<B>
123        + VecZnxIdftApplyConsume<B>
124        + VecZnxBigAddInplace<B>
125        + VecZnxBigAddSmallInplace<B>
126        + VecZnxBigNormalize<B>
127        + VecZnxNormalizeTmpBytes
128        + SvpPrepare<B>
129        + SvpPPolBytesOf
130        + SvpPPolAlloc<B>
131        + SvpApplyDftToDft<B>
132        + VecZnxBigAddNormal<B>
133        + VecZnxFillUniform
134        + VecZnxSubInplace
135        + VecZnxAddInplace
136        + VecZnxNormalizeInplace<B>
137        + VecZnxAddNormal
138        + VecZnxNormalize<B>
139        + VecZnxSub
140        + VecZnxCopy,
141    B: Backend
142        + TakeVecZnxDftImpl<B>
143        + TakeVecZnxBigImpl<B>
144        + TakeSvpPPolImpl<B>
145        + ScratchOwnedAllocImpl<B>
146        + ScratchOwnedBorrowImpl<B>
147        + ScratchAvailableImpl<B>
148        + TakeScalarZnxImpl<B>
149        + TakeVecZnxImpl<B>,
150{
151    let base2k: usize = 8;
152    let k_ct: usize = 54;
153    let k_pt: usize = 30;
154
155    for rank in 1_usize..3 {
156        let n: usize = module.n();
157
158        let glwe_infos: GLWELayout = GLWELayout {
159            n: n.into(),
160            base2k: base2k.into(),
161            k: k_ct.into(),
162            rank: rank.into(),
163        };
164
165        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
166            n: n.into(),
167            base2k: base2k.into(),
168            k: k_pt.into(),
169        };
170
171        let mut ct_compressed: GLWECompressed<Vec<u8>> = GLWECompressed::alloc_from_infos(&glwe_infos);
172
173        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos);
174        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&pt_infos);
175
176        let mut source_xs: Source = Source::new([0u8; 32]);
177        let mut source_xe: Source = Source::new([0u8; 32]);
178        let mut source_xa: Source = Source::new([0u8; 32]);
179
180        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
181            GLWECompressed::encrypt_sk_scratch_space(module, &glwe_infos) | GLWE::decrypt_scratch_space(module, &glwe_infos),
182        );
183
184        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos);
185        sk.fill_ternary_prob(0.5, &mut source_xs);
186        let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
187
188        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
189
190        let seed_xa: [u8; 32] = [1u8; 32];
191
192        ct_compressed.encrypt_sk(
193            module,
194            &pt_want,
195            &sk_prepared,
196            seed_xa,
197            &mut source_xe,
198            scratch.borrow(),
199        );
200
201        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos);
202        ct.decompress(module, &ct_compressed);
203
204        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
205
206        pt_want.sub_inplace_ab(module, &pt_have);
207
208        let noise_have: f64 = pt_want.data.std(base2k, 0) * (ct.k().as_u32() as f64).exp2();
209        let noise_want: f64 = SIGMA;
210
211        assert!(
212            noise_have <= noise_want + 0.2,
213            "{noise_have} <= {}",
214            noise_want + 0.2
215        );
216    }
217}
218
219pub fn test_glwe_encrypt_zero_sk<B>(module: &Module<B>)
220where
221    Module<B>: VecZnxDftBytesOf
222        + VecZnxBigBytesOf
223        + VecZnxDftApply<B>
224        + SvpApplyDftToDftInplace<B>
225        + VecZnxIdftApplyConsume<B>
226        + VecZnxBigAddInplace<B>
227        + VecZnxBigAddSmallInplace<B>
228        + VecZnxBigNormalize<B>
229        + VecZnxNormalizeTmpBytes
230        + SvpPrepare<B>
231        + SvpPPolBytesOf
232        + SvpPPolAlloc<B>
233        + SvpApplyDftToDft<B>
234        + VecZnxBigAddNormal<B>
235        + VecZnxFillUniform
236        + VecZnxSubInplace
237        + VecZnxAddInplace
238        + VecZnxNormalizeInplace<B>
239        + VecZnxAddNormal
240        + VecZnxNormalize<B>
241        + VecZnxSub,
242    B: Backend
243        + TakeVecZnxDftImpl<B>
244        + TakeVecZnxBigImpl<B>
245        + TakeSvpPPolImpl<B>
246        + ScratchOwnedAllocImpl<B>
247        + ScratchOwnedBorrowImpl<B>
248        + ScratchAvailableImpl<B>
249        + TakeScalarZnxImpl<B>
250        + TakeVecZnxImpl<B>,
251{
252    let base2k: usize = 8;
253    let k_ct: usize = 54;
254
255    for rank in 1_usize..3 {
256        let n: usize = module.n();
257
258        let glwe_infos: GLWELayout = GLWELayout {
259            n: n.into(),
260            base2k: base2k.into(),
261            k: k_ct.into(),
262            rank: rank.into(),
263        };
264
265        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos);
266
267        let mut source_xs: Source = Source::new([0u8; 32]);
268        let mut source_xe: Source = Source::new([1u8; 32]);
269        let mut source_xa: Source = Source::new([0u8; 32]);
270
271        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
272            GLWE::decrypt_scratch_space(module, &glwe_infos) | GLWE::encrypt_sk_scratch_space(module, &glwe_infos),
273        );
274
275        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos);
276        sk.fill_ternary_prob(0.5, &mut source_xs);
277        let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
278
279        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos);
280
281        ct.encrypt_zero_sk(
282            module,
283            &sk_prepared,
284            &mut source_xa,
285            &mut source_xe,
286            scratch.borrow(),
287        );
288        ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
289
290        assert!((SIGMA - pt.data.std(base2k, 0) * (k_ct as f64).exp2()) <= 0.2);
291    }
292}
293
294pub fn test_glwe_encrypt_pk<B>(module: &Module<B>)
295where
296    Module<B>: VecZnxDftBytesOf
297        + VecZnxBigNormalize<B>
298        + VecZnxDftApply<B>
299        + SvpApplyDftToDftInplace<B>
300        + VecZnxIdftApplyConsume<B>
301        + VecZnxNormalizeTmpBytes
302        + VecZnxFillUniform
303        + VecZnxSubInplace
304        + VecZnxAddInplace
305        + VecZnxNormalizeInplace<B>
306        + VecZnxAddNormal
307        + VecZnxNormalize<B>
308        + VecZnxSub
309        + SvpPrepare<B>
310        + SvpPPolBytesOf
311        + SvpPPolAlloc<B>
312        + VecZnxBigAddSmallInplace<B>
313        + VecZnxBigBytesOf
314        + VecZnxBigAddInplace<B>
315        + VecZnxCopy
316        + VecZnxDftAlloc<B>
317        + SvpApplyDftToDft<B>
318        + VecZnxBigAddNormal<B>,
319    B: Backend
320        + TakeVecZnxDftImpl<B>
321        + TakeVecZnxBigImpl<B>
322        + TakeSvpPPolImpl<B>
323        + ScratchOwnedAllocImpl<B>
324        + ScratchOwnedBorrowImpl<B>
325        + ScratchAvailableImpl<B>
326        + TakeScalarZnxImpl<B>
327        + TakeVecZnxImpl<B>,
328{
329    let base2k: usize = 8;
330    let k_ct: usize = 54;
331
332    for rank in 1_usize..3 {
333        let n: usize = module.n();
334
335        let glwe_infos: GLWELayout = GLWELayout {
336            n: n.into(),
337            base2k: base2k.into(),
338            k: k_ct.into(),
339            rank: rank.into(),
340        };
341
342        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(&glwe_infos);
343        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos);
344        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(&glwe_infos);
345
346        let mut source_xs: Source = Source::new([0u8; 32]);
347        let mut source_xe: Source = Source::new([0u8; 32]);
348        let mut source_xa: Source = Source::new([0u8; 32]);
349        let mut source_xu: Source = Source::new([0u8; 32]);
350
351        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
352            GLWE::encrypt_sk_scratch_space(module, &glwe_infos)
353                | GLWE::decrypt_scratch_space(module, &glwe_infos)
354                | GLWE::encrypt_pk_scratch_space(module, &glwe_infos),
355        );
356
357        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(&glwe_infos);
358        sk.fill_ternary_prob(0.5, &mut source_xs);
359        let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
360
361        let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc_from_infos(&glwe_infos);
362        pk.generate(module, &sk_prepared, &mut source_xa, &mut source_xe);
363
364        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
365
366        let pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = pk.prepare_alloc(module, scratch.borrow());
367
368        ct.encrypt_pk(
369            module,
370            &pt_want,
371            &pk_prepared,
372            &mut source_xu,
373            &mut source_xe,
374            scratch.borrow(),
375        );
376
377        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
378
379        pt_want.sub_inplace_ab(module, &pt_have);
380
381        let noise_have: f64 = pt_want.data.std(base2k, 0).log2();
382        let noise_want: f64 = ((((rank as f64) + 1.0) * n as f64 * 0.5 * SIGMA * SIGMA).sqrt()).log2() - (k_ct as f64);
383
384        assert!(
385            noise_have <= noise_want + 0.2,
386            "{noise_have} <= {}",
387            noise_want + 0.2
388        );
389    }
390}