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