arnaucube
arnaucube/poulpyPublic Self-hosted repository
poulpy/core/src/tests/generics/encryption/glwe_ct.rs
core/src/tests/generics/encryption/glwe_ct.rsRaw
  1use backend::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};
 15use sampling::source::Source;
 16
 17use crate::{
 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, sigma: f64, rank: usize)
 27where
 28    Module<B>: VecZnxDftAllocBytes
 29        + VecZnxBigAllocBytes
 30        + VecZnxDftFromVecZnx<B>
 31        + SvpApplyInplace<B>
 32        + VecZnxDftToVecZnxBigConsume<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        + VecZnxDftToVecZnxBigConsume<B>
 46        + VecZnxBigAddNormal<B>
 47        + VecZnxBigAddSmallInplace<B>
 48        + VecZnxBigNormalize<B>
 49        + VecZnxNormalizeTmpBytes
 50        + VecZnxDftAllocBytes
 51        + VecZnxBigNormalize<B>
 52        + VecZnxDftFromVecZnx<B>
 53        + SvpApplyInplace<B>
 54        + VecZnxDftToVecZnxBigConsume<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, n, basek, ct.k())
 84            | GLWECiphertext::decrypt_scratch_space(module, n, 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        sigma,
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, sigma: f64, 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        sigma,
191        scratch.borrow(),
192    );
193
194    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
195    ct.decompress(module, &ct_compressed);
196
197    ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
198
199    pt_want.sub_inplace_ab(module, &pt_have);
200
201    let noise_have: f64 = pt_want.data.std(basek, 0) * (ct.k() as f64).exp2();
202    let noise_want: f64 = sigma;
203
204    assert!(
205        noise_have <= noise_want + 0.2,
206        "{} <= {}",
207        noise_have,
208        noise_want + 0.2
209    );
210}
211
212pub fn test_glwe_encrypt_zero_sk<B>(module: &Module<B>, basek: usize, k_ct: usize, sigma: f64, rank: usize)
213where
214    Module<B>: VecZnxDftAllocBytes
215        + VecZnxBigAllocBytes
216        + VecZnxDftFromVecZnx<B>
217        + SvpApplyInplace<B>
218        + VecZnxDftToVecZnxBigConsume<B>
219        + VecZnxBigAddInplace<B>
220        + VecZnxBigAddSmallInplace<B>
221        + VecZnxBigNormalize<B>
222        + VecZnxNormalizeTmpBytes
223        + SvpPrepare<B>
224        + SvpPPolAllocBytes
225        + SvpPPolAlloc<B>
226        + VecZnxDftAllocBytes
227        + VecZnxBigAllocBytes
228        + SvpPPolAllocBytes
229        + SvpPrepare<B>
230        + SvpApply<B>
231        + VecZnxDftToVecZnxBigConsume<B>
232        + VecZnxBigAddNormal<B>
233        + VecZnxBigAddSmallInplace<B>
234        + VecZnxBigNormalize<B>
235        + VecZnxNormalizeTmpBytes
236        + VecZnxDftAllocBytes
237        + VecZnxBigNormalize<B>
238        + VecZnxDftFromVecZnx<B>
239        + SvpApplyInplace<B>
240        + VecZnxDftToVecZnxBigConsume<B>
241        + VecZnxNormalizeTmpBytes
242        + VecZnxFillUniform
243        + VecZnxSubABInplace
244        + VecZnxAddInplace
245        + VecZnxNormalizeInplace<B>
246        + VecZnxAddNormal
247        + VecZnxNormalize<B>
248        + VecZnxSub,
249    B: Backend
250        + TakeVecZnxDftImpl<B>
251        + TakeVecZnxBigImpl<B>
252        + TakeSvpPPolImpl<B>
253        + ScratchOwnedAllocImpl<B>
254        + ScratchOwnedBorrowImpl<B>
255        + ScratchAvailableImpl<B>
256        + TakeScalarZnxImpl<B>
257        + TakeVecZnxImpl<B>,
258{
259    let n = module.n();
260    let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
261
262    let mut source_xs: Source = Source::new([0u8; 32]);
263    let mut source_xe: Source = Source::new([1u8; 32]);
264    let mut source_xa: Source = Source::new([0u8; 32]);
265
266    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
267        GLWECiphertext::decrypt_scratch_space(module, n, basek, k_ct)
268            | GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, k_ct),
269    );
270
271    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
272    sk.fill_ternary_prob(0.5, &mut source_xs);
273    let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
274
275    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
276
277    ct.encrypt_zero_sk(
278        module,
279        &sk_prepared,
280        &mut source_xa,
281        &mut source_xe,
282        sigma,
283        scratch.borrow(),
284    );
285    ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
286
287    assert!((sigma - pt.data.std(basek, 0) * (k_ct as f64).exp2()) <= 0.2);
288}
289
290pub fn test_glwe_encrypt_pk<B>(module: &Module<B>, basek: usize, k_ct: usize, k_pk: usize, sigma: f64, rank: usize)
291where
292    Module<B>: VecZnxDftAllocBytes
293        + VecZnxBigNormalize<B>
294        + VecZnxDftFromVecZnx<B>
295        + SvpApplyInplace<B>
296        + VecZnxDftToVecZnxBigConsume<B>
297        + VecZnxNormalizeTmpBytes
298        + VecZnxFillUniform
299        + VecZnxSubABInplace
300        + VecZnxAddInplace
301        + VecZnxNormalizeInplace<B>
302        + VecZnxAddNormal
303        + VecZnxNormalize<B>
304        + VecZnxSub
305        + SvpPrepare<B>
306        + SvpPPolAllocBytes
307        + SvpPPolAlloc<B>
308        + VecZnxBigAddSmallInplace<B>
309        + VecZnxBigAllocBytes
310        + VecZnxBigAddInplace<B>
311        + VecZnxCopy
312        + VecZnxDftAlloc<B>
313        + SvpApply<B>
314        + VecZnxBigAddNormal<B>,
315    B: Backend
316        + TakeVecZnxDftImpl<B>
317        + TakeVecZnxBigImpl<B>
318        + TakeSvpPPolImpl<B>
319        + ScratchOwnedAllocImpl<B>
320        + ScratchOwnedBorrowImpl<B>
321        + ScratchAvailableImpl<B>
322        + TakeScalarZnxImpl<B>
323        + TakeVecZnxImpl<B>,
324{
325    let n: usize = module.n();
326    let mut ct: GLWECiphertext<Vec<u8>> = GLWECiphertext::alloc(n, basek, k_ct, rank);
327    let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
328    let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc(n, basek, k_ct);
329
330    let mut source_xs: Source = Source::new([0u8; 32]);
331    let mut source_xe: Source = Source::new([0u8; 32]);
332    let mut source_xa: Source = Source::new([0u8; 32]);
333    let mut source_xu: Source = Source::new([0u8; 32]);
334
335    let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
336        GLWECiphertext::encrypt_sk_scratch_space(module, n, basek, ct.k())
337            | GLWECiphertext::decrypt_scratch_space(module, n, basek, ct.k())
338            | GLWECiphertext::encrypt_pk_scratch_space(module, n, basek, k_pk),
339    );
340
341    let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc(n, rank);
342    sk.fill_ternary_prob(0.5, &mut source_xs);
343    let sk_prepared: GLWESecretPrepared<Vec<u8>, B> = sk.prepare_alloc(module, scratch.borrow());
344
345    let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc(n, basek, k_pk, rank);
346    pk.generate_from_sk(module, &sk_prepared, &mut source_xa, &mut source_xe, sigma);
347
348    module.vec_znx_fill_uniform(basek, &mut pt_want.data, 0, k_ct, &mut source_xa);
349
350    let pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = pk.prepare_alloc(module, scratch.borrow());
351
352    ct.encrypt_pk(
353        module,
354        &pt_want,
355        &pk_prepared,
356        &mut source_xu,
357        &mut source_xe,
358        sigma,
359        scratch.borrow(),
360    );
361
362    ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
363
364    pt_want.sub_inplace_ab(module, &pt_have);
365
366    let noise_have: f64 = pt_want.data.std(basek, 0).log2();
367    let noise_want: f64 = ((((rank as f64) + 1.0) * n as f64 * 0.5 * sigma * sigma).sqrt()).log2() - (k_ct as f64);
368
369    assert!(
370        noise_have <= noise_want + 0.2,
371        "{} {}",
372        noise_have,
373        noise_want
374    );
375}