VYPR
Medium severityOSV Advisory· Published Sep 5, 2025· Updated Apr 15, 2026

CVE-2025-58359

CVE-2025-58359

Description

ZF FROST is a Rust implementation of FROST (Flexible Round-Optimised Schnorr Threshold signatures). In versions 2.0.0 through 2.1.0, refresh shares with smaller min_signers will reduce security of group. The inability to change min_signers (i.e. the threshold) with the refresh share functionality (frost_core::keys::refresh module) was not made clear to users. Using a smaller value would not decrease the threshold, and attempts to sign using a smaller threshold would fail. Additionally, after refreshing the shares with a smaller threshold, it would still be possible to sign with the original threshold, potentially causing a security loss to the participant's shares. This issue is fixed in version 2.2.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
frost-corecrates.io
>= 2.0.0, < 2.2.02.2.0

Affected products

1

Patches

1
379ef689c733

refresh: validate min_signers (#908)

24 files changed · +734 67
  • frost-core/Cargo.toml+3 1 modified
    @@ -45,7 +45,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Expose internal types, which do not have SemVer guarantees. This is an advanced
     ## feature which can be useful if you need to build a modified version of FROST.
    
  • frost-core/CHANGELOG.md+3 0 modified
    @@ -6,6 +6,9 @@ Entries are listed in reverse chronological order.
     
     * MSRV has been bumped to Rust 1.81, making all crates no-std (except
       `frost-ed448`). The `std` and `nightly` features were removed from all crates
    +* Added validation for the `min_signers` parameter in the
    +  `frost_core::keys::refresh` functions.
    +* Added DKG refresh functions to the crate-specific `refresh` modules.
     
     ## 2.1.0
     
    
  • frost-core/src/keys/dkg.rs+2 2 modified
    @@ -484,7 +484,7 @@ pub(crate) fn verify_proof_of_knowledge<C: Ciphersuite>(
     /// `round1_packages` maps the identifier of each other participant to the
     /// [`round1::Package`] they sent to the current participant (the owner of
     /// `secret_package`). These identifiers must come from whatever mapping the
    -/// coordinator has between communication channels and participants, i.e. they
    +/// participant has between communication channels and participants, i.e. they
     /// must have assurance that the [`round1::Package`] came from the participant
     /// with that identifier.
     ///
    @@ -561,7 +561,7 @@ pub fn part2<C: Ciphersuite>(
     /// `round2_packages` maps the identifier of each other participant to the
     /// [`round2::Package`] they sent to the current participant (the owner of
     /// `secret_package`). These identifiers must come from whatever mapping the
    -/// coordinator has between communication channels and participants, i.e. they
    +/// participant has between communication channels and participants, i.e. they
     /// must have assurance that the [`round2::Package`] came from the participant
     /// with that identifier.
     ///
    
  • frost-core/src/keys/refresh.rs+100 15 modified
    @@ -1,8 +1,27 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the
    -//! participation of all the remaining signers. This can be done using a Trusted
    -//! Dealer or DKG.
    +//! Refreshing shares has two purposes:
    +//!
    +//! - Mitigate against share compromise.
    +//! - Remove participants from a group.
    +//!
    +//! Refer to the [FROST
    +//! book](https://frost.zfnd.org/frost.html#refreshing-shares) for important
    +//! details.
    +//!
    +//! This modules supports refreshing shares using a Trusted Dealer or DKG. You
    +//! probably want to use the same approach as the original share generation.
    +//!
    +//! For the Trusted Dealer approach, the trusted dealer should call
    +//! [`compute_refreshing_shares()`] and send the returned refreshing shares to
    +//! the participants. Each participant should then call [`refresh_share()`].
    +//!
    +//! For the DKG approach, the flow is very similar to [DKG
    +//! itself](`https://frost.zfnd.org/tutorial/dkg.html`). Each participant calls
    +//! [`refresh_dkg_part_1()`], keeps the returned secret package and sends the
    +//! returned package to other participants. Then each participants calls
    +//! [`refresh_dkg_part2()`] and sends the returned packages to the other
    +//! participants. Finally each participant calls [`refresh_dkg_shares()`].
     
     use alloc::collections::BTreeMap;
     use alloc::vec::Vec;
    @@ -21,10 +40,20 @@ use core::iter;
     
     use super::{dkg::round1::Package, KeyPackage, SecretShare, VerifiableSecretSharingCommitment};
     
    -/// Generates new zero key shares and a public key package using a trusted
    -/// dealer Building a new public key package is done by taking the verifying
    -/// shares from the new public key package and adding them to the original
    -/// verifying shares
    +/// 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).
    +/// - `identifiers`: The identifiers of all participants that want to refresh
    +///   their shares. Must be the same length as `max_signers`.
    +///
    +/// 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,
    @@ -86,9 +115,11 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         Ok((refreshing_shares_minus_identity, refreshed_pub_key_package))
     }
     
    -/// Each participant refreshes their shares This is done by taking the
    -/// `refreshing_share` received from the trusted dealer and adding it to the
    -/// original share
    +/// Refresh a share in the Trusted Dealer refresh procedure.
    +///
    +/// Must be called by each participant refreshing the shares, with the
    +/// `refreshing_share` received from the trusted dealer and the
    +/// `current_key_package` of the participant.
     pub fn refresh_share<C: Ciphersuite>(
         mut refreshing_share: SecretShare<C>,
         current_key_package: &KeyPackage<C>,
    @@ -108,6 +139,10 @@ pub fn refresh_share<C: Ciphersuite>(
         // Verify refreshing_share secret share
         let refreshed_share_package = KeyPackage::<C>::try_from(refreshing_share)?;
     
    +    if refreshed_share_package.min_signers() != current_key_package.min_signers() {
    +        return Err(Error::InvalidMinSigners);
    +    }
    +
         let signing_share: SigningShare<C> = SigningShare::new(
             refreshed_share_package.signing_share.to_scalar()
                 + current_key_package.signing_share.to_scalar(),
    @@ -119,8 +154,20 @@ pub fn refresh_share<C: Ciphersuite>(
         Ok(new_key_package)
     }
     
    -/// Part 1 of refresh share with DKG. A refreshing_key is generated and a new package and secret_package are generated.
    -/// The identity commitment is removed from the packages.
    +/// Part 1 of refresh share with DKG.
    +///
    +/// - `identifier`: The identifier of the participant that wants to refresh
    +///   their share.
    +/// - `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).
    +///
    +/// It returns the [`round1::SecretPackage`] that must be kept in memory
    +/// by the participant for the other steps, and the [`round1::Package`] that
    +/// must be sent to each other participant in the refresh run.
     pub fn refresh_dkg_part_1<C: Ciphersuite, R: RngCore + CryptoRng>(
         identifier: Identifier<C>,
         max_signers: u16,
    @@ -164,7 +211,21 @@ pub fn refresh_dkg_part_1<C: Ciphersuite, R: RngCore + CryptoRng>(
         Ok((secret_package, package))
     }
     
    -/// Part 2 of refresh share with DKG. The identity commitment needs to be added back into the secret package.
    +/// Performs the second part of the refresh procedure for the
    +/// participant holding the given [`round1::SecretPackage`], given the received
    +/// [`round1::Package`]s received from the other participants.
    +///
    +/// `round1_packages` maps the identifier of each other participant to the
    +/// [`round1::Package`] they sent to the current participant (the owner of
    +/// `secret_package`). These identifiers must come from whatever mapping the
    +/// participant has between communication channels and participants, i.e. they
    +/// must have assurance that the [`round1::Package`] came from the participant
    +/// with that identifier.
    +///
    +/// It returns the [`round2::SecretPackage`] that must be kept in memory by the
    +/// participant for the final step, and the map of [`round2::Package`]s that
    +/// must be sent to each other participant who has the given identifier in the
    +/// map key.
     pub fn refresh_dkg_part2<C: Ciphersuite>(
         mut secret_package: round1::SecretPackage<C>,
         round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
    @@ -241,15 +302,39 @@ pub fn refresh_dkg_part2<C: Ciphersuite>(
         ))
     }
     
    -/// This is the step that actually refreshes the shares. New public key packages
    -/// and key packages are created.
    +/// Performs the third and final part of the refresh procedure for the
    +/// participant holding the given [`round2::SecretPackage`], given the received
    +/// [`round1::Package`]s and [`round2::Package`]s received from the other
    +/// participants.
    +///
    +/// `round1_packages` must be the same used in [`refresh_dkg_part2()`].
    +///
    +/// `round2_packages` maps the identifier of each other participant to the
    +/// [`round2::Package`] they sent to the current participant (the owner of
    +/// `secret_package`). These identifiers must come from whatever mapping the
    +/// participant has between communication channels and participants, i.e. they
    +/// must have assurance that the [`round2::Package`] came from the participant
    +/// with that identifier.
    +///
    +/// `old_pub_key_package` and `old_key_package` are the old values from the
    +/// participant, which are being refreshed.
    +///
    +/// It returns the refreshed [`KeyPackage`] that has the long-lived key share
    +/// for the participant, and the refreshed [`PublicKeyPackage`]s that has public
    +/// information about all participants; both of which are required to compute
    +/// FROST signatures. Note that while the verifying (group) key of the
    +/// [`PublicKeyPackage`] will stay the same, the verifying shares will change.
     pub fn refresh_dkg_shares<C: Ciphersuite>(
         round2_secret_package: &round2::SecretPackage<C>,
         round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
         round2_packages: &BTreeMap<Identifier<C>, round2::Package<C>>,
         old_pub_key_package: PublicKeyPackage<C>,
         old_key_package: KeyPackage<C>,
     ) -> Result<(KeyPackage<C>, PublicKeyPackage<C>), Error<C>> {
    +    if round2_secret_package.min_signers() != old_key_package.min_signers() {
    +        return Err(Error::InvalidMinSigners);
    +    }
    +
         // Add identity commitment back into round1_packages
         let mut new_round_1_packages = BTreeMap::new();
         for (sender_identifier, round1_package) in round1_packages {
    
  • frost-core/src/tests/refresh.rs+225 0 modified
    @@ -245,6 +245,83 @@ 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 (zero_shares, _new_pub_key_package) = compute_refreshing_shares(
    +        pub_key_package,
    +        NEW_MAX_SIGNERS,
    +        NEW_MIN_SIGNERS,
    +        &remaining_ids,
    +        &mut rng,
    +    )
    +    .unwrap();
    +
    +    // Each participant refreshes their share
    +
    +    let mut new_shares = BTreeMap::new();
    +
    +    for i in 0..remaining_ids.len() {
    +        let identifier = remaining_ids[i];
    +        let current_share = &old_key_packages[&identifier];
    +        let new_share = refresh_share(zero_shares[i].clone(), current_share);
    +        new_shares.insert(identifier, new_share);
    +    }
    +
    +    assert!(
    +        new_shares
    +            .iter()
    +            .all(|(_, v)| v.is_err() && matches!(v, Err(Error::InvalidMinSigners))),
    +        "{:?}",
    +        new_shares
    +    );
    +}
    +
     /// Test FROST signing with DKG with a Ciphersuite.
     pub fn check_refresh_shares_with_dkg<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
         mut rng: R,
    @@ -429,3 +506,151 @@ where
         // Proceed with the signing test.
         check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
     }
    +
    +/// Test FROST signing with DKG with a Ciphersuite, using a smaller
    +/// threshold than the original one.
    +pub fn check_refresh_shares_with_dkg_smaller_threshold<
    +    C: Ciphersuite + PartialEq,
    +    R: RngCore + CryptoRng,
    +>(
    +    mut rng: R,
    +) where
    +    C::Group: core::cmp::PartialEq,
    +{
    +    ////////////////////////////////////////////////////////////////////////////
    +    // Old Key generation
    +    ////////////////////////////////////////////////////////////////////////////
    +
    +    let old_max_signers = 5;
    +    let min_signers = 3;
    +    let (old_shares, pub_key_package) = generate_with_dealer(
    +        old_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);
    +    }
    +
    +    ////////////////////////////////////////////////////////////////////////////
    +    // Key generation, Round 1
    +    ////////////////////////////////////////////////////////////////////////////
    +
    +    let max_signers = 4;
    +    // Use a smaller threshold than the original
    +    let min_signers = 2;
    +
    +    let remaining_ids = vec![
    +        Identifier::try_from(4).unwrap(),
    +        Identifier::try_from(2).unwrap(),
    +        Identifier::try_from(3).unwrap(),
    +        Identifier::try_from(1).unwrap(),
    +    ];
    +
    +    // Keep track of each participant's round 1 secret package.
    +    // In practice each participant will keep its copy; no one
    +    // will have all the participant's packages.
    +    let mut round1_secret_packages: BTreeMap<
    +        frost::Identifier<C>,
    +        frost::keys::dkg::round1::SecretPackage<C>,
    +    > = BTreeMap::new();
    +
    +    // Keep track of all round 1 packages sent to the given participant.
    +    // This is used to simulate the broadcast; in practice the packages
    +    // will be sent through some communication channel.
    +    let mut received_round1_packages: BTreeMap<
    +        frost::Identifier<C>,
    +        BTreeMap<frost::Identifier<C>, frost::keys::dkg::round1::Package<C>>,
    +    > = BTreeMap::new();
    +
    +    // For each participant, perform the first part of the DKG protocol.
    +    // In practice, each participant will perform this on their own environments.
    +    for participant_identifier in remaining_ids.clone() {
    +        let (round1_secret_package, round1_package) =
    +            refresh_dkg_part_1(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.
    +        round1_secret_packages.insert(participant_identifier, round1_secret_package);
    +
    +        // "Send" the round 1 package to all other participants. In this
    +        // test this is simulated using a BTreeMap; in practice this will be
    +        // sent through some communication channel.
    +        for receiver_participant_identifier in remaining_ids.clone() {
    +            if receiver_participant_identifier == participant_identifier {
    +                continue;
    +            }
    +            received_round1_packages
    +                .entry(receiver_participant_identifier)
    +                .or_default()
    +                .insert(participant_identifier, round1_package.clone());
    +        }
    +    }
    +
    +    ////////////////////////////////////////////////////////////////////////////
    +    // Key generation, Round 2
    +    ////////////////////////////////////////////////////////////////////////////
    +    // Keep track of each participant's round 2 secret package.
    +    // In practice each participant will keep its copy; no one
    +    // will have all the participant's packages.
    +    let mut round2_secret_packages = BTreeMap::new();
    +
    +    // Keep track of all round 2 packages sent to the given participant.
    +    // This is used to simulate the broadcast; in practice the packages
    +    // will be sent through some communication channel.
    +    let mut received_round2_packages = BTreeMap::new();
    +
    +    // For each participant, perform the second part of the DKG protocol.
    +    // In practice, each participant will perform this on their own environments.
    +    for participant_identifier in remaining_ids.clone() {
    +        let round1_secret_package = round1_secret_packages
    +            .remove(&participant_identifier)
    +            .unwrap();
    +        let round1_packages = &received_round1_packages[&participant_identifier];
    +        let (round2_secret_package, round2_packages) =
    +            refresh_dkg_part2(round1_secret_package, round1_packages).expect("should work");
    +
    +        // Store the participant's secret package for later use.
    +        // In practice each participant will store it in their own environment.
    +        round2_secret_packages.insert(participant_identifier, round2_secret_package);
    +
    +        // "Send" the round 2 package to all other participants. In this
    +        // test this is simulated using a BTreeMap; in practice this will be
    +        // sent through some communication channel.
    +        // Note that, in contrast to the previous part, here each other participant
    +        // gets its own specific package.
    +        for (receiver_identifier, round2_package) in round2_packages {
    +            received_round2_packages
    +                .entry(receiver_identifier)
    +                .or_insert_with(BTreeMap::new)
    +                .insert(participant_identifier, round2_package);
    +        }
    +    }
    +
    +    ////////////////////////////////////////////////////////////////////////////
    +    // Key generation, final computation
    +    ////////////////////////////////////////////////////////////////////////////
    +
    +    // For each participant, this is where they refresh their shares
    +    // In practice, each participant will perform this on their own environments.
    +    let mut results = Vec::new();
    +    for participant_identifier in remaining_ids.clone() {
    +        results.push(frost::keys::refresh::refresh_dkg_shares(
    +            &round2_secret_packages[&participant_identifier],
    +            &received_round1_packages[&participant_identifier],
    +            &received_round2_packages[&participant_identifier],
    +            pub_key_package.clone(),
    +            old_key_packages[&participant_identifier].clone(),
    +        ));
    +    }
    +
    +    assert!(results
    +        .iter()
    +        .all(|r| matches!(r, Err(Error::InvalidMinSigners))));
    +}
    
  • frost-ed25519/Cargo.toml+3 1 modified
    @@ -37,7 +37,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-ed25519/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-ed25519/tests/integration_tests.rs+19 0 modified
    @@ -179,13 +179,32 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<Ed25519Sha512, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<Ed25519Sha512, _>(
    +        rng,
    +    );
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    
  • frost-ed448/Cargo.toml+3 1 modified
    @@ -36,7 +36,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-ed448/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-ed448/tests/integration_tests.rs+19 0 modified
    @@ -179,13 +179,32 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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::<
    +        Ed448Shake256,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<Ed448Shake256, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<Ed448Shake256, _>(
    +        rng,
    +    );
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    
  • frost-p256/Cargo.toml+3 1 modified
    @@ -36,7 +36,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-p256/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-p256/tests/integration_tests.rs+19 0 modified
    @@ -179,13 +179,32 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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::<
    +        P256Sha256,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<P256Sha256, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<P256Sha256, _>(
    +        rng,
    +    );
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    
  • frost-rerandomized/Cargo.toml+3 1 modified
    @@ -25,7 +25,9 @@ rand_core.workspace = true
     [dev-dependencies]
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-ristretto255/Cargo.toml+3 1 modified
    @@ -37,7 +37,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-ristretto255/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-ristretto255/tests/integration_tests.rs+20 0 modified
    @@ -180,13 +180,33 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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::<
    +        Ristretto255Sha512,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<Ristretto255Sha512, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<
    +        Ristretto255Sha512,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    
  • frost-secp256k1/Cargo.toml+3 1 modified
    @@ -36,7 +36,9 @@ rand_chacha.workspace = true
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-secp256k1/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-secp256k1/tests/integration_tests.rs+19 0 modified
    @@ -179,13 +179,32 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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::<
    +        Secp256K1Sha256,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<Secp256K1Sha256, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<Secp256K1Sha256, _>(
    +        rng,
    +    );
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    
  • frost-secp256k1-tr/Cargo.toml+3 1 modified
    @@ -37,7 +37,9 @@ secp256k1 = "0.31.0"
     serde_json.workspace = true
     
     [features]
    -default = ["serialization", "cheater-detection"]
    +default = ["serialization", "cheater-detection", "std"]
    +# No longer needed. Kept for retrocompatibility until 3.0.0
    +std = []
     #! ## Features
     ## Enable `serde` support for types that need to be communicated. You
     ## can use `serde` to serialize structs with any encoder that supports
    
  • frost-secp256k1-tr/src/keys/refresh.rs+44 7 modified
    @@ -1,15 +1,17 @@
     //! Refresh Shares
     //!
    -//! Implements the functionality to refresh a share. This requires the participation
    -//! of all the remaining signers. This can be done using a Trusted Dealer or
    -//! DKG (not yet implemented)
    +//! Refer to [`frost_core::keys::refresh`] for more details.
     
    -use crate::{frost, Ciphersuite, CryptoRng, Error, Identifier, RngCore};
    -use alloc::vec::Vec;
    +use crate::{
    +    frost,
    +    keys::dkg::{round1, round2},
    +    Ciphersuite, CryptoRng, Error, Identifier, RngCore,
    +};
    +use alloc::{collections::btree_map::BTreeMap, vec::Vec};
     
     use super::{KeyPackage, PublicKeyPackage, SecretShare};
     
    -/// Refreshes shares using a trusted dealer
    +/// Refer to [`frost_core::keys::refresh::compute_refreshing_shares`].
     pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         old_pub_key_package: PublicKeyPackage,
         max_signers: u16,
    @@ -26,10 +28,45 @@ pub fn compute_refreshing_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
         )
     }
     
    -/// Each participant refreshed their shares
    +/// Refer to [`frost_core::keys::refresh::refresh_share`].
     pub fn refresh_share<C: Ciphersuite>(
         zero_share: SecretShare,
         current_share: &KeyPackage,
     ) -> Result<KeyPackage, Error> {
         frost::keys::refresh::refresh_share(zero_share, current_share)
     }
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part_1`].
    +pub fn refresh_dkg_part1<R: RngCore + CryptoRng>(
    +    identifier: Identifier,
    +    max_signers: u16,
    +    min_signers: u16,
    +    mut rng: R,
    +) -> Result<(round1::SecretPackage, round1::Package), Error> {
    +    frost::keys::refresh::refresh_dkg_part_1(identifier, max_signers, min_signers, &mut rng)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_part2`].
    +pub fn refresh_dkg_part2(
    +    secret_package: round1::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +) -> Result<(round2::SecretPackage, BTreeMap<Identifier, round2::Package>), Error> {
    +    frost::keys::refresh::refresh_dkg_part2(secret_package, round1_packages)
    +}
    +
    +/// Refer to [`frost_core::keys::refresh::refresh_dkg_shares`].
    +pub fn refresh_dkg_shares(
    +    round2_secret_package: &round2::SecretPackage,
    +    round1_packages: &BTreeMap<Identifier, round1::Package>,
    +    round2_packages: &BTreeMap<Identifier, round2::Package>,
    +    old_pub_key_package: PublicKeyPackage,
    +    old_key_package: KeyPackage,
    +) -> Result<(KeyPackage, PublicKeyPackage), Error> {
    +    frost::keys::refresh::refresh_dkg_shares(
    +        round2_secret_package,
    +        round1_packages,
    +        round2_packages,
    +        old_pub_key_package,
    +        old_key_package,
    +    )
    +}
    
  • frost-secp256k1-tr/tests/integration_tests.rs+20 0 modified
    @@ -180,13 +180,33 @@ fn check_refresh_shares_with_dealer_fails_with_invalid_identifier() {
         >(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::<
    +        Secp256K1Sha256TR,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_refresh_shares_with_dkg() {
         let rng = rand::rngs::OsRng;
     
         frost_core::tests::refresh::check_refresh_shares_with_dkg::<Secp256K1Sha256TR, _>(rng);
     }
     
    +#[test]
    +fn check_refresh_shares_with_dkg_smaller_threshold() {
    +    let rng = rand::rngs::OsRng;
    +
    +    frost_core::tests::refresh::check_refresh_shares_with_dkg_smaller_threshold::<
    +        Secp256K1Sha256TR,
    +        _,
    +    >(rng);
    +}
    +
     #[test]
     fn check_sign_with_dealer() {
         let rng = rand::rngs::OsRng;
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.