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