Skip to content

Commit

Permalink
Group mul inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Dec 19, 2024
1 parent 0b3e068 commit 5422f23
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 69 deletions.
30 changes: 21 additions & 9 deletions synedrion/src/cggmp21/interactive_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use super::{
sigma::{
AffGProof, AffGPublicInputs, AffGSecretInputs, DecProof, DecPublicInputs, DecSecretInputs, EncProof,
EncPublicInputs, EncSecretInputs, LogStarProof, LogStarPublicInputs, LogStarSecretInputs, MulProof,
MulStarProof,
MulPublicInputs, MulSecretInputs, MulStarProof,
},
};
use crate::{
Expand Down Expand Up @@ -1045,16 +1045,28 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round3<P, I> {

let p_mul = MulProof::<P>::new(
rng,
&secret_signed_from_scalar::<P>(&self.context.k),
&self.context.rho,
&rho,
pk,
cap_k,
cap_g,
&cap_h,
MulSecretInputs {
x: &secret_signed_from_scalar::<P>(&self.context.k),
rho_x: &self.context.rho,
rho: &rho,
},
MulPublicInputs {
pk,
cap_x: cap_k,
cap_y: cap_g,
cap_c: &cap_h,
},
&aux,
);
assert!(p_mul.verify(pk, cap_k, cap_g, &cap_h, &aux));
assert!(p_mul.verify(
MulPublicInputs {
pk,
cap_x: cap_k,
cap_y: cap_g,
cap_c: &cap_h
},
&aux
));

// Dec proof

Expand Down
2 changes: 1 addition & 1 deletion synedrion/src/cggmp21/sigma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub(crate) use enc::{EncProof, EncPublicInputs, EncSecretInputs};
pub(crate) use fac::FacProof;
pub(crate) use log_star::{LogStarProof, LogStarPublicInputs, LogStarSecretInputs};
pub(crate) use mod_::ModProof;
pub(crate) use mul::MulProof;
pub(crate) use mul::{MulProof, MulPublicInputs, MulSecretInputs};
pub(crate) use mul_star::MulStarProof;
pub(crate) use prm::PrmProof;
pub(crate) use sch::{SchCommitment, SchProof, SchSecret};
136 changes: 77 additions & 59 deletions synedrion/src/cggmp21/sigma/mul.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,27 @@ use crate::{

const HASH_TAG: &[u8] = b"P_mul";

pub(crate) struct MulSecretInputs<'a, P: SchemeParams> {
/// $x$ (technically any integer since it will be implicitly reduced modulo $q$ or $\phi(N)$,
/// but we limit its size to `Uint` since that's what we use in this library).
pub x: &'a SecretSigned<<P::Paillier as PaillierParams>::Uint>,
/// $\rho_x$, a Paillier randomizer for the public key $N$.
pub rho_x: &'a Randomizer<P::Paillier>,
/// $\rho$, a Paillier randomizer for the public key $N$.
pub rho: &'a Randomizer<P::Paillier>,
}

pub(crate) struct MulPublicInputs<'a, P: SchemeParams> {
/// Paillier public key $N$.
pub pk: &'a PublicKeyPaillier<P::Paillier>,
/// Paillier ciphertext $X = enc(x, \rho_x)$.
pub cap_x: &'a Ciphertext<P::Paillier>,
/// Paillier ciphertext $Y$ encrypted with $N$.
pub cap_y: &'a Ciphertext<P::Paillier>,
/// Paillier ciphertext $C = (Y (*) x) * \rho^N \mod N^2$.
pub cap_c: &'a Ciphertext<P::Paillier>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub(crate) struct MulProof<P: SchemeParams> {
e: PublicSigned<<P::Paillier as PaillierParams>::Uint>,
Expand All @@ -25,58 +46,38 @@ pub(crate) struct MulProof<P: SchemeParams> {
v: MaskedRandomizer<P::Paillier>,
}

/**
ZK proof: Paillier multiplication.
Secret inputs:
- $x$ (technically any integer since it will be implicitly reduced modulo $q$ or $\phi(N)$,
but we limit its size to `Uint` since that's what we use in this library),
- $\rho_x$, a Paillier randomizer for the public key $N$,
- $\rho$, a Paillier randomizer for the public key $N$.
Public inputs:
- Paillier public key $N$,
- Paillier ciphertext $X = enc(x, \rho_x)$,
- Paillier ciphertext $Y$ encrypted with $N$,
- Paillier ciphertext $C = (Y (*) x) * \rho^N \mod N^2$,
- Setup parameters ($\hat{N}$, $s$, $t$).
*/
/// ZK proof: Paillier multiplication.
impl<P: SchemeParams> MulProof<P> {
#[allow(clippy::too_many_arguments)]
pub fn new(
rng: &mut impl CryptoRngCore,
x: &SecretSigned<<P::Paillier as PaillierParams>::Uint>,
rho_x: &Randomizer<P::Paillier>,
rho: &Randomizer<P::Paillier>,
pk: &PublicKeyPaillier<P::Paillier>,
cap_x: &Ciphertext<P::Paillier>,
cap_y: &Ciphertext<P::Paillier>,
cap_c: &Ciphertext<P::Paillier>,
secret: MulSecretInputs<'_, P>,
public: MulPublicInputs<'_, P>,
aux: &impl Hashable,
) -> Self {
assert_eq!(cap_x.public_key(), pk);
assert_eq!(cap_y.public_key(), pk);
assert_eq!(cap_c.public_key(), pk);
assert_eq!(public.cap_x.public_key(), public.pk);
assert_eq!(public.cap_y.public_key(), public.pk);
assert_eq!(public.cap_c.public_key(), public.pk);

let alpha_uint = Secret::init_with(|| pk.random_invertible_residue(rng));
let alpha_uint = Secret::init_with(|| public.pk.random_invertible_residue(rng));
let alpha = SecretUnsigned::new(alpha_uint, <P::Paillier as PaillierParams>::MODULUS_BITS)
.expect("the value is bounded by `MODULUS_BITS` by construction");

let r = Randomizer::random(rng, pk);
let s = Randomizer::random(rng, pk);
let r = Randomizer::random(rng, public.pk);
let s = Randomizer::random(rng, public.pk);

let cap_a = (cap_y * &alpha).mul_randomizer(&r).to_wire();
let cap_b = Ciphertext::new_with_randomizer(pk, &alpha, &s).to_wire();
let cap_a = (public.cap_y * &alpha).mul_randomizer(&r).to_wire();
let cap_b = Ciphertext::new_with_randomizer(public.pk, &alpha, &s).to_wire();

let mut reader = XofHasher::new_with_dst(HASH_TAG)
// commitments
.chain(&cap_a)
.chain(&cap_b)
// public parameters
.chain(pk.as_wire())
.chain(&cap_x.to_wire())
.chain(&cap_y.to_wire())
.chain(&cap_c.to_wire())
.chain(public.pk.as_wire())
.chain(&public.cap_x.to_wire())
.chain(&public.cap_y.to_wire())
.chain(&public.cap_c.to_wire())
.chain(aux)
.finalize_to_reader();

Expand All @@ -87,10 +88,10 @@ impl<P: SchemeParams> MulProof<P> {
.to_wide()
.into_signed()
.expect("conversion to `WideUint` provides enough space for a sign bit")
+ x.mul_wide(&e))
+ secret.x.mul_wide(&e))
.to_public();
let u = rho.to_masked(&r, &e);
let v = rho_x.to_masked(&s, &e);
let u = secret.rho.to_masked(&r, &e);
let v = secret.rho_x.to_masked(&s, &e);

Self {
e,
Expand All @@ -102,27 +103,20 @@ impl<P: SchemeParams> MulProof<P> {
}
}

pub fn verify(
&self,
pk: &PublicKeyPaillier<P::Paillier>,
cap_x: &Ciphertext<P::Paillier>,
cap_y: &Ciphertext<P::Paillier>,
cap_c: &Ciphertext<P::Paillier>,
aux: &impl Hashable,
) -> bool {
assert_eq!(cap_x.public_key(), pk);
assert_eq!(cap_y.public_key(), pk);
assert_eq!(cap_c.public_key(), pk);
pub fn verify(&self, public: MulPublicInputs<'_, P>, aux: &impl Hashable) -> bool {
assert_eq!(public.cap_x.public_key(), public.pk);
assert_eq!(public.cap_y.public_key(), public.pk);
assert_eq!(public.cap_c.public_key(), public.pk);

let mut reader = XofHasher::new_with_dst(HASH_TAG)
// commitments
.chain(&self.cap_a)
.chain(&self.cap_b)
// public parameters
.chain(pk.as_wire())
.chain(&cap_x.to_wire())
.chain(&cap_y.to_wire())
.chain(&cap_c.to_wire())
.chain(public.pk.as_wire())
.chain(&public.cap_x.to_wire())
.chain(&public.cap_y.to_wire())
.chain(&public.cap_c.to_wire())
.chain(aux)
.finalize_to_reader();

Expand All @@ -134,14 +128,16 @@ impl<P: SchemeParams> MulProof<P> {
}

// Y^z u^N = A * C^e \mod N^2
if (cap_y * &self.z).mul_masked_randomizer(&self.u) != self.cap_a.to_precomputed(pk) + cap_c * &e {
if (public.cap_y * &self.z).mul_masked_randomizer(&self.u)
!= self.cap_a.to_precomputed(public.pk) + public.cap_c * &e
{
return false;
}

// enc(z, v) == B * X^e \mod N^2
// (Note: typo in the paper, it uses `c` and not `v` here)
if Ciphertext::new_public_with_randomizer_wide(pk, &self.z, &self.v)
!= self.cap_b.to_precomputed(pk) + cap_x * &e
if Ciphertext::new_public_with_randomizer_wide(public.pk, &self.z, &self.v)
!= self.cap_b.to_precomputed(public.pk) + public.cap_x * &e
{
return false;
}
Expand All @@ -154,7 +150,7 @@ impl<P: SchemeParams> MulProof<P> {
mod tests {
use rand_core::OsRng;

use super::MulProof;
use super::{MulProof, MulPublicInputs, MulSecretInputs};
use crate::{
cggmp21::{SchemeParams, TestParams},
paillier::{Ciphertext, Randomizer, SecretKeyPaillierWire},
Expand All @@ -180,7 +176,29 @@ mod tests {
let cap_y = Ciphertext::new_signed(&mut OsRng, pk, &y);
let cap_c = (&cap_y * &x).mul_randomizer(&rho);

let proof = MulProof::<Params>::new(&mut OsRng, &x, &rho_x, &rho, pk, &cap_x, &cap_y, &cap_c, &aux);
assert!(proof.verify(pk, &cap_x, &cap_y, &cap_c, &aux));
let proof = MulProof::<Params>::new(
&mut OsRng,
MulSecretInputs {
x: &x,
rho_x: &rho_x,
rho: &rho,
},
MulPublicInputs {
pk,
cap_x: &cap_x,
cap_y: &cap_y,
cap_c: &cap_c,
},
&aux,
);
assert!(proof.verify(
MulPublicInputs {
pk,
cap_x: &cap_x,
cap_y: &cap_y,
cap_c: &cap_c
},
&aux
));
}
}

0 comments on commit 5422f23

Please sign in to comment.