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