use max_signers and min_signers instead of num_signers and threshold to better follow spec (#157)
This commit is contained in:
parent
68ee645652
commit
201d6adc4d
|
@ -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 {
|
||||
|
|
|
@ -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(t−1)}〉, 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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue