use max_signers and min_signers instead of num_signers and threshold to better follow spec (#157)

This commit is contained in:
Conrado Gouvea 2022-10-27 01:35:16 -03:00 committed by GitHub
parent 68ee645652
commit 201d6adc4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 68 additions and 62 deletions

View File

@ -306,8 +306,8 @@ where
///
/// [`trusted_dealer_keygen`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#appendix-C
pub fn keygen_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
num_signers: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
mut rng: R,
) -> Result<(Vec<SecretShare<C>>, PublicKeyPackage<C>), &'static str> {
let mut bytes = [0; 64];
@ -316,11 +316,11 @@ pub fn keygen_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
let secret = SharedSecret::random(&mut rng);
let group_public = VerifyingKey::from(&secret);
let coefficients = generate_coefficients::<C, R>(threshold as usize - 1, &mut rng);
let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, &mut rng);
let secret_shares = generate_secret_shares(&secret, num_signers, threshold, coefficients)?;
let secret_shares = generate_secret_shares(&secret, max_signers, min_signers, coefficients)?;
let mut signer_pubkeys: HashMap<Identifier<C>, VerifyingShare<C>> =
HashMap::with_capacity(num_signers as usize);
HashMap::with_capacity(max_signers as usize);
for secret_share in &secret_shares {
let signer_public = secret_share.value.into();
@ -463,27 +463,27 @@ pub struct PublicKeyPackage<C: Ciphersuite> {
/// given secret, which is the first element) and a [`VerifiableSecretSharingCommitment`]
/// which contains commitments to those coefficients.
///
/// Returns an error if the parameters (num_signers, threshold) are inconsistent.
/// Returns an error if the parameters (max_signers, min_signers) are inconsistent.
pub(crate) fn generate_secret_polynomial<C: Ciphersuite>(
secret: &SharedSecret<C>,
num_signers: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
mut coefficients: Vec<Scalar<C>>,
) -> Result<(Vec<Scalar<C>>, VerifiableSecretSharingCommitment<C>), &'static str> {
if threshold < 2 {
return Err("Threshold cannot be less than 2");
if min_signers < 2 {
return Err("min_signers cannot be less than 2");
}
if num_signers < 2 {
if max_signers < 2 {
return Err("Number of signers cannot be less than the minimum threshold 2");
}
if threshold > num_signers {
return Err("Threshold cannot exceed num_signers");
if min_signers > max_signers {
return Err("min_signers cannot exceed max_signers");
}
if coefficients.len() != threshold as usize - 1 {
return Err("Must pass threshold-1 coefficients");
if coefficients.len() != min_signers as usize - 1 {
return Err("Must pass min_signers-1 coefficients");
}
// Prepend the secret, which is the 0th coefficient
@ -521,16 +521,16 @@ pub(crate) fn generate_secret_polynomial<C: Ciphersuite>(
/// [`secret_share_shard`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-11.html#appendix-C.1
pub(crate) fn generate_secret_shares<C: Ciphersuite>(
secret: &SharedSecret<C>,
numshares: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
coefficients: Vec<Scalar<C>>,
) -> Result<Vec<SecretShare<C>>, &'static str> {
let mut secret_shares: Vec<SecretShare<C>> = Vec::with_capacity(numshares as usize);
let mut secret_shares: Vec<SecretShare<C>> = Vec::with_capacity(max_signers as usize);
let (coefficients, commitment) =
generate_secret_polynomial(secret, numshares, threshold, coefficients)?;
generate_secret_polynomial(secret, max_signers, min_signers, coefficients)?;
for id in (1..=numshares as u16).map_while(|i| Identifier::<C>::try_from(i).ok()) {
for id in (1..=max_signers as u16).map_while(|i| Identifier::<C>::try_from(i).ok()) {
let value = evaluate_polynomial(id, &coefficients)?;
secret_shares.push(SecretShare {

View File

@ -43,7 +43,7 @@ pub struct Round1SecretPackage<C: Ciphersuite> {
/// The public commitment for the participant (C_i)
pub commitment: VerifiableSecretSharingCommitment<C>,
/// The total number of signers.
pub num_signers: u16,
pub max_signers: u16,
}
/// A package that must be sent by each participant to some other participants
@ -77,7 +77,7 @@ pub struct Round2SecretPackage<C: Ciphersuite> {
/// The participant's own secret share (f_i(i)).
pub secret_share: Scalar<C>,
/// The total number of signers.
pub num_signers: u16,
pub max_signers: u16,
}
/// Performs the first part of the distributed key generation protocol
@ -88,8 +88,8 @@ pub struct Round2SecretPackage<C: Ciphersuite> {
/// must be sent to other participants.
pub fn keygen_part1<C: Ciphersuite, R: RngCore + CryptoRng>(
identifier: Identifier<C>,
num_signers: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
mut rng: R,
) -> Result<(Round1SecretPackage<C>, Round1Package<C>), &'static str> {
let secret: SharedSecret<C> = SharedSecret::random(&mut rng);
@ -102,9 +102,9 @@ pub fn keygen_part1<C: Ciphersuite, R: RngCore + CryptoRng>(
//
// > Every participant P_i computes a public commitment
// > C⃗_i = 〈φ_{i0}, ..., φ_{i(t1)}〉, where φ_{ij} = g^{a_{ij}}, 0 ≤ j ≤ t 1
let coefficients = generate_coefficients::<C, R>(threshold as usize - 1, &mut rng);
let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, &mut rng);
let (coefficients, commitment) =
generate_secret_polynomial(&secret, num_signers, threshold, coefficients)?;
generate_secret_polynomial(&secret, max_signers, min_signers, coefficients)?;
// Round 1, Step 2
//
@ -123,7 +123,7 @@ pub fn keygen_part1<C: Ciphersuite, R: RngCore + CryptoRng>(
identifier,
coefficients,
commitment: commitment.clone(),
num_signers,
max_signers,
};
let package = Round1Package {
sender_identifier: identifier,
@ -163,7 +163,7 @@ pub fn keygen_part2<C: Ciphersuite>(
secret_package: Round1SecretPackage<C>,
round1_packages: &[Round1Package<C>],
) -> Result<(Round2SecretPackage<C>, Vec<Round2Package<C>>), &'static str> {
if round1_packages.len() != (secret_package.num_signers - 1) as usize {
if round1_packages.len() != (secret_package.max_signers - 1) as usize {
return Err("incorrect number of packages");
}
@ -205,7 +205,7 @@ pub fn keygen_part2<C: Ciphersuite>(
identifier: secret_package.identifier,
commitment: secret_package.commitment,
secret_share: fii,
num_signers: secret_package.num_signers,
max_signers: secret_package.max_signers,
},
round2_packages,
))
@ -268,7 +268,7 @@ pub fn keygen_part3<C: Ciphersuite>(
round1_packages: &[Round1Package<C>],
round2_packages: &[Round2Package<C>],
) -> Result<(KeyPackage<C>, PublicKeyPackage<C>), &'static str> {
if round1_packages.len() != (round2_secret_package.num_signers - 1) as usize {
if round1_packages.len() != (round2_secret_package.max_signers - 1) as usize {
return Err("incorrect number of packages");
}
if round1_packages.len() != round2_packages.len() {

View File

@ -14,13 +14,15 @@ pub mod vectors;
pub fn check_share_generation<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
let secret = frost::keys::SharedSecret::<C>::random(&mut rng);
let numshares = 5;
let threshold = 3;
let max_signers = 5;
let min_signers = 3;
let coefficients = frost::keys::generate_coefficients::<C, _>(threshold as usize - 1, &mut rng);
let coefficients =
frost::keys::generate_coefficients::<C, _>(min_signers as usize - 1, &mut rng);
let secret_shares =
frost::keys::generate_secret_shares(&secret, numshares, threshold, coefficients).unwrap();
frost::keys::generate_secret_shares(&secret, max_signers, min_signers, coefficients)
.unwrap();
for secret_share in secret_shares.iter() {
assert!(secret_share.verify().is_ok());
@ -38,10 +40,10 @@ pub fn check_sign_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R
// Key generation
////////////////////////////////////////////////////////////////////////////
let numsigners = 5;
let threshold = 3;
let max_signers = 5;
let min_signers = 3;
let (shares, pubkeys) =
frost::keys::keygen_with_dealer(numsigners, threshold, &mut rng).unwrap();
frost::keys::keygen_with_dealer(max_signers, min_signers, &mut rng).unwrap();
// Verifies the secret shares from the dealer
let key_packages: HashMap<frost::Identifier<C>, frost::keys::KeyPackage<C>> = shares
@ -54,11 +56,11 @@ pub fn check_sign_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R
})
.collect();
check_sign(threshold, key_packages, rng, pubkeys);
check_sign(min_signers, key_packages, rng, pubkeys);
}
fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
threshold: u16,
min_signers: u16,
key_packages: HashMap<frost::Identifier<C>, frost::keys::KeyPackage<C>>,
mut rng: R,
pubkeys: frost::keys::PublicKeyPackage<C>,
@ -71,10 +73,10 @@ fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
// Round 1: generating nonces and signing commitments for each participant
////////////////////////////////////////////////////////////////////////////
for participant_index in 1..(threshold as u16 + 1) {
for participant_index in 1..(min_signers as u16 + 1) {
let participant_identifier = participant_index.try_into().expect("should be nonzero");
// Generate one (1) nonce and one SigningCommitments instance for each
// participant, up to _threshold_.
// participant, up to _min_signers_.
let (nonce, commitment) = frost::round1::commit(
participant_identifier,
key_packages
@ -150,8 +152,8 @@ where
// Key generation, Round 1
////////////////////////////////////////////////////////////////////////////
let numsigners = 5;
let threshold = 3;
let max_signers = 5;
let min_signers = 3;
// Keep track of each participant's round 1 secret package.
// In practice each participant will keep its copy; no one
@ -171,11 +173,15 @@ where
// For each participant, perform the first part of the DKG protocol.
// In practice, each participant will perform this on their own environments.
for participant_index in 1..=numsigners {
for participant_index in 1..=max_signers {
let participant_identifier = participant_index.try_into().expect("should be nonzero");
let (secret_package, round1_package) =
frost::keys::dkg::keygen_part1(participant_identifier, numsigners, threshold, &mut rng)
.unwrap();
let (secret_package, round1_package) = frost::keys::dkg::keygen_part1(
participant_identifier,
max_signers,
min_signers,
&mut rng,
)
.unwrap();
// Store the participant's secret package for later use.
// In practice each participant will store it in their own environment.
@ -184,7 +190,7 @@ where
// Send the round 1 package to all other participants. In this
// test this is simulated using a HashMap; in practice this will be
// sent through some communication channel.
for receiver_participant_index in 1..=numsigners {
for receiver_participant_index in 1..=max_signers {
if receiver_participant_index == participant_index {
continue;
}
@ -214,7 +220,7 @@ where
// For each participant, perform the second part of the DKG protocol.
// In practice, each participant will perform this on their own environments.
for participant_index in 1..=numsigners {
for participant_index in 1..=max_signers {
let participant_identifier = participant_index.try_into().expect("should be nonzero");
let (round2_secret_package, round2_packages) = frost::keys::dkg::keygen_part2(
round1_secret_packages
@ -268,7 +274,7 @@ where
// For each participant, perform the third part of the DKG protocol.
// In practice, each participant will perform this on their own environments.
for participant_index in 1..=numsigners {
for participant_index in 1..=max_signers {
let participant_identifier = participant_index.try_into().expect("should be nonzero");
let (key_package, others_verifying_keys) = frost::keys::dkg::keygen_part3(
&round2_secret_packages[&participant_identifier],
@ -287,7 +293,7 @@ where
}
// Test if the set of verifying keys is correct for all participants.
for participant_index in 1..=numsigners {
for participant_index in 1..=max_signers {
let participant_identifier = participant_index.try_into().expect("should be nonzero");
let public_key_package = others_verifying_keys_by_participant
.get(&participant_identifier)
@ -309,5 +315,5 @@ where
};
// Proceed with the signing test.
check_sign(threshold, key_packages, rng, pubkeys);
check_sign(min_signers, key_packages, rng, pubkeys);
}

View File

@ -206,12 +206,12 @@ pub fn check_sign_with_test_vectors<C: Ciphersuite>(json_vectors: &Value) {
// Key generation
////////////////////////////////////////////////////////////////////////////
let numshares = key_packages.len();
let threshold = share_polynomial_coefficients.len() + 1;
let max_signers = key_packages.len();
let min_signers = share_polynomial_coefficients.len() + 1;
let secret_shares = generate_secret_shares(
&secret_key,
numshares as u16,
threshold as u16,
max_signers as u16,
min_signers as u16,
share_polynomial_coefficients,
)
.unwrap();

View File

@ -250,11 +250,11 @@ pub mod keys {
/// Allows all participants' keys to be generated using a central, trusted
/// dealer.
pub fn keygen_with_dealer<RNG: RngCore + CryptoRng>(
num_signers: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
mut rng: RNG,
) -> Result<(Vec<SecretShare>, PublicKeyPackage), &'static str> {
frost::keys::keygen_with_dealer(num_signers, threshold, &mut rng)
frost::keys::keygen_with_dealer(max_signers, min_signers, &mut rng)
}
/// Secret and public key material generated by a dealer performing

View File

@ -228,11 +228,11 @@ pub mod keys {
/// Allows all participants' keys to be generated using a central, trusted
/// dealer.
pub fn keygen_with_dealer<RNG: RngCore + CryptoRng>(
num_signers: u16,
threshold: u16,
max_signers: u16,
min_signers: u16,
mut rng: RNG,
) -> Result<(Vec<SecretShare>, PublicKeyPackage), &'static str> {
frost::keys::keygen_with_dealer(num_signers, threshold, &mut rng)
frost::keys::keygen_with_dealer(max_signers, min_signers, &mut rng)
}
/// Secret and public key material generated by a dealer performing