Skip to content

Commit

Permalink
Better handling of Paillier randomizers
Browse files Browse the repository at this point in the history
  • Loading branch information
fjarri committed Dec 2, 2024
1 parent 1979be3 commit 5f154ac
Show file tree
Hide file tree
Showing 13 changed files with 256 additions and 175 deletions.
6 changes: 3 additions & 3 deletions synedrion/src/cggmp21/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
cggmp21::SchemeParams,
curve::{secret_split, Point, Scalar},
paillier::{
Ciphertext, PaillierParams, PublicKeyPaillier, PublicKeyPaillierWire, RPParams, RPParamsWire, RandomizerWire,
Ciphertext, PaillierParams, PublicKeyPaillier, PublicKeyPaillierWire, RPParams, RPParamsWire, Randomizer,
SecretKeyPaillier, SecretKeyPaillierWire,
},
tools::Secret,
Expand Down Expand Up @@ -113,8 +113,8 @@ pub(crate) struct PresigningData<P: SchemeParams, I> {
#[derive(Debug, Clone)]
pub(crate) struct PresigningValues<P: SchemeParams> {
pub(crate) hat_beta: Secret<Signed<<P::Paillier as PaillierParams>::Uint>>,
pub(crate) hat_r: RandomizerWire<P::Paillier>,
pub(crate) hat_s: RandomizerWire<P::Paillier>,
pub(crate) hat_r: Randomizer<P::Paillier>,
pub(crate) hat_s: Randomizer<P::Paillier>,
pub(crate) cap_k: Ciphertext<P::Paillier>,
/// Received $\hat{D}_{i,j}$.
pub(crate) hat_cap_d_received: Ciphertext<P::Paillier>,
Expand Down
52 changes: 26 additions & 26 deletions synedrion/src/cggmp21/interactive_signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use super::{
};
use crate::{
curve::{Point, RecoverableSignature, Scalar},
paillier::{Ciphertext, CiphertextWire, PaillierParams, Randomizer, RandomizerWire},
paillier::{Ciphertext, CiphertextWire, PaillierParams, Randomizer},
tools::{
hashing::{Chain, FofHasher, HashOutput},
DowncastMap, Secret, Without,
Expand Down Expand Up @@ -162,10 +162,10 @@ impl<P: SchemeParams, I: PartyId> EntryPoint<I> for InteractiveSigning<P, I> {
let pk = aux_info.secret_aux.paillier_sk.public_key();

let nu = Randomizer::<P::Paillier>::random(rng, pk);
let cap_g = Ciphertext::new_with_randomizer(pk, &secret_uint_from_scalar::<P>(&gamma), &nu.to_wire());
let cap_g = Ciphertext::new_with_randomizer(pk, &secret_uint_from_scalar::<P>(&gamma), &nu);

let rho = Randomizer::<P::Paillier>::random(rng, pk);
let cap_k = Ciphertext::new_with_randomizer(pk, &secret_uint_from_scalar::<P>(&k), &rho.to_wire());
let cap_k = Ciphertext::new_with_randomizer(pk, &secret_uint_from_scalar::<P>(&k), &rho);

Ok(BoxedRound::new_dynamic(Round1 {
context: Context {
Expand Down Expand Up @@ -391,10 +391,10 @@ struct Round2Message<P: SchemeParams> {
struct Round2Artifact<P: SchemeParams> {
beta: Secret<Signed<<P::Paillier as PaillierParams>::Uint>>,
hat_beta: Secret<Signed<<P::Paillier as PaillierParams>::Uint>>,
r: RandomizerWire<P::Paillier>,
s: RandomizerWire<P::Paillier>,
hat_r: RandomizerWire<P::Paillier>,
hat_s: RandomizerWire<P::Paillier>,
r: Randomizer<P::Paillier>,
s: Randomizer<P::Paillier>,
hat_r: Randomizer<P::Paillier>,
hat_s: Randomizer<P::Paillier>,
cap_d: Ciphertext<P::Paillier>,
cap_f: Ciphertext<P::Paillier>,
hat_cap_d: Ciphertext<P::Paillier>,
Expand Down Expand Up @@ -451,14 +451,14 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round2<P, I> {
let gamma = secret_signed_from_scalar::<P>(&self.context.gamma);
let x = secret_signed_from_scalar::<P>(&self.context.key_share.secret_share);

let cap_f = Ciphertext::new_with_randomizer_signed(pk, &beta, &r.to_wire());
let cap_d = &self.all_cap_k[destination] * &gamma
+ Ciphertext::new_with_randomizer_signed(target_pk, &-&beta, &s.to_wire());
let cap_f = Ciphertext::new_with_randomizer_signed(pk, &beta, &r);
let cap_d =
&self.all_cap_k[destination] * &gamma + Ciphertext::new_with_randomizer_signed(target_pk, &-&beta, &s);

let hat_cap_f = Ciphertext::new_with_randomizer_signed(pk, &hat_beta, &hat_r.to_wire());
let hat_cap_f = Ciphertext::new_with_randomizer_signed(pk, &hat_beta, &hat_r);
let hat_cap_d = &self.all_cap_k[destination]
* secret_signed_from_scalar::<P>(&self.context.key_share.secret_share)
+ Ciphertext::new_with_randomizer_signed(target_pk, &-&hat_beta, &hat_s.to_wire());
+ Ciphertext::new_with_randomizer_signed(target_pk, &-&hat_beta, &hat_s);

let public_aux = &self.context.aux_info.public_aux[destination];
let rp = &public_aux.rp_params;
Expand All @@ -467,8 +467,8 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round2<P, I> {
rng,
&gamma,
&beta,
s.clone(),
r.clone(),
&s,
&r,
target_pk,
pk,
&self.all_cap_k[destination],
Expand All @@ -483,8 +483,8 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round2<P, I> {
rng,
&x,
&hat_beta,
hat_s.clone(),
hat_r.clone(),
&hat_s,
&hat_r,
target_pk,
pk,
&self.all_cap_k[destination],
Expand Down Expand Up @@ -524,10 +524,10 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round2<P, I> {
let artifact = Artifact::new(Round2Artifact::<P> {
beta,
hat_beta,
r: r.to_wire(),
s: s.to_wire(),
hat_r: hat_r.to_wire(),
hat_s: hat_s.to_wire(),
r,
s,
hat_r,
hat_s,
cap_d,
cap_f,
hat_cap_d,
Expand Down Expand Up @@ -889,8 +889,8 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round3<P, I> {
rng,
&secret_signed_from_scalar::<P>(&self.context.gamma),

Check warning on line 890 in synedrion/src/cggmp21/interactive_signing.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/interactive_signing.rs#L890

Added line #L890 was not covered by tests
beta,
s.to_precomputed(target_pk),
r.to_precomputed(pk),
s,
r,

Check warning on line 893 in synedrion/src/cggmp21/interactive_signing.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/interactive_signing.rs#L892-L893

Added lines #L892 - L893 were not covered by tests
target_pk,
pk,
&self.all_cap_k[id_j],
Expand Down Expand Up @@ -920,7 +920,7 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round3<P, I> {

let rho = Randomizer::random(rng, pk);
let cap_h = (&self.all_cap_g[&self.context.my_id] * secret_bounded_from_scalar::<P>(&self.context.k))
.mul_randomizer(&rho.to_wire());
.mul_randomizer(&rho);

Check warning on line 923 in synedrion/src/cggmp21/interactive_signing.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/interactive_signing.rs#L922-L923

Added lines #L922 - L923 were not covered by tests

let p_mul = MulProof::<P>::new(
rng,
Expand Down Expand Up @@ -1115,8 +1115,8 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round4<P, I> {
rng,
&secret_signed_from_scalar::<P>(&self.context.key_share.secret_share),
&values.hat_beta,
values.hat_s.to_precomputed(target_pk),
values.hat_r.to_precomputed(pk),
&values.hat_s,
&values.hat_r,
target_pk,
pk,
&values.cap_k,
Expand Down Expand Up @@ -1148,7 +1148,7 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round4<P, I> {
let cap_x = self.context.key_share.public_shares[&my_id];

let rho = Randomizer::random(rng, pk);
let hat_cap_h = (&self.presigning.cap_k * secret_bounded_from_scalar::<P>(x)).mul_randomizer(&rho.to_wire());
let hat_cap_h = (&self.presigning.cap_k * secret_bounded_from_scalar::<P>(x)).mul_randomizer(&rho);

let aux = (&self.context.ssid_hash, &my_id);

Expand Down
8 changes: 4 additions & 4 deletions synedrion/src/cggmp21/key_refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use super::{
use crate::{
curve::{secret_split, Point, Scalar},
paillier::{
Ciphertext, CiphertextWire, PublicKeyPaillier, PublicKeyPaillierWire, RPParams, RPParamsWire, RPSecret,
RandomizerWire, SecretKeyPaillier, SecretKeyPaillierWire,
Ciphertext, CiphertextWire, PaillierParams, PublicKeyPaillier, PublicKeyPaillierWire, RPParams, RPParamsWire,
RPSecret, SecretKeyPaillier, SecretKeyPaillierWire,
},
tools::{
bitvec::BitVec,
Expand Down Expand Up @@ -69,7 +69,7 @@ enum KeyRefreshErrorEnum<P: SchemeParams> {
Round3MismatchedSecret {
cap_c: CiphertextWire<P::Paillier>,
x: Scalar,
mu: RandomizerWire<P::Paillier>,
mu: <P::Paillier as PaillierParams>::Uint,
},
}

Expand Down Expand Up @@ -660,7 +660,7 @@ impl<P: SchemeParams, I: PartyId> Round<I> for Round3<P, I> {
KeyRefreshErrorEnum::Round3MismatchedSecret {
cap_c: direct_message.data2.paillier_enc_x,
x: *x.expose_secret(),
mu: mu.to_wire(),
mu: mu.expose(),

Check warning on line 663 in synedrion/src/cggmp21/key_refresh.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/key_refresh.rs#L662-L663

Added lines #L662 - L663 were not covered by tests
},
)));
}
Expand Down
46 changes: 23 additions & 23 deletions synedrion/src/cggmp21/sigma/aff_g.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use super::super::{
use crate::{
curve::Point,
paillier::{
Ciphertext, CiphertextWire, PaillierParams, PublicKeyPaillier, RPCommitmentWire, RPParams, Randomizer,
RandomizerWire,
Ciphertext, CiphertextWire, MaskedRandomizer, PaillierParams, PublicKeyPaillier, RPCommitmentWire, RPParams,
Randomizer,
},
tools::{
hashing::{Chain, Hashable, XofHasher},
Expand Down Expand Up @@ -58,8 +58,8 @@ pub(crate) struct AffGProof<P: SchemeParams> {
z2: Signed<<P::Paillier as PaillierParams>::Uint>,
z3: Signed<<P::Paillier as PaillierParams>::WideUint>,
z4: Signed<<P::Paillier as PaillierParams>::WideUint>,
omega: RandomizerWire<P::Paillier>,
omega_y: RandomizerWire<P::Paillier>,
omega: MaskedRandomizer<P::Paillier>,
omega_y: MaskedRandomizer<P::Paillier>,
}

impl<P: SchemeParams> AffGProof<P> {
Expand All @@ -68,8 +68,8 @@ impl<P: SchemeParams> AffGProof<P> {
rng: &mut impl CryptoRngCore,
x: &Secret<Signed<<P::Paillier as PaillierParams>::Uint>>,
y: &Secret<Signed<<P::Paillier as PaillierParams>::Uint>>,
rho: Randomizer<P::Paillier>,
rho_y: Randomizer<P::Paillier>,
rho: &Randomizer<P::Paillier>,
rho_y: &Randomizer<P::Paillier>,
pk0: &PublicKeyPaillier<P::Paillier>,
pk1: &PublicKeyPaillier<P::Paillier>,
cap_c: &Ciphertext<P::Paillier>,
Expand All @@ -90,17 +90,17 @@ impl<P: SchemeParams> AffGProof<P> {
let alpha = Secret::init_with(|| Signed::random_bounded_bits(rng, P::L_BOUND + P::EPS_BOUND));
let beta = Secret::init_with(|| Signed::random_bounded_bits(rng, P::LP_BOUND + P::EPS_BOUND));

let r_mod = Randomizer::random(rng, pk0);
let r_y_mod = Randomizer::random(rng, pk1);
let r = Randomizer::random(rng, pk0);
let r_y = Randomizer::random(rng, pk1);

let gamma = Secret::init_with(|| Signed::random_bounded_bits_scaled(rng, P::L_BOUND + P::EPS_BOUND, hat_cap_n));
let m = Secret::init_with(|| Signed::random_bounded_bits_scaled(rng, P::L_BOUND, hat_cap_n));
let delta = Secret::init_with(|| Signed::random_bounded_bits_scaled(rng, P::L_BOUND + P::EPS_BOUND, hat_cap_n));
let mu = Secret::init_with(|| Signed::random_bounded_bits_scaled(rng, P::L_BOUND, hat_cap_n));

let cap_a = (cap_c * &alpha + Ciphertext::new_with_randomizer_signed(pk0, &beta, &r_mod.to_wire())).to_wire();
let cap_a = (cap_c * &alpha + Ciphertext::new_with_randomizer_signed(pk0, &beta, &r)).to_wire();
let cap_b_x = secret_scalar_from_signed::<P>(&alpha).mul_by_generator();
let cap_b_y = Ciphertext::new_with_randomizer_signed(pk1, &beta, &r_y_mod.to_wire()).to_wire();
let cap_b_y = Ciphertext::new_with_randomizer_signed(pk1, &beta, &r_y).to_wire();
let cap_e = setup.commit(&alpha, &gamma).to_wire();
let cap_s = setup.commit(x, &m).to_wire();
let cap_f = setup.commit(&beta, &delta).to_wire();
Expand Down Expand Up @@ -145,12 +145,12 @@ impl<P: SchemeParams> AffGProof<P> {
let z3 = *(gamma + m * e_wide).expose_secret();
let z4 = *(delta + mu * e_wide).expose_secret();

let omega = rho.to_public(&r_mod, &e);
let omega = rho.to_masked(&r, &e);

// NOTE: deviation from the paper to support a different $D$
// (see the comment in `AffGProof`)
// Original: $\rho_y^e$. Modified: $\rho_y^{-e}$.
let omega_y = rho_y.to_public(&r_y_mod, &-e);
let omega_y = rho_y.to_masked(&r_y, &-e);

Self {
e,
Expand Down Expand Up @@ -225,7 +225,7 @@ impl<P: SchemeParams> AffGProof<P> {

// C^{z_1} (1 + N_0)^{z_2} \omega^{N_0} = A D^e \mod N_0^2
// => C (*) z_1 (+) encrypt_0(z_2, \omega) = A (+) D (*) e
if cap_c * self.z1 + Ciphertext::new_nonsecret_with_randomizer_signed(pk0, &self.z2, &self.omega)
if cap_c * self.z1 + Ciphertext::new_public_with_randomizer_signed(pk0, &self.z2, &self.omega)
!= cap_d * e + self.cap_a.to_precomputed(pk0)
{
return false;
Expand All @@ -241,23 +241,23 @@ impl<P: SchemeParams> AffGProof<P> {
// Original: `Y^e`. Modified `Y^{-e}`.
// (1 + N_1)^{z_2} \omega_y^{N_1} = B_y Y^(-e) \mod N_1^2
// => encrypt_1(z_2, \omega_y) = B_y (+) Y (*) (-e)
if Ciphertext::new_nonsecret_with_randomizer_signed(pk1, &self.z2, &self.omega_y)
if Ciphertext::new_public_with_randomizer_signed(pk1, &self.z2, &self.omega_y)
!= cap_y * (-e) + self.cap_b_y.to_precomputed(pk1)
{
return false;
}

// s^{z_1} t^{z_3} = E S^e \mod \hat{N}
let cap_e_mod = self.cap_e.to_precomputed(setup);
let cap_s_mod = self.cap_s.to_precomputed(setup);
if setup.commit_public(&self.z1, &self.z3) != &cap_e_mod * &cap_s_mod.pow_signed_vartime(&e) {
let cap_e = self.cap_e.to_precomputed(setup);
let cap_s = self.cap_s.to_precomputed(setup);
if setup.commit_public(&self.z1, &self.z3) != &cap_e * &cap_s.pow_signed_vartime(&e) {
return false;
}

// s^{z_2} t^{z_4} = F T^e \mod \hat{N}
let cap_f_mod = self.cap_f.to_precomputed(setup);
let cap_t_mod = self.cap_t.to_precomputed(setup);
if setup.commit_public(&self.z2, &self.z4) != &cap_f_mod * &cap_t_mod.pow_signed_vartime(&e) {
let cap_f = self.cap_f.to_precomputed(setup);
let cap_t = self.cap_t.to_precomputed(setup);
if setup.commit_public(&self.z2, &self.z4) != &cap_f * &cap_t.pow_signed_vartime(&e) {
return false;
}

Expand Down Expand Up @@ -300,12 +300,12 @@ mod tests {
let secret = Secret::init_with(|| Signed::random_bounded_bits(&mut OsRng, Params::L_BOUND));
let cap_c = Ciphertext::new_signed(&mut OsRng, pk0, &secret);

let cap_d = &cap_c * &x + Ciphertext::new_with_randomizer_signed(pk0, &-&y, &rho.to_wire());
let cap_y = Ciphertext::new_with_randomizer_signed(pk1, &y, &rho_y.to_wire());
let cap_d = &cap_c * &x + Ciphertext::new_with_randomizer_signed(pk0, &-&y, &rho);
let cap_y = Ciphertext::new_with_randomizer_signed(pk1, &y, &rho_y);
let cap_x = secret_scalar_from_signed::<TestParams>(&x).mul_by_generator();

let proof = AffGProof::<Params>::new(
&mut OsRng, &x, &y, rho, rho_y, pk0, pk1, &cap_c, &cap_d, &cap_y, &cap_x, &rp_params, &aux,
&mut OsRng, &x, &y, &rho, &rho_y, pk0, pk1, &cap_c, &cap_d, &cap_y, &cap_x, &rp_params, &aux,
);
assert!(proof.verify(pk0, pk1, &cap_c, &cap_d, &cap_y, &cap_x, &rp_params, &aux));
}
Expand Down
20 changes: 10 additions & 10 deletions synedrion/src/cggmp21/sigma/dec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use super::super::{
use crate::{
curve::Scalar,
paillier::{
Ciphertext, CiphertextWire, PaillierParams, PublicKeyPaillier, RPCommitmentWire, RPParams, Randomizer,
RandomizerWire,
Ciphertext, CiphertextWire, MaskedRandomizer, PaillierParams, PublicKeyPaillier, RPCommitmentWire, RPParams,
Randomizer,
},
tools::hashing::{Chain, Hashable, XofHasher},
tools::Secret,
Expand Down Expand Up @@ -43,7 +43,7 @@ pub(crate) struct DecProof<P: SchemeParams> {
gamma: Scalar,
z1: Signed<<P::Paillier as PaillierParams>::WideUint>,
z2: Signed<<P::Paillier as PaillierParams>::WideUint>,
omega: RandomizerWire<P::Paillier>,
omega: MaskedRandomizer<P::Paillier>,
}

impl<P: SchemeParams> DecProof<P> {
Expand All @@ -69,7 +69,7 @@ impl<P: SchemeParams> DecProof<P> {

let cap_s = setup.commit(y, &mu).to_wire();
let cap_t = setup.commit(&alpha, &nu).to_wire();
let cap_a = Ciphertext::new_with_randomizer_signed(pk0, &alpha, &r.to_wire()).to_wire();
let cap_a = Ciphertext::new_with_randomizer_signed(pk0, &alpha, &r).to_wire();

// `alpha` is secret, but `gamma` only uncovers $\ell$ bits of `alpha`'s full $\ell + \eps$ bits,
// and it's transmitted to another node, so it can be considered public.
Expand Down Expand Up @@ -98,7 +98,7 @@ impl<P: SchemeParams> DecProof<P> {
let z1 = *(alpha.to_wide() + y.mul_wide(&e)).expose_secret();
let z2 = *(nu + mu * e.to_wide()).expose_secret();

let omega = rho.to_public(&r, &e);
let omega = rho.to_masked(&r, &e);

Self {
e,
Expand Down Expand Up @@ -144,7 +144,7 @@ impl<P: SchemeParams> DecProof<P> {
}

// enc(z_1, \omega) == A (+) C (*) e
if Ciphertext::new_nonsecret_with_randomizer_wide(pk0, &self.z1, &self.omega)
if Ciphertext::new_public_with_randomizer_wide(pk0, &self.z1, &self.omega)
!= self.cap_a.to_precomputed(pk0) + cap_c * e
{
return false;
Expand All @@ -156,9 +156,9 @@ impl<P: SchemeParams> DecProof<P> {
}

// s^{z_1} t^{z_2} == T S^e
let cap_s_mod = self.cap_s.to_precomputed(setup);
let cap_t_mod = self.cap_t.to_precomputed(setup);
if setup.commit_public_wide(&self.z1, &self.z2) != &cap_t_mod * &cap_s_mod.pow_signed_vartime(&e) {
let cap_s = self.cap_s.to_precomputed(setup);
let cap_t = self.cap_t.to_precomputed(setup);
if setup.commit_public_wide(&self.z1, &self.z2) != &cap_t * &cap_s.pow_signed_vartime(&e) {
return false;
}

Expand Down Expand Up @@ -195,7 +195,7 @@ mod tests {
let x = scalar_from_signed::<Params>(y.expose_secret());

let rho = Randomizer::random(&mut OsRng, pk);
let cap_c = Ciphertext::new_with_randomizer_signed(pk, &y, &rho.to_wire());
let cap_c = Ciphertext::new_with_randomizer_signed(pk, &y, &rho);

let proof = DecProof::<Params>::new(&mut OsRng, &y, &rho, pk, &x, &cap_c, &setup, &aux);
assert!(proof.verify(pk, &x, &cap_c, &setup, &aux));
Expand Down
Loading

0 comments on commit 5f154ac

Please sign in to comment.