Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SecretBox for all secret values #144

Merged
merged 26 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7b44069
Use more SecretBox-es
dvdplm Aug 23, 2024
7073b93
Remove TODO
dvdplm Aug 24, 2024
965aaf8
Use SecretBox for SecretKeyPaillier members
dvdplm Aug 24, 2024
bdeca27
CiphertextMod takes randomizer in a SecretBox
dvdplm Aug 24, 2024
1c668ef
SecretKeyPaillierPrecomputed::primes wrapped in SecretBox (and associ…
dvdplm Aug 26, 2024
7cdf476
SecretKeyPaillierPrecomputed::totient is wrapped in SecretBox
dvdplm Aug 26, 2024
1ca1671
Add comment on why `totient_nonzero` cannot be wrapped in a SecretBox…
dvdplm Aug 26, 2024
e4efcc1
Enable the `zeroize` feature of `crypto-bigint`
dvdplm Aug 27, 2024
1c28c15
SecretKeyPaillierPrecomputed::inv_totient is now wrapped in a `Secret…
dvdplm Aug 27, 2024
b388d9c
Cleanup
dvdplm Aug 27, 2024
5c107c6
Add question about commit_wide
dvdplm Aug 27, 2024
8ecd879
Impl Serialize for SecretKeyPaillier
dvdplm Aug 27, 2024
a0e9623
Make AffGProof rho and rho_y SecretBoxes
dvdplm Aug 27, 2024
28b36e9
Merge branch 'master' into dp-wrap-secrets-in-secretbox-77
dvdplm Aug 27, 2024
f4368b7
typo
dvdplm Aug 29, 2024
8e2ae99
Remove SecretBox around Randomizer and RandomizerMod given they are a…
dvdplm Sep 5, 2024
f72c393
Revert to passing references
dvdplm Sep 5, 2024
555cca7
Fix clippy complaints
dvdplm Sep 5, 2024
ed43266
Remove unneeded trait impls
dvdplm Sep 6, 2024
183bc7d
Test for debug output
dvdplm Sep 7, 2024
dcb95ce
Test secret paillier key serialization
dvdplm Sep 7, 2024
f5e4db8
Review feedback
dvdplm Sep 16, 2024
3386bb1
Impl PartialEq for SecretkeyPaillier
dvdplm Sep 16, 2024
01c7c03
Use secrecy 0.10
dvdplm Sep 18, 2024
5623b40
Merge branch 'master' into dp-wrap-secrets-in-secretbox-77
dvdplm Sep 26, 2024
66b313f
Cleanup
dvdplm Sep 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion synedrion/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,10 @@ displaydoc = { version = "0.2", default-features = false}
getrandom = { version = "0.2", features = ["js"]}

[dev-dependencies]
rand_chacha = "0.3"
serde_assert = "0.8"
tokio = { version = "1", features = ["rt", "sync", "time", "macros"] }
rand = "0.8"
rand_chacha = "0.3"
criterion = "0.5"
k256 = {version = "0.14.0-pre.2", default-features = false, features = ["ecdsa", "arithmetic", "pem", "serde"]}
impls = "1"
Expand Down
12 changes: 8 additions & 4 deletions synedrion/src/cggmp21/entities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub struct PresigningData<P: SchemeParams, I> {

#[derive(Debug, Clone)]
pub(crate) struct PresigningValues<P: SchemeParams> {
pub(crate) hat_beta: Signed<<P::Paillier as PaillierParams>::Uint>,
pub(crate) hat_beta: SecretBox<Signed<<P::Paillier as PaillierParams>::Uint>>,
pub(crate) hat_r: Randomizer<P::Paillier>,
pub(crate) hat_s: Randomizer<P::Paillier>,
pub(crate) cap_k: CiphertextMod<P::Paillier>,
Expand Down Expand Up @@ -276,7 +276,11 @@ impl<P: SchemeParams, I: Ord + Clone> AuxInfo<P, I> {
}
}

impl<P: SchemeParams, I: Ord + Clone + PartialEq> PresigningData<P, I> {
impl<P, I> PresigningData<P, I>
where
P: SchemeParams,
I: Ord + Clone + PartialEq,
{
/// Creates a consistent set of presigning data for testing purposes.
#[cfg(any(test, feature = "bench-internals"))]
pub(crate) fn new_centralized(
Expand Down Expand Up @@ -346,7 +350,7 @@ impl<P: SchemeParams, I: Ord + Clone + PartialEq> PresigningData<P, I> {
let id_ji = (id_j.clone(), id_i.clone());

hat_betas.insert(id_ij.clone(), hat_beta);
hat_ss.insert(id_ij.clone(), hat_s);
hat_ss.insert(id_ij.clone(), hat_s.clone());
hat_rs.insert(id_ij.clone(), hat_r);

hat_cap_ds.insert(id_ji.clone(), hat_cap_d);
Expand All @@ -368,7 +372,7 @@ impl<P: SchemeParams, I: Ord + Clone + PartialEq> PresigningData<P, I> {
values.insert(
id_j.clone(),
PresigningValues {
hat_beta: hat_betas[&id_ij],
hat_beta: SecretBox::new(Box::new(hat_betas[&id_ij])),
hat_r: hat_rs[&id_ij].clone(),
hat_s: hat_ss[&id_ij].clone(),
hat_cap_d_received: hat_cap_ds[&id_ij].clone(),
Expand Down
58 changes: 37 additions & 21 deletions synedrion/src/cggmp21/protocols/presigning.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,12 @@

#[derive(Debug, Clone)]
pub struct Round2Artifact<P: SchemeParams> {
beta: Signed<<P::Paillier as PaillierParams>::Uint>, // TODO (#77): secret
hat_beta: Signed<<P::Paillier as PaillierParams>::Uint>, // TODO (#77): secret
r: Randomizer<P::Paillier>, // TODO (#77): secret
s: Randomizer<P::Paillier>, // TODO (#77): secret
hat_r: Randomizer<P::Paillier>, // TODO (#77): secret
hat_s: Randomizer<P::Paillier>, // TODO (#77): secret
beta: SecretBox<Signed<<P::Paillier as PaillierParams>::Uint>>,
hat_beta: SecretBox<Signed<<P::Paillier as PaillierParams>::Uint>>,
r: Randomizer<P::Paillier>,
s: Randomizer<P::Paillier>,
hat_r: Randomizer<P::Paillier>,
hat_s: Randomizer<P::Paillier>,
cap_d: CiphertextMod<P::Paillier>,
cap_f: CiphertextMod<P::Paillier>,
hat_cap_d: CiphertextMod<P::Paillier>,
Expand Down Expand Up @@ -344,25 +344,38 @@
let aux = (&self.context.ssid_hash, &self.my_id());

let cap_gamma = self.context.gamma.mul_by_generator();
let pk = &self.context.aux_info.secret_aux.paillier_sk.public_key();
let pk = self.context.aux_info.secret_aux.paillier_sk.public_key();

let target_pk = &self.context.aux_info.public_aux[destination].paillier_pk;

let beta = Signed::random_bounded_bits(rng, P::LP_BOUND);
let hat_beta = Signed::random_bounded_bits(rng, P::LP_BOUND);
let beta = SecretBox::new(Box::new(Signed::random_bounded_bits(rng, P::LP_BOUND)));
let hat_beta = SecretBox::new(Box::new(Signed::random_bounded_bits(rng, P::LP_BOUND)));
let r = RandomizerMod::random(rng, pk);
let s = RandomizerMod::random(rng, target_pk);
let hat_r = RandomizerMod::random(rng, pk);
let hat_s = RandomizerMod::random(rng, target_pk);

let cap_f = CiphertextMod::new_with_randomizer_signed(pk, &beta, &r.retrieve());
let cap_f =
CiphertextMod::new_with_randomizer_signed(pk, beta.expose_secret(), &r.retrieve());
let cap_d = &self.all_cap_k[destination] * P::signed_from_scalar(&self.context.gamma)
+ CiphertextMod::new_with_randomizer_signed(target_pk, &-beta, &s.retrieve());
+ CiphertextMod::new_with_randomizer_signed(
target_pk,
&-beta.expose_secret(),
&s.retrieve(),
);

let hat_cap_f = CiphertextMod::new_with_randomizer_signed(pk, &hat_beta, &hat_r.retrieve());
let hat_cap_f = CiphertextMod::new_with_randomizer_signed(
pk,
hat_beta.expose_secret(),
&hat_r.retrieve(),
);
let hat_cap_d = &self.all_cap_k[destination]
* P::signed_from_scalar(self.context.key_share.secret_share.expose_secret())
+ CiphertextMod::new_with_randomizer_signed(target_pk, &-hat_beta, &hat_s.retrieve());
+ CiphertextMod::new_with_randomizer_signed(
target_pk,
&-hat_beta.expose_secret(),
&hat_s.retrieve(),
);

let public_aux = &self.context.aux_info.public_aux[destination];
let rp = &public_aux.rp_params;
Expand All @@ -371,8 +384,8 @@
rng,
&P::signed_from_scalar(&self.context.gamma),
&beta,
&s,
&r,
s.clone(),
r.clone(),
target_pk,
pk,
&self.all_cap_k[destination],
Expand All @@ -387,8 +400,8 @@
rng,
&P::signed_from_scalar(self.context.key_share.secret_share.expose_secret()),
&hat_beta,
&hat_s,
&hat_r,
hat_s.clone(),
hat_r.clone(),
target_pk,
pk,
&self.all_cap_k[destination],
Expand Down Expand Up @@ -542,14 +555,17 @@
let cap_delta = cap_gamma * self.context.k;

let alpha_sum: Signed<_> = payloads.values().map(|p| p.alpha).sum();
let beta_sum: Signed<_> = artifacts.values().map(|p| p.beta).sum();
let beta_sum: Signed<_> = artifacts.values().map(|p| p.beta.expose_secret()).sum();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder how far should we go to protect the secrets? In this sum, for example, the safest way to do it is to actually write out an explicit loop mutating the sum inside a SecretBox.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I have the same concern and a poor intuition for what "good enough" means here.

By explicit loop, do you mean something like this?

       let beta_sum =
            artifacts
                .values()
                .fold(SecretBox::new(Box::new(Signed::default())), |mut sum, p| {
                    *sum.expose_secret_mut() = sum.expose_secret().add(p.beta.expose_secret());
                    sum
                });

In this case here I'm not so sure it's worth it. One line below we'd expose_secret again to add beta_sum to delta. But perhaps delta is a secret too? 😱

let delta = P::signed_from_scalar(&self.context.gamma)
* P::signed_from_scalar(&self.context.k)
+ alpha_sum
+ beta_sum;

let hat_alpha_sum: Signed<_> = payloads.values().map(|payload| payload.hat_alpha).sum();
let hat_beta_sum: Signed<_> = artifacts.values().map(|artifact| artifact.hat_beta).sum();
let hat_beta_sum: Signed<_> = artifacts
.values()
.map(|artifact| artifact.hat_beta.expose_secret())
.sum();
let chi = P::signed_from_scalar(self.context.key_share.secret_share.expose_secret())
* P::signed_from_scalar(&self.context.k)
+ hat_alpha_sum
Expand Down Expand Up @@ -770,8 +786,8 @@
rng,
&P::signed_from_scalar(&self.context.gamma),
beta,
&s.to_mod(target_pk),
&r.to_mod(pk),
s.to_mod(target_pk),
r.to_mod(pk),

Check warning on line 790 in synedrion/src/cggmp21/protocols/presigning.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/protocols/presigning.rs#L789-L790

Added lines #L789 - L790 were not covered by tests
target_pk,
pk,
&self.all_cap_k[id_j],
Expand Down
6 changes: 3 additions & 3 deletions synedrion/src/cggmp21/protocols/signing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,14 @@
let target_pk = &self.aux_info.public_aux[id_j].paillier_pk;
let rp = &self.aux_info.public_aux[id_l].rp_params;

let values = &self.inputs.presigning.values.get(id_j).unwrap();
let values = self.inputs.presigning.values.get(id_j).unwrap();

Check warning on line 185 in synedrion/src/cggmp21/protocols/signing.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/protocols/signing.rs#L185

Added line #L185 was not covered by tests

let p_aff_g = AffGProof::<P>::new(
rng,
&P::signed_from_scalar(self.inputs.key_share.secret_share.expose_secret()),
&values.hat_beta,
&values.hat_s.to_mod(target_pk),
&values.hat_r.to_mod(pk),
values.hat_s.to_mod(target_pk),
values.hat_r.to_mod(pk),

Check warning on line 192 in synedrion/src/cggmp21/protocols/signing.rs

View check run for this annotation

Codecov / codecov/patch

synedrion/src/cggmp21/protocols/signing.rs#L191-L192

Added lines #L191 - L192 were not covered by tests
target_pk,
pk,
&values.cap_k,
Expand Down
41 changes: 24 additions & 17 deletions synedrion/src/cggmp21/sigma/aff_g.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Paillier Affine Operation with Group Commitment in Range ($\Pi^{aff-g}$, Section 6.2, Fig. 15)

use rand_core::CryptoRngCore;
use secrecy::{ExposeSecret, SecretBox};
use serde::{Deserialize, Serialize};

use super::super::SchemeParams;
Expand Down Expand Up @@ -59,9 +60,9 @@ impl<P: SchemeParams> AffGProof<P> {
pub fn new(
rng: &mut impl CryptoRngCore,
x: &Signed<<P::Paillier as PaillierParams>::Uint>,
y: &Signed<<P::Paillier as PaillierParams>::Uint>,
rho: &RandomizerMod<P::Paillier>,
rho_y: &RandomizerMod<P::Paillier>,
y: &SecretBox<Signed<<P::Paillier as PaillierParams>::Uint>>,
rho: RandomizerMod<P::Paillier>,
rho_y: RandomizerMod<P::Paillier>,
pk0: &PublicKeyPaillierPrecomputed<P::Paillier>,
pk1: &PublicKeyPaillierPrecomputed<P::Paillier>,
cap_c: &CiphertextMod<P::Paillier>,
Expand All @@ -72,7 +73,7 @@ impl<P: SchemeParams> AffGProof<P> {
aux: &impl Hashable,
) -> Self {
x.assert_bound(P::L_BOUND);
y.assert_bound(P::LP_BOUND);
y.expose_secret().assert_bound(P::LP_BOUND);
assert!(cap_c.public_key() == pk0);
assert!(cap_d.public_key() == pk0);
assert!(cap_y.public_key() == pk1);
Expand All @@ -96,14 +97,14 @@ impl<P: SchemeParams> AffGProof<P> {
let cap_b_x = P::scalar_from_signed(&alpha).mul_by_generator();
let cap_b_y =
CiphertextMod::new_with_randomizer_signed(pk1, &beta, &r_y_mod.retrieve()).retrieve();
let cap_e = setup.commit(&alpha, &gamma).retrieve();
let cap_s = setup.commit(x, &m).retrieve();
let cap_f = setup.commit(&beta, &delta).retrieve();
let cap_e = setup.commit(&alpha.into(), &gamma).retrieve();
let cap_s = setup.commit(&x.into(), &m).retrieve();
let cap_f = setup.commit(&beta.into(), &delta).retrieve();

// NOTE: deviation from the paper to support a different $D$
// (see the comment in `AffGProof`)
// Original: $s^y$. Modified: $s^{-y}$
let cap_t = setup.commit(&-y, &mu).retrieve();
let cap_t = setup.commit(&(-y.expose_secret()).into(), &mu).retrieve();

let mut reader = XofHasher::new_with_dst(HASH_TAG)
// commitments
Expand Down Expand Up @@ -135,7 +136,7 @@ impl<P: SchemeParams> AffGProof<P> {
// (see the comment in `AffGProof`)
// Original: $z_2 = \beta + e y$
// Modified: $z_2 = \beta - e y$
let z2 = beta + e * (-y);
let z2 = beta + e * (-y.expose_secret());

let z3 = gamma + e_wide * m;
let z4 = delta + e_wide * mu;
Expand Down Expand Up @@ -249,14 +250,16 @@ impl<P: SchemeParams> AffGProof<P> {
// s^{z_1} t^{z_3} = E S^e \mod \hat{N}
let cap_e_mod = self.cap_e.to_mod(aux_pk);
let cap_s_mod = self.cap_s.to_mod(aux_pk);
if setup.commit(&self.z1, &self.z3) != &cap_e_mod * &cap_s_mod.pow_signed_vartime(&e) {
if setup.commit(&self.z1.into(), &self.z3) != &cap_e_mod * &cap_s_mod.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_mod(aux_pk);
let cap_t_mod = self.cap_t.to_mod(aux_pk);
if setup.commit(&self.z2, &self.z4) != &cap_f_mod * &cap_t_mod.pow_signed_vartime(&e) {
if setup.commit(&self.z2.into(), &self.z4) != &cap_f_mod * &cap_t_mod.pow_signed_vartime(&e)
{
return false;
}

Expand All @@ -267,6 +270,7 @@ impl<P: SchemeParams> AffGProof<P> {
#[cfg(test)]
mod tests {
use rand_core::OsRng;
use secrecy::{ExposeSecret, SecretBox};

use super::AffGProof;
use crate::cggmp21::{SchemeParams, TestParams};
Expand All @@ -290,21 +294,24 @@ mod tests {
let aux: &[u8] = b"abcde";

let x = Signed::random_bounded_bits(&mut OsRng, Params::L_BOUND);
let y = Signed::random_bounded_bits(&mut OsRng, Params::LP_BOUND);
let y = SecretBox::new(Box::new(Signed::random_bounded_bits(
&mut OsRng,
Params::LP_BOUND,
)));

let rho = RandomizerMod::random(&mut OsRng, pk0);
let rho_y = RandomizerMod::random(&mut OsRng, pk1);
let secret = Signed::random(&mut OsRng);
let cap_c = CiphertextMod::new_signed(&mut OsRng, pk0, &secret);

let cap_d =
&cap_c * x + CiphertextMod::new_with_randomizer_signed(pk0, &-y, &rho.retrieve());
let cap_y = CiphertextMod::new_with_randomizer_signed(pk1, &y, &rho_y.retrieve());
let cap_d = &cap_c * x
+ CiphertextMod::new_with_randomizer_signed(pk0, &-y.expose_secret(), &rho.retrieve());
let cap_y =
CiphertextMod::new_with_randomizer_signed(pk1, y.expose_secret(), &rho_y.retrieve());
let cap_x = Params::scalar_from_signed(&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, &setup,
&aux,
&mut OsRng, &x, &y, rho, rho_y, pk0, pk1, &cap_c, &cap_d, &cap_y, &cap_x, &setup, &aux,
);
assert!(proof.verify(pk0, pk1, &cap_c, &cap_d, &cap_y, &cap_x, &setup, &aux));
}
Expand Down
8 changes: 5 additions & 3 deletions synedrion/src/cggmp21/sigma/dec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ impl<P: SchemeParams> DecProof<P> {
let nu = Signed::random_bounded_bits_scaled(rng, P::L_BOUND + P::EPS_BOUND, hat_cap_n);
let r = RandomizerMod::random(rng, pk0);

let cap_s = setup.commit(y, &mu).retrieve();
let cap_t = setup.commit(&alpha, &nu).retrieve();
let cap_s = setup.commit(&y.into(), &mu).retrieve();
let cap_t = setup.commit(&alpha.into(), &nu).retrieve();
let cap_a =
CiphertextMod::new_with_randomizer_signed(pk0, &alpha, &r.retrieve()).retrieve();
let gamma = P::scalar_from_signed(&alpha);
Expand Down Expand Up @@ -150,7 +150,9 @@ impl<P: SchemeParams> DecProof<P> {
// s^{z_1} t^{z_2} == T S^e
let cap_s_mod = self.cap_s.to_mod(setup.public_key());
let cap_t_mod = self.cap_t.to_mod(setup.public_key());
if setup.commit_wide(&self.z1, &self.z2) != &cap_t_mod * &cap_s_mod.pow_signed_vartime(&e) {
if setup.commit_wide(&self.z1.into(), &self.z2)
!= &cap_t_mod * &cap_s_mod.pow_signed_vartime(&e)
{
return false;
}

Expand Down
7 changes: 4 additions & 3 deletions synedrion/src/cggmp21/sigma/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ impl<P: SchemeParams> EncProof<P> {
let r = RandomizerMod::random(rng, pk0);
let gamma = Signed::random_bounded_bits_scaled(rng, P::L_BOUND + P::EPS_BOUND, hat_cap_n);

let cap_s = setup.commit(k, &mu).retrieve();
let cap_s = setup.commit(&k.into(), &mu).retrieve();
let cap_a =
CiphertextMod::new_with_randomizer_signed(pk0, &alpha, &r.retrieve()).retrieve();
let cap_c = setup.commit(&alpha, &gamma).retrieve();
let cap_c = setup.commit(&alpha.into(), &gamma).retrieve();

let mut reader = XofHasher::new_with_dst(HASH_TAG)
// commitments
Expand Down Expand Up @@ -135,7 +135,8 @@ impl<P: SchemeParams> EncProof<P> {
// s^{z_1} t^{z_3} == C S^e \mod \hat{N}
let cap_c_mod = self.cap_c.to_mod(setup.public_key());
let cap_s_mod = self.cap_s.to_mod(setup.public_key());
if setup.commit(&self.z1, &self.z3) != &cap_c_mod * &cap_s_mod.pow_signed_vartime(&e) {
if setup.commit(&self.z1.into(), &self.z3) != &cap_c_mod * &cap_s_mod.pow_signed_vartime(&e)
{
return false;
}

Expand Down
Loading
Loading