arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
phantom-zone/src/noise.rs
src/noise.rsRaw
  1#[cfg(test)]
  2mod tests {
  3    use itertools::{izip, Itertools};
  4    use num_traits::zero;
  5    use rand::{thread_rng, Rng};
  6
  7    use crate::{
  8        bool::keys::ClientKey,
  9        ntt,
 10        random::{
 11            DefaultSecureRng, RandomFill, RandomFillGaussianInModulus, RandomFillUniformInModulus,
 12        },
 13        utils::{
 14            fill_random_ternary_secret_with_hamming_weight, generate_prime, Stats, TryConvertFrom1,
 15        },
 16        ArithmeticOps, Decomposer, DefaultDecomposer, ModInit, ModularOpsU64, Ntt, NttBackendU64,
 17        NttInit, VectorOps,
 18    };
 19
 20    #[test]
 21    fn non_interactive_multi_party() {
 22        let logq = 56;
 23        let ring_size = 1usize << 11;
 24        let q = generate_prime(logq, 2 * ring_size as u64, 1 << logq).unwrap();
 25        let logb = 1;
 26        let d = 56;
 27        let decomposer = DefaultDecomposer::new(q, logb, d);
 28        let gadget_vec = decomposer.gadget_vector();
 29        let mut rng = DefaultSecureRng::new();
 30
 31        let modop = ModularOpsU64::new(q);
 32        let nttop = NttBackendU64::new(&q, ring_size);
 33
 34        let no_of_parties = 16;
 35        let client_secrets = (0..no_of_parties)
 36            .into_iter()
 37            .map(|_| {
 38                let mut sk = vec![0i64; ring_size];
 39                fill_random_ternary_secret_with_hamming_weight(&mut sk, ring_size >> 1, &mut rng);
 40                sk
 41            })
 42            .collect_vec();
 43
 44        let mut s_ideal = vec![0i64; ring_size];
 45        client_secrets.iter().for_each(|s| {
 46            izip!(s_ideal.iter_mut(), s.iter()).for_each(|(add_to, v)| {
 47                *add_to = *add_to + *v;
 48            });
 49        });
 50
 51        let sk_poly_ideal = Vec::<u64>::try_convert_from(s_ideal.as_slice(), &q);
 52        let mut sk_poly_ideal_eval = sk_poly_ideal.clone();
 53        nttop.forward(&mut sk_poly_ideal_eval);
 54
 55        let mut ksk_seed = [0u8; 32];
 56        rng.fill_bytes(&mut ksk_seed);
 57
 58        // zero encryptions for each party for ksk(u)
 59        let client_zero_encs = {
 60            client_secrets
 61                .iter()
 62                .map(|sk| {
 63                    let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
 64                    let mut sk_poly_eval = sk_poly.clone();
 65                    nttop.forward(sk_poly_eval.as_mut_slice());
 66
 67                    let mut zero_encs =
 68                        vec![vec![0u64; ring_size]; decomposer.decomposition_count()];
 69                    let mut ksk_prng = DefaultSecureRng::new_seeded(ksk_seed);
 70                    zero_encs.iter_mut().for_each(|out| {
 71                        RandomFillUniformInModulus::random_fill(
 72                            &mut ksk_prng,
 73                            &q,
 74                            out.as_mut_slice(),
 75                        );
 76                        nttop.forward(out.as_mut_slice());
 77                        modop.elwise_mul_mut(out.as_mut_slice(), &sk_poly_eval);
 78                        nttop.backward(out.as_mut_slice());
 79
 80                        let mut error = vec![0u64; ring_size];
 81                        RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
 82
 83                        modop.elwise_add_mut(out.as_mut_slice(), &error);
 84                    });
 85                    zero_encs
 86                })
 87                .collect_vec()
 88        };
 89
 90        // main values
 91        let main_a = {
 92            let mut a = vec![0u64; ring_size];
 93            RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut a);
 94            a
 95        };
 96        let main_m = {
 97            let mut main_m = vec![0u64; ring_size];
 98            RandomFillUniformInModulus::random_fill(&mut rng, &q, &mut main_m);
 99            main_m
100        };
101
102        let mut main_u = vec![0i64; ring_size];
103        fill_random_ternary_secret_with_hamming_weight(&mut main_u, ring_size >> 1, &mut rng);
104        let u_main_poly = Vec::<u64>::try_convert_from(main_u.as_slice(), &q);
105        let mut u_main_poly_eval = u_main_poly.clone();
106        nttop.forward(u_main_poly_eval.as_mut_slice());
107
108        // party 0
109        let (mut party0_ksk_u, mut rlwe_main_m_parta) = {
110            // party 0's secret
111            let sk = client_secrets[0].clone();
112            let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
113            let mut sk_poly_eval = sk_poly.clone();
114            nttop.forward(sk_poly_eval.as_mut_slice());
115
116            // `main_a*u + main_m` with ephemeral key u
117            let mut rlwe_main_m = main_a.clone();
118            nttop.forward(&mut rlwe_main_m);
119            modop.elwise_mul_mut(&mut rlwe_main_m, &u_main_poly_eval);
120            nttop.backward(&mut rlwe_main_m);
121            let mut error = vec![0u64; ring_size];
122            RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
123            modop.elwise_add_mut(&mut rlwe_main_m, &error);
124            modop.elwise_add_mut(&mut rlwe_main_m, &main_m);
125
126            // Generate KSK(u)
127            let mut ksk_prng = DefaultSecureRng::new_seeded(ksk_seed);
128            let mut ksk_u = vec![vec![0u64; ring_size]; 2 * decomposer.decomposition_count()];
129            let (ksk_u_a, ksk_u_b) = ksk_u.split_at_mut(decomposer.decomposition_count());
130            izip!(ksk_u_b.iter_mut(), ksk_u_a.iter_mut(), gadget_vec.iter()).for_each(
131                |(row_b, row_a, beta_i)| {
132                    // sample a
133                    RandomFillUniformInModulus::random_fill(&mut ksk_prng, &q, row_a.as_mut());
134
135                    // s_i * a
136                    let mut s_i_a = row_a.clone();
137                    nttop.forward(&mut s_i_a);
138                    modop.elwise_mul_mut(&mut s_i_a, &sk_poly_eval);
139                    nttop.backward(&mut s_i_a);
140
141                    // \beta * u
142                    let mut beta_u = u_main_poly.clone();
143                    modop.elwise_scalar_mul_mut(beta_u.as_mut_slice(), beta_i);
144
145                    // e
146                    RandomFillGaussianInModulus::random_fill(&mut rng, &q, row_b.as_mut_slice());
147                    // e + \beta * u
148                    modop.elwise_add_mut(row_b.as_mut_slice(), &beta_u);
149
150                    // b = e + \beta * u + a * s_i
151                    modop.elwise_add_mut(row_b.as_mut_slice(), &s_i_a);
152                },
153            );
154
155            // send ksk u from s_0 to s_{ideal}
156            ksk_u_b.iter_mut().enumerate().for_each(|(index, out_b)| {
157                // note: skip zero encryption of party 0
158                client_zero_encs.iter().skip(1).for_each(|encs| {
159                    modop.elwise_add_mut(out_b, &encs[index]);
160                });
161            });
162
163            // // put ksk in fourier domain
164            // ksk_u
165            //     .iter_mut()
166            //     .for_each(|r| nttop.forward(r.as_mut_slice()));
167            (ksk_u, rlwe_main_m)
168        };
169
170        // Check ksk_u is correct
171        // {
172        //     let (ksk_a, ksk_b) =
173        // party0_ksk_u.split_at_mut(decomposer.decomposition_count());
174        //     izip!(
175        //         ksk_a.iter(),
176        //         ksk_b.iter(),
177        //         decomposer.gadget_vector().iter()
178        //     )
179        //     .for_each(|(row_a, row_b, beta_i)| {
180        //         // a * s
181        //         let mut sa = row_a.clone();
182        //         nttop.forward(&mut sa);
183        //         modop.elwise_mul_mut(&mut sa, &sk_poly_ideal_eval);
184        //         nttop.backward(&mut sa);
185
186        //         // b - a*s
187        //         let mut out = sa;
188        //         modop.elwise_neg_mut(&mut out);
189        //         modop.elwise_add_mut(&mut out, row_b);
190
191        //         // beta * u
192        //         let mut expected = u_main_poly.clone();
193        //         modop.elwise_scalar_mul_mut(&mut expected, beta_i);
194        //         assert_eq!(expected, out);
195        //     });
196        // }
197
198        // RLWE(0) = main_a * s + e = \sum main_a*s_i + e_i
199        let rlwe_to_switch = {
200            let mut sum = vec![0u64; ring_size];
201            client_secrets.iter().for_each(|sk| {
202                let sk_poly = Vec::<u64>::try_convert_from(sk.as_slice(), &q);
203                let mut sk_poly_eval = sk_poly.clone();
204                nttop.forward(sk_poly_eval.as_mut_slice());
205
206                // a * s
207                let mut rlwe = main_a.clone();
208                nttop.forward(&mut rlwe);
209                modop.elwise_mul_mut(rlwe.as_mut_slice(), &sk_poly_eval);
210                nttop.backward(&mut rlwe);
211                // a * s + e
212                let mut error = vec![0u64; ring_size];
213                RandomFillGaussianInModulus::random_fill(&mut rng, &q, &mut error);
214                modop.elwise_add_mut(&mut rlwe, &error);
215
216                modop.elwise_add_mut(&mut sum, &rlwe);
217            });
218            sum
219        };
220        // {
221        //     let mut tmp = main_a.clone();
222        //     nttop.forward(&mut tmp);
223        //     modop.elwise_mul_mut(&mut tmp, &sk_poly_ideal_eval);
224        //     nttop.backward(&mut tmp);
225        //     assert_eq!(&rlwe_to_switch, &tmp);
226        // }
227
228        // Key switch \sum decomp<RLWE(0)> * KSK(i)
229        let mut decomp_rlwe = vec![vec![0u64; ring_size]; decomposer.decomposition_count()];
230        rlwe_to_switch.iter().enumerate().for_each(|(ri, el)| {
231            decomposer
232                .decompose_iter(el)
233                .enumerate()
234                .for_each(|(j, d_el)| {
235                    decomp_rlwe[j][ri] = d_el;
236                });
237        });
238
239        // put ksk_u and decomp<RLWE(main_a*s_ideal + e)> in fourier domain
240        decomp_rlwe
241            .iter_mut()
242            .for_each(|r| nttop.forward(r.as_mut_slice()));
243        party0_ksk_u
244            .iter_mut()
245            .for_each(|r| nttop.forward(r.as_mut_slice()));
246
247        let (ksk_u_a, ksk_u_b) = party0_ksk_u.split_at(decomposer.decomposition_count());
248        let mut rlwe_main_m_partb_eval = vec![vec![0u64; ring_size]; 2];
249        izip!(decomp_rlwe.iter(), ksk_u_a.iter(), ksk_u_b.iter()).for_each(|(o, a, b)| {
250            // A part
251            // rlwe[0] += o*a
252            izip!(rlwe_main_m_partb_eval[0].iter_mut(), o.iter(), a.iter()).for_each(
253                |(r, o, a)| {
254                    *r = modop.add(r, &modop.mul(o, a));
255                },
256            );
257
258            // B part
259            // rlwe[1] += o*b
260            izip!(rlwe_main_m_partb_eval[1].iter_mut(), o.iter(), b.iter()).for_each(
261                |(r, o, b)| {
262                    *r = modop.add(r, &modop.mul(o, b));
263                },
264            );
265        });
266
267        // construct RLWE_{s_{ideal}}(-sm)
268        nttop.forward(rlwe_main_m_parta.as_mut_slice());
269        modop.elwise_add_mut(&mut rlwe_main_m_partb_eval[0], &rlwe_main_m_parta);
270        let rlwe_main_m_eval = rlwe_main_m_partb_eval;
271
272        // decrypt RLWE_{s_{ideal}}(m) and check
273        let mut neg_s_m_main_out = rlwe_main_m_eval[0].clone();
274        modop.elwise_mul_mut(&mut neg_s_m_main_out, &sk_poly_ideal_eval);
275        modop.elwise_neg_mut(&mut neg_s_m_main_out);
276        modop.elwise_add_mut(&mut neg_s_m_main_out, &rlwe_main_m_eval[1]);
277        nttop.backward(&mut neg_s_m_main_out);
278
279        let mut neg_s_main_m = main_m.clone();
280        nttop.forward(&mut neg_s_main_m);
281        modop.elwise_mul_mut(&mut neg_s_main_m, &sk_poly_ideal_eval);
282        modop.elwise_neg_mut(&mut neg_s_main_m);
283        nttop.backward(&mut neg_s_main_m);
284
285        let mut diff = neg_s_m_main_out.clone();
286        modop.elwise_sub_mut(&mut diff, &neg_s_main_m);
287
288        let mut stat = Stats::new();
289        stat.add_more(&Vec::<i64>::try_convert_from(&diff, &q));
290        println!("Log2 Std: {}", stat.std_dev().abs().log2());
291    }
292}