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