phantom-zone/src/multi_party.rs
src/multi_party.rsRaw
1use itertools::izip;
2
3use crate::{
4 backend::{GetModulus, VectorOps},
5 ntt::{self, Ntt},
6 random::{NewWithSeed, RandomFillGaussianInModulus, RandomFillUniformInModulus},
7 utils::TryConvertFrom1,
8 Decomposer, Matrix, MatrixEntity, MatrixMut, Row, RowEntity, RowMut,
9};
10
11pub(crate) fn public_key_share<
12 R: Row + RowMut + RowEntity,
13 S,
14 ModOp: VectorOps<Element = R::Element> + GetModulus<Element = R::Element>,
15 NttOp: Ntt<Element = R::Element>,
16 Rng: RandomFillGaussianInModulus<[R::Element], ModOp::M>,
17 PRng: RandomFillUniformInModulus<[R::Element], ModOp::M>,
18>(
19 share_out: &mut R,
20 s_i: &[S],
21 modop: &ModOp,
22 nttop: &NttOp,
23 p_rng: &mut PRng,
24 rng: &mut Rng,
25) where
26 R: TryConvertFrom1<[S], ModOp::M>,
27{
28 let ring_size = share_out.as_ref().len();
29 assert!(s_i.len() == ring_size);
30
31 let q = modop.modulus();
32
33 // sample a
34 let mut a = {
35 let mut a = R::zeros(ring_size);
36 RandomFillUniformInModulus::random_fill(p_rng, &q, a.as_mut());
37 a
38 };
39
40 // s*a
41 nttop.forward(a.as_mut());
42 let mut s = R::try_convert_from(s_i, &q);
43 nttop.forward(s.as_mut());
44 modop.elwise_mul_mut(s.as_mut(), a.as_ref());
45 nttop.backward(s.as_mut());
46
47 RandomFillGaussianInModulus::random_fill(rng, &q, share_out.as_mut());
48 modop.elwise_add_mut(share_out.as_mut(), s.as_ref()); // s*e + e
49}
50
51fn non_interactive_rgsw_ct<
52 M: MatrixMut + MatrixEntity,
53 S,
54 PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,
55 Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>,
56 NttOp: Ntt<Element = M::MatElement>,
57 ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>,
58>(
59 s: &[S],
60 u: &[S],
61 m: &[M::MatElement],
62 gadget_vec: &[M::MatElement],
63 p_rng: &mut PRng,
64 rng: &mut Rng,
65 nttop: &NttOp,
66 modop: &ModOp,
67) -> (M, M)
68where
69 <M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity,
70 M::MatElement: Copy,
71{
72 assert_eq!(s.len(), u.len());
73 assert_eq!(s.len(), m.len());
74 let q = modop.modulus();
75 let d = gadget_vec.len();
76 let ring_size = s.len();
77
78 let mut s_poly_eval = M::R::try_convert_from(s, q);
79 let mut u_poly_eval = M::R::try_convert_from(u, q);
80 nttop.forward(s_poly_eval.as_mut());
81 nttop.forward(u_poly_eval.as_mut());
82
83 // encryptions of a_i*u + e + \beta m
84 let mut enc_beta_m = M::zeros(d, ring_size);
85 // zero encrypition: a_i*s + e'
86 let mut zero_encryptions = M::zeros(d, ring_size);
87
88 let mut scratch_space = M::R::zeros(ring_size);
89
90 izip!(
91 enc_beta_m.iter_rows_mut(),
92 zero_encryptions.iter_rows_mut(),
93 gadget_vec.iter()
94 )
95 .for_each(|(e_beta_m, e_zero, beta)| {
96 // sample a_i
97 RandomFillUniformInModulus::random_fill(p_rng, q, e_beta_m.as_mut());
98 e_zero.as_mut().copy_from_slice(e_beta_m.as_ref());
99
100 // a_i * u + \beta m + e //
101 // a_i * u
102 nttop.forward(e_beta_m.as_mut());
103 modop.elwise_mul_mut(e_beta_m.as_mut(), u_poly_eval.as_ref());
104 nttop.backward(e_beta_m.as_mut());
105 // sample error e
106 RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
107 // a_i * u + e
108 modop.elwise_add_mut(e_beta_m.as_mut(), scratch_space.as_ref());
109 // beta * m
110 modop.elwise_scalar_mul(scratch_space.as_mut(), m.as_ref(), beta);
111 // a_i * u + e + \beta m
112 modop.elwise_add_mut(e_beta_m.as_mut(), scratch_space.as_ref());
113
114 // a_i * s + e //
115 // a_i * s
116 nttop.forward(e_zero.as_mut());
117 modop.elwise_mul_mut(e_zero.as_mut(), s_poly_eval.as_ref());
118 nttop.backward(e_zero.as_mut());
119 // sample error e
120 RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
121 // a_i * s + e
122 modop.elwise_add_mut(e_zero.as_mut(), scratch_space.as_ref());
123 });
124
125 (enc_beta_m, zero_encryptions)
126}
127
128pub(crate) fn non_interactive_ksk_gen<
129 M: MatrixMut + MatrixEntity,
130 S,
131 PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,
132 Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>,
133 NttOp: Ntt<Element = M::MatElement>,
134 ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>,
135>(
136 s: &[S],
137 u: &[S],
138 gadget_vec: &[M::MatElement],
139 p_rng: &mut PRng,
140 rng: &mut Rng,
141 nttop: &NttOp,
142 modop: &ModOp,
143) where
144 <M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity,
145 M::MatElement: Copy,
146{
147 assert_eq!(s.len(), u.len());
148
149 let q = modop.modulus();
150 let d = gadget_vec.len();
151 let ring_size = s.len();
152
153 let mut s_poly_eval = M::R::try_convert_from(s, q);
154 nttop.forward(s_poly_eval.as_mut());
155 let u_poly = M::R::try_convert_from(u, q);
156
157 // a_i * s + \beta u + e
158 let mut ksk = M::zeros(d, ring_size);
159
160 let mut scratch_space = M::R::zeros(ring_size);
161
162 izip!(ksk.iter_rows_mut(), gadget_vec.iter()).for_each(|(e_ksk, beta)| {
163 // sample a_i
164 RandomFillUniformInModulus::random_fill(p_rng, q, e_ksk.as_mut());
165
166 // a_i * s + e + beta u
167 nttop.forward(e_ksk.as_mut());
168 modop.elwise_mul_mut(e_ksk.as_mut(), s_poly_eval.as_ref());
169 nttop.backward(e_ksk.as_mut());
170 // sample error e
171 RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
172 // a_i * s + e
173 modop.elwise_add_mut(e_ksk.as_mut(), scratch_space.as_ref());
174 // \beta * u
175 modop.elwise_scalar_mul(scratch_space.as_mut(), u_poly.as_ref(), beta);
176 // a_i * s + e + \beta * u
177 modop.elwise_add_mut(e_ksk.as_mut(), scratch_space.as_ref());
178 });
179}
180
181pub(crate) fn non_interactive_ksk_zero_encryptions_for_other_party_i<
182 M: MatrixMut + MatrixEntity,
183 S,
184 PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,
185 Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>,
186 NttOp: Ntt<Element = M::MatElement>,
187 ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>,
188>(
189 s: &[S],
190 gadget_vec: &[M::MatElement],
191 p_rng: &mut PRng,
192 rng: &mut Rng,
193 nttop: &NttOp,
194 modop: &ModOp,
195) -> M
196where
197 <M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity,
198 M::MatElement: Copy,
199{
200 let q = modop.modulus();
201 let d = gadget_vec.len();
202 let ring_size = s.len();
203
204 let mut s_poly_eval = M::R::try_convert_from(s, q);
205 nttop.forward(s_poly_eval.as_mut());
206
207 // a_i * s + e
208 let mut zero_encs = M::zeros(d, ring_size);
209
210 let mut scratch_space = M::R::zeros(ring_size);
211
212 izip!(zero_encs.iter_rows_mut()).for_each(|(e_zero)| {
213 // sample a_i
214 RandomFillUniformInModulus::random_fill(p_rng, q, e_zero.as_mut());
215
216 // a_i * s + e
217 nttop.forward(e_zero.as_mut());
218 modop.elwise_mul_mut(e_zero.as_mut(), s_poly_eval.as_ref());
219 nttop.backward(e_zero.as_mut());
220 // sample error e
221 RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
222 modop.elwise_add_mut(e_zero.as_mut(), scratch_space.as_ref());
223 });
224 zero_encs
225}