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        VecZnxSubInplace,
  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, GLWECiphertextLayout, GLWEPlaintext, GLWEPlaintextLayout, GLWEPublicKey, GLWESecret, LWEInfos,
 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        + SvpApplyDftToDft<B>
 42        + VecZnxBigAddNormal<B>
 43        + VecZnxFillUniform
 44        + VecZnxSubInplace
 45        + VecZnxAddInplace
 46        + VecZnxNormalizeInplace<B>
 47        + VecZnxAddNormal
 48        + VecZnxNormalize<B>
 49        + VecZnxSub,
 50    B: Backend
 51        + TakeVecZnxDftImpl<B>
 52        + TakeVecZnxBigImpl<B>
 53        + TakeSvpPPolImpl<B>
 54        + ScratchOwnedAllocImpl<B>
 55        + ScratchOwnedBorrowImpl<B>
 56        + ScratchAvailableImpl<B>
 57        + TakeScalarZnxImpl<B>
 58        + TakeVecZnxImpl<B>,
 59{
 60    let base2k: usize = 8;
 61    let k_ct: usize = 54;
 62    let k_pt: usize = 30;
 63
 64    for rank in 1_usize..3 {
 65        let n: usize = module.n();
 66
 67        let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
 68            n: n.into(),
 69            base2k: base2k.into(),
 70            k: k_ct.into(),
 71            rank: rank.into(),
 72        };
 73
 74        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
 75            n: n.into(),
 76            base2k: base2k.into(),
 77            k: k_pt.into(),
 78        };
 79
 80        let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos);
 81        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos);
 82        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos);
 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, &glwe_infos)
 90                | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos),
 91        );
 92
 93        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
 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(base2k, &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(base2k, 0) * (ct.k().as_u32() 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        + SvpApplyDftToDft<B>
134        + VecZnxBigAddNormal<B>
135        + VecZnxFillUniform
136        + VecZnxSubInplace
137        + VecZnxAddInplace
138        + VecZnxNormalizeInplace<B>
139        + VecZnxAddNormal
140        + VecZnxNormalize<B>
141        + VecZnxSub
142        + VecZnxCopy,
143    B: Backend
144        + TakeVecZnxDftImpl<B>
145        + TakeVecZnxBigImpl<B>
146        + TakeSvpPPolImpl<B>
147        + ScratchOwnedAllocImpl<B>
148        + ScratchOwnedBorrowImpl<B>
149        + ScratchAvailableImpl<B>
150        + TakeScalarZnxImpl<B>
151        + TakeVecZnxImpl<B>,
152{
153    let base2k: usize = 8;
154    let k_ct: usize = 54;
155    let k_pt: usize = 30;
156
157    for rank in 1_usize..3 {
158        let n: usize = module.n();
159
160        let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
161            n: n.into(),
162            base2k: base2k.into(),
163            k: k_ct.into(),
164            rank: rank.into(),
165        };
166
167        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
168            n: n.into(),
169            base2k: base2k.into(),
170            k: k_pt.into(),
171        };
172
173        let mut ct_compressed: GLWECiphertextCompressed<Vec<u8>> = GLWECiphertextCompressed::alloc(&glwe_infos);
174
175        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos);
176        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&pt_infos);
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, &glwe_infos)
184                | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos),
185        );
186
187        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
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(base2k, &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(&glwe_infos);
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(base2k, 0) * (ct.k().as_u32() as f64).exp2();
212        let noise_want: f64 = SIGMA;
213
214        assert!(
215            noise_have <= noise_want + 0.2,
216            "{noise_have} <= {}",
217            noise_want + 0.2
218        );
219    }
220}
221
222pub fn test_glwe_encrypt_zero_sk<B>(module: &Module<B>)
223where
224    Module<B>: VecZnxDftAllocBytes
225        + VecZnxBigAllocBytes
226        + VecZnxDftApply<B>
227        + SvpApplyDftToDftInplace<B>
228        + VecZnxIdftApplyConsume<B>
229        + VecZnxBigAddInplace<B>
230        + VecZnxBigAddSmallInplace<B>
231        + VecZnxBigNormalize<B>
232        + VecZnxNormalizeTmpBytes
233        + SvpPrepare<B>
234        + SvpPPolAllocBytes
235        + SvpPPolAlloc<B>
236        + SvpApplyDftToDft<B>
237        + VecZnxBigAddNormal<B>
238        + VecZnxFillUniform
239        + VecZnxSubInplace
240        + VecZnxAddInplace
241        + VecZnxNormalizeInplace<B>
242        + VecZnxAddNormal
243        + VecZnxNormalize<B>
244        + VecZnxSub,
245    B: Backend
246        + TakeVecZnxDftImpl<B>
247        + TakeVecZnxBigImpl<B>
248        + TakeSvpPPolImpl<B>
249        + ScratchOwnedAllocImpl<B>
250        + ScratchOwnedBorrowImpl<B>
251        + ScratchAvailableImpl<B>
252        + TakeScalarZnxImpl<B>
253        + TakeVecZnxImpl<B>,
254{
255    let base2k: usize = 8;
256    let k_ct: usize = 54;
257
258    for rank in 1_usize..3 {
259        let n: usize = module.n();
260
261        let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
262            n: n.into(),
263            base2k: base2k.into(),
264            k: k_ct.into(),
265            rank: rank.into(),
266        };
267
268        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
269
270        let mut source_xs: Source = Source::new([0u8; 32]);
271        let mut source_xe: Source = Source::new([1u8; 32]);
272        let mut source_xa: Source = Source::new([0u8; 32]);
273
274        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
275            GLWECiphertext::decrypt_scratch_space(module, &glwe_infos)
276                | GLWECiphertext::encrypt_sk_scratch_space(module, &glwe_infos),
277        );
278
279        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
280        sk.fill_ternary_prob(0.5, &mut source_xs);
281        let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
282
283        let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos);
284
285        ct.encrypt_zero_sk(
286            module,
287            &sk_prepared,
288            &mut source_xa,
289            &mut source_xe,
290            scratch.borrow(),
291        );
292        ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
293
294        assert!((SIGMA - pt.data.std(base2k, 0) * (k_ct as f64).exp2()) <= 0.2);
295    }
296}
297
298pub fn test_glwe_encrypt_pk<B>(module: &Module<B>)
299where
300    Module<B>: VecZnxDftAllocBytes
301        + VecZnxBigNormalize<B>
302        + VecZnxDftApply<B>
303        + SvpApplyDftToDftInplace<B>
304        + VecZnxIdftApplyConsume<B>
305        + VecZnxNormalizeTmpBytes
306        + VecZnxFillUniform
307        + VecZnxSubInplace
308        + VecZnxAddInplace
309        + VecZnxNormalizeInplace<B>
310        + VecZnxAddNormal
311        + VecZnxNormalize<B>
312        + VecZnxSub
313        + SvpPrepare<B>
314        + SvpPPolAllocBytes
315        + SvpPPolAlloc<B>
316        + VecZnxBigAddSmallInplace<B>
317        + VecZnxBigAllocBytes
318        + VecZnxBigAddInplace<B>
319        + VecZnxCopy
320        + VecZnxDftAlloc<B>
321        + SvpApplyDftToDft<B>
322        + VecZnxBigAddNormal<B>,
323    B: Backend
324        + TakeVecZnxDftImpl<B>
325        + TakeVecZnxBigImpl<B>
326        + TakeSvpPPolImpl<B>
327        + ScratchOwnedAllocImpl<B>
328        + ScratchOwnedBorrowImpl<B>
329        + ScratchAvailableImpl<B>
330        + TakeScalarZnxImpl<B>
331        + TakeVecZnxImpl<B>,
332{
333    let base2k: usize = 8;
334    let k_ct: usize = 54;
335
336    for rank in 1_usize..3 {
337        let n: usize = module.n();
338
339        let glwe_infos: GLWECiphertextLayout = GLWECiphertextLayout {
340            n: n.into(),
341            base2k: base2k.into(),
342            k: k_ct.into(),
343            rank: rank.into(),
344        };
345
346        let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(&glwe_infos);
347        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
348        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(&glwe_infos);
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, &glwe_infos)
357                | GLWECiphertext::decrypt_scratch_space(module, &glwe_infos)
358                | GLWECiphertext::encrypt_pk_scratch_space(module, &glwe_infos),
359        );
360
361        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(&glwe_infos);
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(&glwe_infos);
366        pk.generate(module, &sk_prepared, &mut source_xa, &mut source_xe);
367
368        module.vec_znx_fill_uniform(base2k, &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(base2k, 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            "{noise_have} <= {}",
391            noise_want + 0.2
392        );
393    }
394}