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