arnaucube
arnaucube/phantom-zonePublic Self-hosted repository
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}