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::{ScratchAvailable, ScratchOwnedAlloc, ScratchOwnedBorrow, VecZnxFillUniform},
  3    layouts::{Backend, Module, Scratch, ScratchOwned},
  4    source::Source,
  5};
  6
  7use crate::{
  8    GLWECompressedEncryptSk, GLWEEncryptPk, GLWEEncryptSk, GLWEPublicKeyGenerate, GLWESub, ScratchTakeCore,
  9    decryption::GLWEDecrypt,
 10    encryption::SIGMA,
 11    layouts::{
 12        GLWE, GLWEAlloc, GLWELayout, GLWEPlaintext, GLWEPlaintextLayout, GLWEPublicKey, GLWEPublicKeyPrepare,
 13        GLWEPublicKeyPreparedAlloc, GLWESecret, GLWESecretPrepare, GLWESecretPreparedAlloc, LWEInfos,
 14        compressed::GLWECompressed,
 15        prepared::{GLWEPublicKeyPrepared, GLWESecretPrepared},
 16    },
 17};
 18
 19pub fn test_glwe_encrypt_sk<B: Backend>(module: &Module<B>)
 20where
 21    Module<B>: GLWEAlloc
 22        + GLWEEncryptSk<B>
 23        + GLWEDecrypt<B>
 24        + GLWESecretPreparedAlloc<B>
 25        + GLWESecretPrepare<B>
 26        + VecZnxFillUniform
 27        + GLWESub,
 28    ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
 29    Scratch<B>: ScratchAvailable + ScratchTakeCore<B>,
 30{
 31    let base2k: usize = 8;
 32    let k_ct: usize = 54;
 33    let k_pt: usize = 30;
 34
 35    for rank in 1_usize..3 {
 36        let n: usize = module.n();
 37
 38        let glwe_infos: GLWELayout = GLWELayout {
 39            n: n.into(),
 40            base2k: base2k.into(),
 41            k: k_ct.into(),
 42            rank: rank.into(),
 43        };
 44
 45        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
 46            n: n.into(),
 47            base2k: base2k.into(),
 48            k: k_pt.into(),
 49        };
 50
 51        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(module, &glwe_infos);
 52        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &pt_infos);
 53        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &pt_infos);
 54
 55        let mut source_xs: Source = Source::new([0u8; 32]);
 56        let mut source_xe: Source = Source::new([0u8; 32]);
 57        let mut source_xa: Source = Source::new([0u8; 32]);
 58
 59        let mut scratch: ScratchOwned<B> =
 60            ScratchOwned::alloc(GLWE::encrypt_sk_tmp_bytes(module, &glwe_infos) | GLWE::decrypt_tmp_bytes(module, &glwe_infos));
 61
 62        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &glwe_infos);
 63        sk.fill_ternary_prob(0.5, &mut source_xs);
 64
 65        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, rank.into());
 66        sk_prepared.prepare(module, &sk);
 67
 68        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
 69
 70        ct.encrypt_sk(
 71            module,
 72            &pt_want,
 73            &sk_prepared,
 74            &mut source_xa,
 75            &mut source_xe,
 76            scratch.borrow(),
 77        );
 78
 79        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
 80
 81        module.glwe_sub_inplace(&mut pt_want, &pt_have);
 82
 83        let noise_have: f64 = pt_want.data.std(base2k, 0) * (ct.k().as_u32() as f64).exp2();
 84        let noise_want: f64 = SIGMA;
 85
 86        assert!(noise_have <= noise_want + 0.2);
 87    }
 88}
 89
 90pub fn test_glwe_compressed_encrypt_sk<B: Backend>(module: &Module<B>)
 91where
 92    Module<B>: GLWEAlloc
 93        + GLWECompressedEncryptSk<B>
 94        + GLWEDecrypt<B>
 95        + GLWESecretPreparedAlloc<B>
 96        + GLWESecretPrepare<B>
 97        + VecZnxFillUniform
 98        + GLWESub,
 99    ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
100    Scratch<B>: ScratchAvailable + ScratchTakeCore<B>,
101{
102    let base2k: usize = 8;
103    let k_ct: usize = 54;
104    let k_pt: usize = 30;
105
106    for rank in 1_usize..3 {
107        let n: usize = module.n();
108
109        let glwe_infos: GLWELayout = GLWELayout {
110            n: n.into(),
111            base2k: base2k.into(),
112            k: k_ct.into(),
113            rank: rank.into(),
114        };
115
116        let pt_infos: GLWEPlaintextLayout = GLWEPlaintextLayout {
117            n: n.into(),
118            base2k: base2k.into(),
119            k: k_pt.into(),
120        };
121
122        let mut ct_compressed: GLWECompressed<Vec<u8>> = GLWECompressed::alloc_from_infos(module, &glwe_infos);
123
124        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &pt_infos);
125        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &pt_infos);
126
127        let mut source_xs: Source = Source::new([0u8; 32]);
128        let mut source_xe: Source = Source::new([0u8; 32]);
129        let mut source_xa: Source = Source::new([0u8; 32]);
130
131        let mut scratch: ScratchOwned<B> = ScratchOwned::alloc(
132            GLWECompressed::encrypt_sk_tmp_bytes(module, &glwe_infos) | GLWE::decrypt_tmp_bytes(module, &glwe_infos),
133        );
134
135        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &glwe_infos);
136        sk.fill_ternary_prob(0.5, &mut source_xs);
137
138        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, rank.into());
139        sk_prepared.prepare(module, &sk);
140
141        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
142
143        let seed_xa: [u8; 32] = [1u8; 32];
144
145        ct_compressed.encrypt_sk(
146            module,
147            &pt_want,
148            &sk_prepared,
149            seed_xa,
150            &mut source_xe,
151            scratch.borrow(),
152        );
153
154        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(module, &glwe_infos);
155        ct.decompress(module, &ct_compressed);
156
157        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
158
159        module.glwe_sub_inplace(&mut pt_want, &pt_have);
160
161        let noise_have: f64 = pt_want.data.std(base2k, 0) * (ct.k().as_u32() as f64).exp2();
162        let noise_want: f64 = SIGMA;
163
164        assert!(
165            noise_have <= noise_want + 0.2,
166            "{noise_have} <= {}",
167            noise_want + 0.2
168        );
169    }
170}
171
172pub fn test_glwe_encrypt_zero_sk<B: Backend>(module: &Module<B>)
173where
174    Module<B>: GLWEAlloc
175        + GLWEEncryptSk<B>
176        + GLWEDecrypt<B>
177        + GLWESecretPreparedAlloc<B>
178        + GLWESecretPrepare<B>
179        + VecZnxFillUniform
180        + GLWESub,
181    ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
182    Scratch<B>: ScratchAvailable + ScratchTakeCore<B>,
183{
184    let base2k: usize = 8;
185    let k_ct: usize = 54;
186
187    for rank in 1_usize..3 {
188        let n: usize = module.n();
189
190        let glwe_infos: GLWELayout = GLWELayout {
191            n: n.into(),
192            base2k: base2k.into(),
193            k: k_ct.into(),
194            rank: rank.into(),
195        };
196
197        let mut pt: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &glwe_infos);
198
199        let mut source_xs: Source = Source::new([0u8; 32]);
200        let mut source_xe: Source = Source::new([1u8; 32]);
201        let mut source_xa: Source = Source::new([0u8; 32]);
202
203        let mut scratch: ScratchOwned<B> =
204            ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, &glwe_infos) | GLWE::encrypt_sk_tmp_bytes(module, &glwe_infos));
205
206        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &glwe_infos);
207        sk.fill_ternary_prob(0.5, &mut source_xs);
208
209        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, rank.into());
210        sk_prepared.prepare(module, &sk);
211
212        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(module, &glwe_infos);
213
214        ct.encrypt_zero_sk(
215            module,
216            &sk_prepared,
217            &mut source_xa,
218            &mut source_xe,
219            scratch.borrow(),
220        );
221        ct.decrypt(module, &mut pt, &sk_prepared, scratch.borrow());
222
223        assert!((SIGMA - pt.data.std(base2k, 0) * (k_ct as f64).exp2()) <= 0.2);
224    }
225}
226
227pub fn test_glwe_encrypt_pk<B: Backend>(module: &Module<B>)
228where
229    Module<B>: GLWEAlloc
230        + GLWEEncryptPk<B>
231        + GLWEPublicKeyPrepare<B>
232        + GLWEPublicKeyPreparedAlloc<B>
233        + GLWEPublicKeyGenerate<B>
234        + GLWEDecrypt<B>
235        + GLWESecretPreparedAlloc<B>
236        + GLWESecretPrepare<B>
237        + VecZnxFillUniform
238        + GLWESub,
239    ScratchOwned<B>: ScratchOwnedAlloc<B> + ScratchOwnedBorrow<B>,
240    Scratch<B>: ScratchAvailable + ScratchTakeCore<B>,
241{
242    let base2k: usize = 8;
243    let k_ct: usize = 54;
244
245    for rank in 1_usize..3 {
246        let n: usize = module.n();
247
248        let glwe_infos: GLWELayout = GLWELayout {
249            n: n.into(),
250            base2k: base2k.into(),
251            k: k_ct.into(),
252            rank: rank.into(),
253        };
254
255        let mut ct: GLWE<Vec<u8>> = GLWE::alloc_from_infos(module, &glwe_infos);
256        let mut pt_have: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &glwe_infos);
257        let mut pt_want: GLWEPlaintext<Vec<u8>> = GLWEPlaintext::alloc_from_infos(module, &glwe_infos);
258
259        let mut source_xs: Source = Source::new([0u8; 32]);
260        let mut source_xe: Source = Source::new([0u8; 32]);
261        let mut source_xa: Source = Source::new([0u8; 32]);
262        let mut source_xu: Source = Source::new([0u8; 32]);
263
264        let mut scratch: ScratchOwned<B> =
265            ScratchOwned::alloc(GLWE::decrypt_tmp_bytes(module, &glwe_infos) | GLWE::encrypt_pk_tmp_bytes(module, &glwe_infos));
266
267        let mut sk: GLWESecret<Vec<u8>> = GLWESecret::alloc_from_infos(module, &glwe_infos);
268        sk.fill_ternary_prob(0.5, &mut source_xs);
269
270        let mut sk_prepared: GLWESecretPrepared<Vec<u8>, B> = GLWESecretPrepared::alloc(module, rank.into());
271        sk_prepared.prepare(module, &sk);
272
273        let mut pk: GLWEPublicKey<Vec<u8>> = GLWEPublicKey::alloc_from_infos(module, &glwe_infos);
274        pk.generate(module, &sk_prepared, &mut source_xa, &mut source_xe);
275
276        module.vec_znx_fill_uniform(base2k, &mut pt_want.data, 0, &mut source_xa);
277
278        let mut pk_prepared: GLWEPublicKeyPrepared<Vec<u8>, B> = GLWEPublicKeyPrepared::alloc_from_infos(module, &glwe_infos);
279        pk_prepared.prepare(module, &pk);
280
281        ct.encrypt_pk(
282            module,
283            &pt_want,
284            &pk_prepared,
285            &mut source_xu,
286            &mut source_xe,
287            scratch.borrow(),
288        );
289
290        ct.decrypt(module, &mut pt_have, &sk_prepared, scratch.borrow());
291
292        module.glwe_sub_inplace(&mut pt_want, &pt_have);
293
294        let noise_have: f64 = pt_want.data.std(base2k, 0).log2();
295        let noise_want: f64 = ((((rank as f64) + 1.0) * n as f64 * 0.5 * SIGMA * SIGMA).sqrt()).log2() - (k_ct as f64);
296
297        assert!(
298            noise_have <= noise_want + 0.2,
299            "{noise_have} <= {}",
300            noise_want + 0.2
301        );
302    }
303}