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}