|
@ -1,9 +1,11 @@ |
|
|
|
|
|
use itertools::izip;
|
|
|
|
|
|
|
|
|
use crate::{
|
|
|
use crate::{
|
|
|
backend::{GetModulus, VectorOps},
|
|
|
backend::{GetModulus, VectorOps},
|
|
|
ntt::Ntt,
|
|
|
|
|
|
|
|
|
ntt::{self, Ntt},
|
|
|
random::{NewWithSeed, RandomFillGaussianInModulus, RandomFillUniformInModulus},
|
|
|
random::{NewWithSeed, RandomFillGaussianInModulus, RandomFillUniformInModulus},
|
|
|
utils::TryConvertFrom1,
|
|
|
utils::TryConvertFrom1,
|
|
|
Matrix, Row, RowEntity, RowMut,
|
|
|
|
|
|
|
|
|
Decomposer, Matrix, MatrixEntity, MatrixMut, Row, RowEntity, RowMut,
|
|
|
};
|
|
|
};
|
|
|
|
|
|
|
|
|
pub(crate) fn public_key_share<
|
|
|
pub(crate) fn public_key_share<
|
|
@ -45,3 +47,149 @@ pub(crate) fn public_key_share< |
|
|
RandomFillGaussianInModulus::random_fill(rng, &q, share_out.as_mut());
|
|
|
RandomFillGaussianInModulus::random_fill(rng, &q, share_out.as_mut());
|
|
|
modop.elwise_add_mut(share_out.as_mut(), s.as_ref()); // s*e + e
|
|
|
modop.elwise_add_mut(share_out.as_mut(), s.as_ref()); // s*e + e
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn non_interactive_rgsw_ct<
|
|
|
|
|
|
M: MatrixMut + MatrixEntity,
|
|
|
|
|
|
S,
|
|
|
|
|
|
PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,
|
|
|
|
|
|
Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>,
|
|
|
|
|
|
NttOp: Ntt<Element = M::MatElement>,
|
|
|
|
|
|
ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>,
|
|
|
|
|
|
>(
|
|
|
|
|
|
s: &[S],
|
|
|
|
|
|
ephemeral_u: &[S],
|
|
|
|
|
|
m: &[M::MatElement],
|
|
|
|
|
|
gadget_vec: &[M::MatElement],
|
|
|
|
|
|
p_rng: &mut PRng,
|
|
|
|
|
|
rng: &mut Rng,
|
|
|
|
|
|
nttop: &NttOp,
|
|
|
|
|
|
modop: &ModOp,
|
|
|
|
|
|
) -> (M, M)
|
|
|
|
|
|
where
|
|
|
|
|
|
<M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity,
|
|
|
|
|
|
M::MatElement: Copy,
|
|
|
|
|
|
{
|
|
|
|
|
|
assert_eq!(s.len(), ephemeral_u.len());
|
|
|
|
|
|
assert_eq!(s.len(), m.len());
|
|
|
|
|
|
let q = modop.modulus();
|
|
|
|
|
|
let d = gadget_vec.len();
|
|
|
|
|
|
let ring_size = s.len();
|
|
|
|
|
|
|
|
|
|
|
|
let mut s_poly_eval = M::R::try_convert_from(s, q);
|
|
|
|
|
|
let mut u_poly_eval = M::R::try_convert_from(ephemeral_u, q);
|
|
|
|
|
|
nttop.forward(s_poly_eval.as_mut());
|
|
|
|
|
|
nttop.forward(u_poly_eval.as_mut());
|
|
|
|
|
|
|
|
|
|
|
|
// encryptions of a_i*u + e + \beta m
|
|
|
|
|
|
let mut enc_beta_m = M::zeros(d, ring_size);
|
|
|
|
|
|
// zero encrypition: a_i*s + e'
|
|
|
|
|
|
let mut zero_encryptions = M::zeros(d, ring_size);
|
|
|
|
|
|
|
|
|
|
|
|
let mut scratch_space = M::R::zeros(ring_size);
|
|
|
|
|
|
|
|
|
|
|
|
izip!(
|
|
|
|
|
|
enc_beta_m.iter_rows_mut(),
|
|
|
|
|
|
zero_encryptions.iter_rows_mut(),
|
|
|
|
|
|
gadget_vec.iter()
|
|
|
|
|
|
)
|
|
|
|
|
|
.for_each(|(e_beta_m, e_zero, beta)| {
|
|
|
|
|
|
// sample a_i
|
|
|
|
|
|
RandomFillUniformInModulus::random_fill(p_rng, q, e_beta_m.as_mut());
|
|
|
|
|
|
e_zero.as_mut().copy_from_slice(e_beta_m.as_ref());
|
|
|
|
|
|
|
|
|
|
|
|
// a_i * u + \beta m + e //
|
|
|
|
|
|
// a_i * u
|
|
|
|
|
|
nttop.forward(e_beta_m.as_mut());
|
|
|
|
|
|
modop.elwise_mul_mut(e_beta_m.as_mut(), u_poly_eval.as_ref());
|
|
|
|
|
|
nttop.backward(e_beta_m.as_mut());
|
|
|
|
|
|
// sample error e
|
|
|
|
|
|
RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
|
|
|
|
|
|
// a_i * u + e
|
|
|
|
|
|
modop.elwise_add_mut(e_beta_m.as_mut(), scratch_space.as_ref());
|
|
|
|
|
|
// beta * m
|
|
|
|
|
|
modop.elwise_scalar_mul(scratch_space.as_mut(), m.as_ref(), beta);
|
|
|
|
|
|
// a_i * u + e + \beta m
|
|
|
|
|
|
modop.elwise_add_mut(e_beta_m.as_mut(), scratch_space.as_ref());
|
|
|
|
|
|
|
|
|
|
|
|
// a_i * s + e //
|
|
|
|
|
|
// a_i * s
|
|
|
|
|
|
nttop.forward(e_zero.as_mut());
|
|
|
|
|
|
modop.elwise_mul_mut(e_zero.as_mut(), s_poly_eval.as_ref());
|
|
|
|
|
|
nttop.backward(e_zero.as_mut());
|
|
|
|
|
|
// sample error e
|
|
|
|
|
|
RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
|
|
|
|
|
|
// a_i * s + e
|
|
|
|
|
|
modop.elwise_add_mut(e_zero.as_mut(), scratch_space.as_ref());
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
(enc_beta_m, zero_encryptions)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn non_interactive_ksk_gen<
|
|
|
|
|
|
M: MatrixMut + MatrixEntity,
|
|
|
|
|
|
S,
|
|
|
|
|
|
PRng: RandomFillUniformInModulus<[M::MatElement], ModOp::M>,
|
|
|
|
|
|
Rng: RandomFillGaussianInModulus<[M::MatElement], ModOp::M>,
|
|
|
|
|
|
NttOp: Ntt<Element = M::MatElement>,
|
|
|
|
|
|
ModOp: VectorOps<Element = M::MatElement> + GetModulus<Element = M::MatElement>,
|
|
|
|
|
|
>(
|
|
|
|
|
|
s: &[S],
|
|
|
|
|
|
ephemeral_u: &[S],
|
|
|
|
|
|
gadget_vec: &[M::MatElement],
|
|
|
|
|
|
p_rng: &mut PRng,
|
|
|
|
|
|
rng: &mut Rng,
|
|
|
|
|
|
nttop: &NttOp,
|
|
|
|
|
|
modop: &ModOp,
|
|
|
|
|
|
) where
|
|
|
|
|
|
<M as Matrix>::R: RowMut + TryConvertFrom1<[S], ModOp::M> + RowEntity,
|
|
|
|
|
|
M::MatElement: Copy,
|
|
|
|
|
|
{
|
|
|
|
|
|
assert_eq!(s.len(), ephemeral_u.len());
|
|
|
|
|
|
|
|
|
|
|
|
let q = modop.modulus();
|
|
|
|
|
|
let d = gadget_vec.len();
|
|
|
|
|
|
let ring_size = s.len();
|
|
|
|
|
|
|
|
|
|
|
|
let mut s_poly_eval = M::R::try_convert_from(s, q);
|
|
|
|
|
|
nttop.forward(s_poly_eval.as_mut());
|
|
|
|
|
|
let u_poly = M::R::try_convert_from(ephemeral_u, q);
|
|
|
|
|
|
|
|
|
|
|
|
// a_i * s + \beta u + e
|
|
|
|
|
|
// a_i * s + e
|
|
|
|
|
|
let mut ksk = M::zeros(d, ring_size);
|
|
|
|
|
|
let mut zero_encs = M::zeros(d, ring_size);
|
|
|
|
|
|
|
|
|
|
|
|
let mut scratch_space = M::R::zeros(ring_size);
|
|
|
|
|
|
|
|
|
|
|
|
izip!(
|
|
|
|
|
|
ksk.iter_rows_mut(),
|
|
|
|
|
|
zero_encs.iter_rows_mut(),
|
|
|
|
|
|
gadget_vec.iter()
|
|
|
|
|
|
)
|
|
|
|
|
|
.for_each(|(e_ksk, e_zero, beta)| {
|
|
|
|
|
|
// sample a_i
|
|
|
|
|
|
RandomFillUniformInModulus::random_fill(p_rng, q, e_ksk.as_mut());
|
|
|
|
|
|
e_zero.as_mut().copy_from_slice(e_ksk.as_ref());
|
|
|
|
|
|
|
|
|
|
|
|
// a_i * s + e + beta u
|
|
|
|
|
|
nttop.forward(e_ksk.as_mut());
|
|
|
|
|
|
modop.elwise_mul_mut(e_ksk.as_mut(), s_poly_eval.as_ref());
|
|
|
|
|
|
nttop.backward(e_ksk.as_mut());
|
|
|
|
|
|
// sample error e
|
|
|
|
|
|
RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
|
|
|
|
|
|
// a_i * s + e
|
|
|
|
|
|
modop.elwise_add_mut(e_ksk.as_mut(), scratch_space.as_ref());
|
|
|
|
|
|
// \beta * u
|
|
|
|
|
|
modop.elwise_scalar_mul(scratch_space.as_mut(), u_poly.as_ref(), beta);
|
|
|
|
|
|
// a_i * s + e + \beta * u
|
|
|
|
|
|
modop.elwise_add_mut(e_ksk.as_mut(), scratch_space.as_ref());
|
|
|
|
|
|
|
|
|
|
|
|
// a_i * s + e
|
|
|
|
|
|
nttop.forward(e_zero.as_mut());
|
|
|
|
|
|
modop.elwise_mul_mut(e_zero.as_mut(), s_poly_eval.as_ref());
|
|
|
|
|
|
nttop.backward(e_zero.as_mut());
|
|
|
|
|
|
// sample error e
|
|
|
|
|
|
RandomFillGaussianInModulus::random_fill(rng, q, scratch_space.as_mut());
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|