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