Skip to content
Open
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
6 changes: 6 additions & 0 deletions frost-core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ Entries are listed in reverse chronological order.
* The `std` and `nightly` features were removed from all crates
* Renamed `frost_core::keys::refresh::refresh_dkg_part_1` to `refresh_dkg_part1`.
* Fixed the crate-specific versions of the `refresh` module to be non-generic.
* Removed the `min_signers` and `max_signers` arguments from
`frost_core::keys::refresh::compute_refreshing_shares()`. The former is now
read from the `pub_key_package`; if you pass a pre-3.0.0 generate package,
you will need to fills its `min_signers` field with the original threshold
before calling the function (recreate it with `PublicKeyPackage::new()`).
The latter was simply redundant.

### Additional changes

Expand Down
47 changes: 23 additions & 24 deletions frost-core/src/keys/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,38 +42,37 @@ use super::{dkg::round1::Package, KeyPackage, SecretShare, VerifiableSecretShari

/// Compute refreshing shares for the Trusted Dealer refresh procedure.
///
/// - `pub_key_package`: the current public key package.
/// - `max_signers`: the number of participants that are refreshing their
/// shares. It can be smaller than the original value, but still equal to or
/// greater than `min_signers`.
/// - `min_signers`: the threshold needed to sign. It must be equal to the
/// original value for the group (i.e. the refresh process can't reduce
/// the threshold).
/// - `pub_key_package`: the current public key package. Note: if a pre-3.0.0
/// generate package is used, you will need to manually set the `min_signers`
/// field with the theshold that was used in the original share generation.
/// (You can't change the threshold when refreshing shares.)
/// - `identifiers`: The identifiers of all participants that want to refresh
/// their shares. Must be the same length as `max_signers`.
/// their shares. Must be a subset of the identifiers in `pub_key_package`. If
/// not all identifiers are passed, the refresh procedure will effectively
/// remove the missing participants. The length must be equal to or greater
/// than the threshold of the group.
///
/// It returns a vectors of [`SecretShare`] that must be sent to the participants
/// in the same order as `identifiers`, and the refreshed [`PublicKeyPackage`].
/// It returns a vectors of [`SecretShare`] that must be sent to the
/// participants in the same order as `identifiers`, and the refreshed
/// [`PublicKeyPackage`].
pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
pub_key_package: PublicKeyPackage<C>,
max_signers: u16,
min_signers: u16,
identifiers: &[Identifier<C>],
rng: &mut R,
) -> Result<(Vec<SecretShare<C>>, PublicKeyPackage<C>), Error<C>> {
// Validate min_signers. It's OK if the min_signers is missing, because
// we validate it again in `refresh_share()`.
if let Some(package_min_signers) = pub_key_package.min_signers {
if min_signers != package_min_signers {
return Err(Error::InvalidMinSigners);
}
}
let min_signers = pub_key_package
.min_signers
.ok_or(Error::InvalidMinSigners)?;

let signers = identifiers.len() as u16;
validate_num_of_signers(min_signers, signers)?;

// Validate inputs
if identifiers.len() != max_signers as usize {
return Err(Error::IncorrectNumberOfIdentifiers);
if identifiers
.iter()
.any(|i| !pub_key_package.verifying_shares().contains_key(i))
{
return Err(Error::UnknownIdentifier);
}
validate_num_of_signers(min_signers, max_signers)?;

// Build refreshing shares
let refreshing_key = SigningKey {
Expand All @@ -83,7 +82,7 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, rng);
let refreshing_shares = generate_secret_shares(
&refreshing_key,
max_signers,
signers,
min_signers,
coefficients,
identifiers,
Expand Down
105 changes: 7 additions & 98 deletions frost-core/src/tests/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,10 @@ pub fn check_refresh_shares_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
Identifier::try_from(5).unwrap(),
];

const NEW_MAX_SIGNERS: u16 = 4;

// Trusted Dealer generates zero keys and new public key package

let (zero_shares, new_pub_key_package) = compute_refreshing_shares(
pub_key_package,
NEW_MAX_SIGNERS,
MIN_SIGNERS,
&remaining_ids,
&mut rng,
)
.unwrap();
let (zero_shares, new_pub_key_package) =
compute_refreshing_shares(pub_key_package, &remaining_ids, &mut rng).unwrap();
// Simulate serialization / deserialization to ensure it works
let new_pub_key_package =
frost::keys::PublicKeyPackage::deserialize(&new_pub_key_package.serialize().unwrap())
Expand Down Expand Up @@ -102,21 +94,13 @@ pub fn check_refresh_shares_with_dealer_fails_with_invalid_signers<
C: Ciphersuite,
R: RngCore + CryptoRng,
>(
new_max_signers: u16,
min_signers: u16,
identifiers: &[Identifier<C>],
error: Error<C>,
mut rng: R,
) {
let (_old_shares, pub_key_package) =
generate_with_dealer::<C, R>(5, 2, frost::keys::IdentifierList::Default, &mut rng).unwrap();
let out = compute_refreshing_shares(
pub_key_package,
new_max_signers,
min_signers,
identifiers,
&mut rng,
);
let out = compute_refreshing_shares(pub_key_package, identifiers, &mut rng);

assert!(out.is_err());
assert!(out == Err(error))
Expand Down Expand Up @@ -166,18 +150,10 @@ pub fn check_refresh_shares_with_dealer_fails_with_invalid_public_key_package<
Identifier::try_from(5).unwrap(),
];

const NEW_MAX_SIGNERS: u16 = 4;

// Trusted Dealer generates zero keys and new public key package

let e = compute_refreshing_shares(
incorrect_pub_key_package,
NEW_MAX_SIGNERS,
MIN_SIGNERS,
&remaining_ids,
&mut rng,
)
.unwrap_err();
let e =
compute_refreshing_shares(incorrect_pub_key_package, &remaining_ids, &mut rng).unwrap_err();

assert_eq!(e, Error::UnknownIdentifier)
}
Expand Down Expand Up @@ -215,16 +191,8 @@ pub fn check_refresh_shares_with_dealer_serialisation<C: Ciphersuite, R: RngCore
Identifier::try_from(5).unwrap(),
];

const NEW_MAX_SIGNERS: u16 = 4;

let (zero_shares, new_pub_key_package) = compute_refreshing_shares(
pub_key_package,
NEW_MAX_SIGNERS,
MIN_SIGNERS,
&remaining_ids,
&mut rng,
)
.unwrap();
let (zero_shares, new_pub_key_package) =
compute_refreshing_shares(pub_key_package, &remaining_ids, &mut rng).unwrap();

// Trusted dealer serialises zero shares and key package

Expand Down Expand Up @@ -254,65 +222,6 @@ pub fn check_refresh_shares_with_dealer_serialisation<C: Ciphersuite, R: RngCore
assert!(key_package.is_ok());
}

/// We want to test that using a different min_signers than original fails.
pub fn check_refresh_shares_with_dealer_fails_with_different_min_signers<
C: Ciphersuite,
R: RngCore + CryptoRng,
>(
mut rng: R,
) {
// Compute shares

////////////////////////////////////////////////////////////////////////////
// Old Key generation
////////////////////////////////////////////////////////////////////////////

const MAX_SIGNERS: u16 = 5;
const MIN_SIGNERS: u16 = 3;
let (old_shares, pub_key_package) = generate_with_dealer(
MAX_SIGNERS,
MIN_SIGNERS,
frost::keys::IdentifierList::Default,
&mut rng,
)
.unwrap();

let mut old_key_packages: BTreeMap<frost::Identifier<C>, KeyPackage<C>> = BTreeMap::new();

for (k, v) in old_shares {
let key_package = KeyPackage::try_from(v).unwrap();
old_key_packages.insert(k, key_package);
}

////////////////////////////////////////////////////////////////////////////
// New Key generation
////////////////////////////////////////////////////////////////////////////

// Signer 2 will be removed and Signers 1, 3, 4 & 5 will remain

let remaining_ids = vec![
Identifier::try_from(1).unwrap(),
Identifier::try_from(3).unwrap(),
Identifier::try_from(4).unwrap(),
Identifier::try_from(5).unwrap(),
];

const NEW_MAX_SIGNERS: u16 = 4;
const NEW_MIN_SIGNERS: u16 = 2;

// Trusted Dealer generates zero keys and new public key package

let r = compute_refreshing_shares(
pub_key_package,
NEW_MAX_SIGNERS,
NEW_MIN_SIGNERS,
&remaining_ids,
&mut rng,
);

assert_eq!(r, Err(Error::InvalidMinSigners));
}

/// Test FROST signing with DKG with a Ciphersuite.
pub fn check_refresh_shares_with_dkg<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
mut rng: R,
Expand Down
10 changes: 1 addition & 9 deletions frost-ed25519/src/keys/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,10 @@ use super::{KeyPackage, PublicKeyPackage, SecretShare};
/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
pub fn compute_refreshing_shares<R: RngCore + CryptoRng>(
old_pub_key_package: PublicKeyPackage,
max_signers: u16,
min_signers: u16,
identifiers: &[Identifier],
mut rng: &mut R,
) -> Result<(Vec<SecretShare>, PublicKeyPackage), Error> {
frost::keys::refresh::compute_refreshing_shares(
old_pub_key_package,
max_signers,
min_signers,
identifiers,
&mut rng,
)
frost::keys::refresh::compute_refreshing_shares(old_pub_key_package, identifiers, &mut rng)
}

/// Refer to [`frost_core::keys::refresh::refresh_share`].
Expand Down
85 changes: 1 addition & 84 deletions frost-ed25519/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,77 +89,6 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_public_key_package() {
>(rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_invalid_min_signers() {
let rng = rand::rngs::OsRng;
let identifiers = vec![
Identifier::try_from(1).unwrap(),
Identifier::try_from(3).unwrap(),
Identifier::try_from(4).unwrap(),
Identifier::try_from(5).unwrap(),
];
let min_signers = 1;
let max_signers = 4;
let error = Error::InvalidMinSigners;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_invalid_signers::<
Ed25519Sha512,
_,
>(max_signers, min_signers, &identifiers, error, rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_unequal_num_identifiers_and_max_signers() {
let rng = rand::rngs::OsRng;
let identifiers = vec![
Identifier::try_from(1).unwrap(),
Identifier::try_from(3).unwrap(),
Identifier::try_from(4).unwrap(),
Identifier::try_from(5).unwrap(),
];
let min_signers = 2;
let max_signers = 3;
let error: frost_core::Error<Ed25519Sha512> = Error::IncorrectNumberOfIdentifiers;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_invalid_signers::<
Ed25519Sha512,
_,
>(max_signers, min_signers, &identifiers, error, rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_min_signers_greater_than_max() {
let rng = rand::rngs::OsRng;
let identifiers = vec![
Identifier::try_from(1).unwrap(),
Identifier::try_from(3).unwrap(),
Identifier::try_from(4).unwrap(),
Identifier::try_from(5).unwrap(),
];
let min_signers = 6;
let max_signers = 4;
let error: frost_core::Error<Ed25519Sha512> = Error::InvalidMinSigners;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_invalid_signers::<
Ed25519Sha512,
_,
>(max_signers, min_signers, &identifiers, error, rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_invalid_max_signers() {
let rng = rand::rngs::OsRng;
let identifiers = vec![Identifier::try_from(1).unwrap()];
let min_signers = 2;
let max_signers = 1;
let error = Error::InvalidMaxSigners;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_invalid_signers::<
Ed25519Sha512,
_,
>(max_signers, min_signers, &identifiers, error, rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
let rng = rand::rngs::OsRng;
Expand All @@ -169,24 +98,12 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
Identifier::try_from(4).unwrap(),
Identifier::try_from(6).unwrap(),
];
let min_signers = 2;
let max_signers = 4;
let error = Error::UnknownIdentifier;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_invalid_signers::<
Ed25519Sha512,
_,
>(max_signers, min_signers, &identifiers, error, rng);
}

#[test]
fn check_refresh_shares_with_dealer_fails_with_different_min_signers() {
let rng = rand::rngs::OsRng;

frost_core::tests::refresh::check_refresh_shares_with_dealer_fails_with_different_min_signers::<
Ed25519Sha512,
_,
>(rng);
>(&identifiers, error, rng);
}

#[test]
Expand Down
10 changes: 1 addition & 9 deletions frost-ed448/src/keys/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,10 @@ use super::{KeyPackage, PublicKeyPackage, SecretShare};
/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
pub fn compute_refreshing_shares<R: RngCore + CryptoRng>(
old_pub_key_package: PublicKeyPackage,
max_signers: u16,
min_signers: u16,
identifiers: &[Identifier],
mut rng: &mut R,
) -> Result<(Vec<SecretShare>, PublicKeyPackage), Error> {
frost::keys::refresh::compute_refreshing_shares(
old_pub_key_package,
max_signers,
min_signers,
identifiers,
&mut rng,
)
frost::keys::refresh::compute_refreshing_shares(old_pub_key_package, identifiers, &mut rng)
}

/// Refer to [`frost_core::keys::refresh::refresh_share`].
Expand Down
Loading
Loading