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

all: make DKG SecretPackages serializable #833

Merged
merged 1 commit into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
127 changes: 108 additions & 19 deletions frost-core/src/keys/dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub mod round1 {

use super::*;

use crate::serialization::SerializableScalar;
#[cfg(feature = "serialization")]
use crate::serialization::{Deserialize, Serialize};

Expand Down Expand Up @@ -117,13 +118,16 @@ pub mod round1 {
///
/// This package MUST NOT be sent to other participants!
#[derive(Clone, PartialEq, Eq, Getters)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))]
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
pub struct SecretPackage<C: Ciphersuite> {
/// The identifier of the participant holding the secret.
pub(crate) identifier: Identifier<C>,
/// Coefficients of the temporary secret polynomial for the participant.
/// These are (a_{i0}, ..., a_{i(t−1)})) which define the polynomial f_i(x)
#[getter(skip)]
pub(crate) coefficients: Vec<Scalar<C>>,
pub(crate) coefficients: Vec<SerializableScalar<C>>,
/// The public commitment for the participant (C_i)
pub(crate) commitment: VerifiableSecretSharingCommitment<C>,
/// The minimum number of signers.
Expand All @@ -136,10 +140,45 @@ pub mod round1 {
where
C: Ciphersuite,
{
/// Create a new Secret Package. This should be called only if
/// custom serialization is required; run the DKG to create
/// a valid SecretPackage.
pub fn new(
identifier: Identifier<C>,
coefficients: Vec<Scalar<C>>,
commitment: VerifiableSecretSharingCommitment<C>,
min_signers: u16,
max_signers: u16,
) -> Self {
Self {
identifier,
coefficients: coefficients.into_iter().map(SerializableScalar).collect(),
commitment,
min_signers,
max_signers,
}
}

/// Returns the secret coefficients.
#[cfg(feature = "internals")]
pub fn coefficients(&self) -> &[Scalar<C>] {
&self.coefficients
pub fn coefficients(&self) -> Vec<Scalar<C>> {
self.coefficients.iter().map(|s| s.0).collect()
}
}

#[cfg(feature = "serialization")]
impl<C> SecretPackage<C>
where
C: Ciphersuite,
{
/// Serialize the struct into a Vec.
pub fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
Serialize::serialize(&self)
}

/// Deserialize the struct from a slice of bytes.
pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
Deserialize::deserialize(bytes)
}
}

Expand All @@ -164,7 +203,7 @@ pub mod round1 {
{
fn zeroize(&mut self) {
for c in self.coefficients.iter_mut() {
*c = <<C::Group as Group>::Field>::zero();
*c = SerializableScalar(<<C::Group as Group>::Field>::zero());
}
}
}
Expand All @@ -178,6 +217,8 @@ pub mod round2 {
#[cfg(feature = "serialization")]
use alloc::vec::Vec;

use crate::serialization::SerializableScalar;

use super::*;

/// A package that must be sent by each participant to some other participants
Expand Down Expand Up @@ -235,19 +276,67 @@ pub mod round2 {
///
/// This package MUST NOT be sent to other participants!
#[derive(Clone, PartialEq, Eq, Getters)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))]
#[cfg_attr(feature = "serde", serde(deny_unknown_fields))]
pub struct SecretPackage<C: Ciphersuite> {
/// The identifier of the participant holding the secret.
pub(crate) identifier: Identifier<C>,
/// The public commitment from the participant (C_i)
pub(crate) commitment: VerifiableSecretSharingCommitment<C>,
/// The participant's own secret share (f_i(i)).
pub(crate) secret_share: Scalar<C>,
#[getter(skip)]
pub(crate) secret_share: SerializableScalar<C>,
/// The minimum number of signers.
pub(crate) min_signers: u16,
/// The total number of signers.
pub(crate) max_signers: u16,
}

impl<C> SecretPackage<C>
where
C: Ciphersuite,
{
/// Create a new SecretPackage. Use this only if custom serialization is
/// required; run the DKG to create a valid SecretPackage.
pub fn new(
identifier: Identifier<C>,
commitment: VerifiableSecretSharingCommitment<C>,
secret_share: Scalar<C>,
min_signers: u16,
max_signers: u16,
) -> Self {
Self {
identifier,
commitment,
secret_share: SerializableScalar(secret_share),
min_signers,
max_signers,
}
}

/// Return the SecretShare.
pub fn secret_share(&self) -> Scalar<C> {
self.secret_share.0
}
}

#[cfg(feature = "serialization")]
impl<C> SecretPackage<C>
where
C: Ciphersuite,
{
/// Serialize the struct into a Vec.
pub fn serialize(&self) -> Result<Vec<u8>, Error<C>> {
Serialize::serialize(&self)
}

/// Deserialize the struct from a slice of bytes.
pub fn deserialize(bytes: &[u8]) -> Result<Self, Error<C>> {
Deserialize::deserialize(bytes)
}
}

impl<C> core::fmt::Debug for SecretPackage<C>
where
C: Ciphersuite,
Expand All @@ -268,7 +357,7 @@ pub mod round2 {
C: Ciphersuite,
{
fn zeroize(&mut self) {
self.secret_share = <<C::Group as Group>::Field>::zero();
self.secret_share = SerializableScalar(<<C::Group as Group>::Field>::zero());
}
}
}
Expand Down Expand Up @@ -304,13 +393,13 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
let proof_of_knowledge =
compute_proof_of_knowledge(identifier, &coefficients, &commitment, &mut rng)?;

let secret_package = round1::SecretPackage {
let secret_package = round1::SecretPackage::new(
identifier,
coefficients,
commitment: commitment.clone(),
commitment.clone(),
min_signers,
max_signers,
};
);
let package = round1::Package {
header: Header::default(),
commitment,
Expand Down Expand Up @@ -439,7 +528,7 @@ pub fn part2<C: Ciphersuite>(
// > Each P_i securely sends to each other participant P_ℓ a secret share (ℓ, f_i(ℓ)),
// > deleting f_i and each share afterward except for (i, f_i(i)),
// > which they keep for themselves.
let signing_share = SigningShare::from_coefficients(&secret_package.coefficients, ell);
let signing_share = SigningShare::from_coefficients(&secret_package.coefficients(), ell);

round2_packages.insert(
ell,
Expand All @@ -449,15 +538,15 @@ pub fn part2<C: Ciphersuite>(
},
);
}
let fii = evaluate_polynomial(secret_package.identifier, &secret_package.coefficients);
let fii = evaluate_polynomial(secret_package.identifier, &secret_package.coefficients());
Ok((
round2::SecretPackage {
identifier: secret_package.identifier,
commitment: secret_package.commitment,
secret_share: fii,
min_signers: secret_package.min_signers,
max_signers: secret_package.max_signers,
},
round2::SecretPackage::new(
secret_package.identifier,
secret_package.commitment,
fii,
secret_package.min_signers,
secret_package.max_signers,
),
round2_packages,
))
}
Expand Down Expand Up @@ -542,7 +631,7 @@ pub fn part3<C: Ciphersuite>(
signing_share = signing_share + f_ell_i.to_scalar();
}

signing_share = signing_share + round2_secret_package.secret_share;
signing_share = signing_share + round2_secret_package.secret_share();
let signing_share = SigningShare::new(signing_share);

// Round 2, Step 4
Expand Down
28 changes: 14 additions & 14 deletions frost-core/src/keys/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,13 @@ pub fn refresh_dkg_part_1<C: Ciphersuite, R: RngCore + CryptoRng>(
let proof_of_knowledge =
compute_proof_of_knowledge(identifier, &coefficients, &commitment, &mut rng)?;

let secret_package = round1::SecretPackage {
let secret_package = round1::SecretPackage::new(
identifier,
coefficients: coefficients.clone(),
commitment: commitment.clone(),
coefficients.clone(),
commitment.clone(),
min_signers,
max_signers,
};
);
let package = round1::Package {
header: Header::default(),
commitment,
Expand Down Expand Up @@ -217,7 +217,7 @@ pub fn refresh_dkg_part2<C: Ciphersuite>(
// > Each P_i securely sends to each other participant P_ℓ a secret share (ℓ, f_i(ℓ)),
// > deleting f_i and each share afterward except for (i, f_i(i)),
// > which they keep for themselves.
let signing_share = SigningShare::from_coefficients(&secret_package.coefficients, ell);
let signing_share = SigningShare::from_coefficients(&secret_package.coefficients(), ell);

round2_packages.insert(
ell,
Expand All @@ -227,16 +227,16 @@ pub fn refresh_dkg_part2<C: Ciphersuite>(
},
);
}
let fii = evaluate_polynomial(secret_package.identifier, &secret_package.coefficients);
let fii = evaluate_polynomial(secret_package.identifier, &secret_package.coefficients());

Ok((
round2::SecretPackage {
identifier: secret_package.identifier,
commitment: secret_package.commitment,
secret_share: fii,
min_signers: secret_package.min_signers,
max_signers: secret_package.max_signers,
},
round2::SecretPackage::new(
secret_package.identifier,
secret_package.commitment,
fii,
secret_package.min_signers,
secret_package.max_signers,
),
round2_packages,
))
}
Expand Down Expand Up @@ -323,7 +323,7 @@ pub fn refresh_dkg_shares<C: Ciphersuite>(
signing_share = signing_share + f_ell_i.to_scalar();
}

signing_share = signing_share + round2_secret_package.secret_share;
signing_share = signing_share + round2_secret_package.secret_share();

// Build new signing share
let old_signing_share = old_key_package.signing_share.to_scalar();
Expand Down
8 changes: 4 additions & 4 deletions frost-core/src/tests/vectors_dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,13 @@ pub fn check_dkg_keygen<C: Ciphersuite>(json_vectors: &Value) {
)
.unwrap();

let round1_secret_package = SecretPackage {
identifier: participant_id,
let round1_secret_package = SecretPackage::new(
participant_id,
coefficients,
commitment: commitment.clone(),
commitment.clone(),
min_signers,
max_signers,
};
);

let (round2_secret_package, _round2_packages_1) =
part2(round1_secret_package, &round1_packages).unwrap();
Expand Down
39 changes: 39 additions & 0 deletions frost-ed25519/tests/helpers/samples.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@ pub fn public_key_package() -> PublicKeyPackage {
PublicKeyPackage::new(verifying_shares, verifying_key)
}

/// Generate a sample round1::SecretPackage.
pub fn round1_secret_package() -> round1::SecretPackage {
let identifier = 42u16.try_into().unwrap();
let coefficients = vec![scalar1(), scalar1()];
let min_signers = 2;
let max_signers = 3;

let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()).unwrap();
let commitment =
VerifiableSecretSharingCommitment::deserialize(vec![serialized_element]).unwrap();

round1::SecretPackage::new(
identifier,
coefficients,
commitment,
min_signers,
max_signers,
)
}

/// Generate a sample round1::Package.
pub fn round1_package() -> round1::Package {
let serialized_signature = Signature::new(element1(), scalar1()).serialize().unwrap();
Expand All @@ -119,6 +139,25 @@ pub fn round1_package() -> round1::Package {
round1::Package::new(vss_commitment, signature)
}

/// Generate a sample round1::SecretPackage.
pub fn round2_secret_package() -> round2::SecretPackage {
let identifier = 42u16.try_into().unwrap();
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()).unwrap();
let commitment =
VerifiableSecretSharingCommitment::deserialize(vec![serialized_element]).unwrap();
let secret_share = scalar1();
let min_signers = 2;
let max_signers = 3;

round2::SecretPackage::new(
identifier,
commitment,
secret_share,
min_signers,
max_signers,
)
}

/// Generate a sample round2::Package.
pub fn round2_package() -> round2::Package {
let serialized_scalar = <<C as Ciphersuite>::Group as Group>::Field::serialize(&scalar1());
Expand Down
Loading
Loading