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