add computing PublicKeyPackage from commitments (#551)

* Refactor computing the public key package and expose it.

* Fix clippy issue.

* Add test.

* Fix test.

* Improve test.

* Split it up.

* Fix build.

* Improve api.

* Expose more stuff.

* Expose more stuff.

* Extract proof of knowledge verification.

* Add construct_proof_of_knowledge.

* fix dkg test

* overall cleanup

* change IncorrectCommitment to IncorrectNumberOfCommitments

* clippy fixes

* fix order of inputs for DKG commitment hashing

* also change regular challenge() verifying key argument to VerifyingKey

---------

Co-authored-by: David Craven <david@craven.ch>
This commit is contained in:
Conrado Gouvea 2023-10-27 08:48:54 -03:00 committed by GitHub
parent e0db6151e0
commit 71c092532c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 267 additions and 122 deletions

View File

@ -14,6 +14,9 @@ Entries are listed in reverse chronological order.
string was also changed for all ciphersuites: it is now equal to the
`contextString` of each ciphersuite per the FROST spec.
* An option to disable cheater detection during aggregation of signatures has been added.
* Added `PublicKeyPackage::from_commitment()` and
`PublicKeyPackage::from_dkg_commitments` to create a `PublicKeyPackage` from
the commitments generated in trusted dealer or distributed key generation.
## Released

View File

@ -32,7 +32,7 @@ where
{
fn from((vk, sig, msg): (VerifyingKey<C>, Signature<C>, &'msg M)) -> Self {
// Compute c now to avoid dependency on the msg lifetime.
let c = crate::challenge(&sig.R, &vk.element, msg.as_ref());
let c = crate::challenge(&sig.R, &vk, msg.as_ref());
Self { vk, sig, c }
}

View File

@ -467,7 +467,7 @@ where
// Compute the per-message challenge.
let challenge = crate::challenge::<C>(
&group_commitment.0,
&pubkeys.verifying_key.element,
&pubkeys.verifying_key,
signing_package.message().as_slice(),
);

View File

@ -29,6 +29,35 @@ use super::compute_lagrange_coefficient;
pub mod dkg;
pub mod repairable;
/// Sum the commitments from all participants in a distributed key generation
/// run into a single group commitment.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn sum_commitments<C: Ciphersuite>(
commitments: &[&VerifiableSecretSharingCommitment<C>],
) -> Result<VerifiableSecretSharingCommitment<C>, Error<C>> {
let mut group_commitment = vec![
CoefficientCommitment(<C::Group>::identity());
commitments
.get(0)
.ok_or(Error::IncorrectNumberOfCommitments)?
.0
.len()
];
for commitment in commitments {
for (i, c) in group_commitment.iter_mut().enumerate() {
*c = CoefficientCommitment(
c.value()
+ commitment
.0
.get(i)
.ok_or(Error::IncorrectNumberOfCommitments)?
.value(),
);
}
}
Ok(VerifiableSecretSharingCommitment(group_commitment))
}
/// Return a vector of randomly generated polynomial coefficients ([`Scalar`]s).
pub(crate) fn generate_coefficients<C: Ciphersuite, R: RngCore + CryptoRng>(
size: usize,
@ -40,6 +69,7 @@ pub(crate) fn generate_coefficients<C: Ciphersuite, R: RngCore + CryptoRng>(
}
/// Return a list of default identifiers (1 to max_signers, inclusive).
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn default_identifiers<C: Ciphersuite>(max_signers: u16) -> Vec<Identifier<C>> {
(1..=max_signers)
.map(|i| Identifier::<C>::try_from(i).expect("nonzero"))
@ -83,6 +113,12 @@ where
pub fn serialize(&self) -> <<C::Group as Group>::Field as Field>::Serialization {
<<C::Group as Group>::Field>::serialize(&self.0)
}
/// Computes the signing share from a list of coefficients.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn from_coefficients(coefficients: &[Scalar<C>], peer: Identifier<C>) -> Self {
Self(evaluate_polynomial(peer, coefficients))
}
}
impl<C> Debug for SigningShare<C>
@ -181,6 +217,26 @@ where
pub fn serialize(&self) -> <C::Group as Group>::Serialization {
<C::Group as Group>::serialize(&self.0)
}
/// Computes a verifying share for a peer given the group commitment.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn from_commitment(
identifier: Identifier<C>,
commitment: &VerifiableSecretSharingCommitment<C>,
) -> VerifyingShare<C> {
// DKG Round 2, Step 4
//
// > Any participant can compute the public verification share of any
// > other participant by calculating
// > Y_i = ∏_{j=1}^n ∏_{k=0}^{t1} φ_{jk}^{i^k mod q}.
//
// Rewriting the equation by moving the product over j to further inside
// the equation:
// Y_i = ∏_{k=0}^{t1} (∏_{j=1}^n φ_{jk})^{i^k mod q}
// i.e. we can operate on the sum of all φ_j commitments, which is
// what is passed to the functions.
VerifyingShare(evaluate_vss(identifier, commitment))
}
}
impl<C> Debug for VerifyingShare<C>
@ -334,10 +390,18 @@ where
Ok(Self(coefficient_commitments))
}
/// Get the first commitment (which is equivalent to the VerifyingKey),
/// or an error if the vector is empty.
pub(crate) fn first(&self) -> Result<CoefficientCommitment<C>, Error<C>> {
self.0.get(0).ok_or(Error::MissingCommitment).copied()
/// Get the VerifyingKey matching this commitment vector (which is the first
/// element in the vector), or an error if the vector is empty.
pub(crate) fn verifying_key(&self) -> Result<VerifyingKey<C>, Error<C>> {
Ok(VerifyingKey::new(
self.0.get(0).ok_or(Error::MissingCommitment)?.0,
))
}
/// Returns the coefficient commitments.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn coefficients(&self) -> &[CoefficientCommitment<C>] {
&self.0
}
}
@ -404,17 +468,13 @@ where
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#appendix-C.2-4
pub fn verify(&self) -> Result<(VerifyingShare<C>, VerifyingKey<C>), Error<C>> {
let f_result = <C::Group>::generator() * self.signing_share.0;
let result = evaluate_vss(&self.commitment, self.identifier);
let result = evaluate_vss(self.identifier, &self.commitment);
if !(f_result == result) {
return Err(Error::InvalidSecretShare);
}
let verifying_key = VerifyingKey {
element: self.commitment.first()?.0,
};
Ok((VerifyingShare(result), verifying_key))
Ok((VerifyingShare(result), self.commitment.verifying_key()?))
}
}
@ -547,11 +607,13 @@ fn evaluate_polynomial<C: Ciphersuite>(
}
/// Evaluates the right-hand side of the VSS verification equation, namely
/// ∏^{t1}_{k=0} φ^{i^k mod q}_{k} using `identifier` as `i` and the
/// `commitment` as the commitment vector φ_
/// ∏^{t1}_{k=0} φ^{i^k mod q}_{k} (multiplicative notation) using
/// `identifier` as `i` and the `commitment` as the commitment vector φ_.
///
/// This is also used in Round 2, Step 4 of the DKG.
fn evaluate_vss<C: Ciphersuite>(
commitment: &VerifiableSecretSharingCommitment<C>,
identifier: Identifier<C>,
commitment: &VerifiableSecretSharingCommitment<C>,
) -> Element<C> {
let i = identifier;
@ -691,6 +753,38 @@ where
verifying_key,
}
}
/// Computes the public key package given a list of participant identifiers
/// and a [`VerifiableSecretSharingCommitment`]. This is useful in scenarios
/// where the commitments are published somewhere and it's desirable to
/// recreate the public key package from them.
pub fn from_commitment(
identifiers: &BTreeSet<Identifier<C>>,
commitment: &VerifiableSecretSharingCommitment<C>,
) -> Result<PublicKeyPackage<C>, Error<C>> {
let verifying_keys: BTreeMap<_, _> = identifiers
.iter()
.map(|id| (*id, VerifyingShare::from_commitment(*id, commitment)))
.collect();
Ok(PublicKeyPackage::new(
verifying_keys,
VerifyingKey::from_commitment(commitment)?,
))
}
/// Computes the public key package given a map of participant identifiers
/// and their [`VerifiableSecretSharingCommitment`] from a distributed key
/// generation process. This is useful in scenarios where the commitments
/// are published somewhere and it's desirable to recreate the public key
/// package from them.
pub fn from_dkg_commitments(
commitments: &BTreeMap<Identifier<C>, &VerifiableSecretSharingCommitment<C>>,
) -> Result<PublicKeyPackage<C>, Error<C>> {
let identifiers: BTreeSet<_> = commitments.keys().copied().collect();
let commitments: Vec<_> = commitments.values().copied().collect();
let group_commitment = sum_commitments(&commitments)?;
Self::from_commitment(&identifiers, &group_commitment)
}
}
#[cfg(feature = "serialization")]

View File

@ -40,9 +40,9 @@ use crate::{
};
use super::{
evaluate_polynomial, evaluate_vss, generate_coefficients, generate_secret_polynomial,
evaluate_polynomial, generate_coefficients, generate_secret_polynomial,
validate_num_of_signers, KeyPackage, PublicKeyPackage, SecretShare, SigningShare,
VerifiableSecretSharingCommitment, VerifyingShare,
VerifiableSecretSharingCommitment,
};
/// DKG Round 1 structures.
@ -124,6 +124,17 @@ pub mod round1 {
pub(crate) max_signers: u16,
}
impl<C> SecretPackage<C>
where
C: Ciphersuite,
{
/// Returns the secret coefficients.
#[cfg(feature = "internals")]
pub fn coefficients(&self) -> &[Scalar<C>] {
&self.coefficients
}
}
impl<C> std::fmt::Debug for SecretPackage<C>
where
C: Ciphersuite,
@ -280,22 +291,8 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
let coefficients = generate_coefficients::<C, R>(min_signers as usize - 1, &mut rng);
let (coefficients, commitment) =
generate_secret_polynomial(&secret, max_signers, min_signers, coefficients)?;
// Round 1, Step 2
//
// > Every P_i computes a proof of knowledge to the corresponding secret
// > a_{i0} by calculating σ_i = (R_i, μ_i), such that k ← Z_q, R_i = g^k,
// > c_i = H(i, Φ, g^{a_{i0}} , R_i), μ_i = k + a_{i0} · c_i, with Φ being
// > a context string to prevent replay attacks.
let k = <<C::Group as Group>::Field>::random(&mut rng);
let R_i = <C::Group>::generator() * k;
let c_i =
challenge::<C>(identifier, &commitment.first()?.0, &R_i).ok_or(Error::DKGNotSupported)?;
let a_i0 = *coefficients
.get(0)
.expect("coefficients must have at least one element");
let mu_i = k + a_i0 * c_i.0;
let proof_of_knowledge =
compute_proof_of_knowledge(identifier, &coefficients, &commitment, &mut rng)?;
let secret_package = round1::SecretPackage {
identifier,
@ -307,7 +304,7 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
let package = round1::Package {
header: Header::default(),
commitment,
proof_of_knowledge: Signature { R: R_i, z: mu_i },
proof_of_knowledge,
};
Ok((secret_package, package))
@ -316,7 +313,7 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
/// Generates the challenge for the proof of knowledge to a secret for the DKG.
fn challenge<C>(
identifier: Identifier<C>,
verifying_key: &Element<C>,
verifying_key: &VerifyingKey<C>,
R: &Element<C>,
) -> Option<Challenge<C>>
where
@ -325,12 +322,62 @@ where
let mut preimage = vec![];
preimage.extend_from_slice(identifier.serialize().as_ref());
preimage.extend_from_slice(<C::Group>::serialize(verifying_key).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key.element).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
Some(Challenge(C::HDKG(&preimage[..])?))
}
/// Compute the proof of knowledge of the secret coefficients used to generate
/// the public secret sharing commitment.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn compute_proof_of_knowledge<C: Ciphersuite, R: RngCore + CryptoRng>(
identifier: Identifier<C>,
coefficients: &[Scalar<C>],
commitment: &VerifiableSecretSharingCommitment<C>,
mut rng: R,
) -> Result<Signature<C>, Error<C>> {
// Round 1, Step 2
//
// > Every P_i computes a proof of knowledge to the corresponding secret
// > a_{i0} by calculating σ_i = (R_i, μ_i), such that k ← Z_q, R_i = g^k,
// > c_i = H(i, Φ, g^{a_{i0}} , R_i), μ_i = k + a_{i0} · c_i, with Φ being
// > a context string to prevent replay attacks.
let k = <<C::Group as Group>::Field>::random(&mut rng);
let R_i = <C::Group>::generator() * k;
let c_i = challenge::<C>(identifier, &commitment.verifying_key()?, &R_i)
.ok_or(Error::DKGNotSupported)?;
let a_i0 = *coefficients
.get(0)
.expect("coefficients must have at least one element");
let mu_i = k + a_i0 * c_i.0;
Ok(Signature { R: R_i, z: mu_i })
}
/// Verifies the proof of knowledge of the secret coefficients used to generate the
/// public secret sharing commitment.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn verify_proof_of_knowledge<C: Ciphersuite>(
identifier: Identifier<C>,
commitment: &VerifiableSecretSharingCommitment<C>,
proof_of_knowledge: Signature<C>,
) -> Result<(), Error<C>> {
// Round 1, Step 5
//
// > Upon receiving C⃗_, σ_ from participants 1 ≤ ≤ n, ≠ i, participant
// > P_i verifies σ_ = (R_, μ_), aborting on failure, by checking
// > R_ ? ≟ g^{μ_} · φ^{-c_}_{0}, where c_ = H(, Φ, φ_{0}, R_).
let ell = identifier;
let R_ell = proof_of_knowledge.R;
let mu_ell = proof_of_knowledge.z;
let phi_ell0 = commitment.verifying_key()?;
let c_ell = challenge::<C>(ell, &phi_ell0, &R_ell).ok_or(Error::DKGNotSupported)?;
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0.element * c_ell.0 {
return Err(Error::InvalidProofOfKnowledge { culprit: ell });
}
Ok(())
}
/// Performs the second part of the distributed key generation protocol
/// for the participant holding the given [`round1::SecretPackage`],
/// given the received [`round1::Package`]s received from the other participants.
@ -363,18 +410,11 @@ pub fn part2<C: Ciphersuite>(
for (sender_identifier, round1_package) in round1_packages {
let ell = *sender_identifier;
// Round 1, Step 5
//
// > Upon receiving C⃗_, σ_ from participants 1 ≤ ≤ n, ≠ i, participant
// > P_i verifies σ_ = (R_, μ_), aborting on failure, by checking
// > R_ ? ≟ g^{μ_} · φ^{-c_}_{0}, where c_ = H(, Φ, φ_{0}, R_).
let R_ell = round1_package.proof_of_knowledge.R;
let mu_ell = round1_package.proof_of_knowledge.z;
let phi_ell0 = round1_package.commitment.first()?.0;
let c_ell = challenge::<C>(ell, &phi_ell0, &R_ell).ok_or(Error::DKGNotSupported)?;
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0 * c_ell.0 {
return Err(Error::InvalidProofOfKnowledge { culprit: ell });
}
verify_proof_of_knowledge(
ell,
&round1_package.commitment,
round1_package.proof_of_knowledge,
)?;
// Round 2, Step 1
//
@ -404,47 +444,6 @@ pub fn part2<C: Ciphersuite>(
))
}
/// Computes the verifying shares of the other participants for the third step
/// of the DKG protocol.
fn compute_verifying_shares<C: Ciphersuite>(
round1_packages: &BTreeMap<Identifier<C>, round1::Package<C>>,
round2_secret_package: &round2::SecretPackage<C>,
) -> Result<BTreeMap<Identifier<C>, VerifyingShare<C>>, Error<C>> {
// Round 2, Step 4
//
// > Any participant can compute the public verification share of any other participant
// > by calculating Y_i = ∏_{j=1}^n ∏_{k=0}^{t1} φ_{jk}^{i^k mod q}.
let mut others_verifying_shares = BTreeMap::new();
// Note that in this loop, "i" refers to the other participant whose public verification share
// we are computing, and not the current participant.
for i in round1_packages.keys().cloned() {
let mut y_i = <C::Group>::identity();
// We need to iterate through all commitment vectors, including our own,
// so chain it manually
for commitment in round1_packages
.keys()
.map(|k| {
// Get the commitment vector for this participant
Ok::<&VerifiableSecretSharingCommitment<C>, Error<C>>(
&round1_packages
.get(k)
.ok_or(Error::PackageNotFound)?
.commitment,
)
})
// Chain our own commitment vector
.chain(iter::once(Ok(&round2_secret_package.commitment)))
{
y_i = y_i + evaluate_vss(commitment?, i);
}
let y_i = VerifyingShare(y_i);
others_verifying_shares.insert(i, y_i);
}
Ok(others_verifying_shares)
}
/// Performs the third and final part of the distributed key generation protocol
/// for the participant holding the given [`round2::SecretPackage`],
/// given the received [`round1::Package`]s and [`round2::Package`]s received from
@ -481,7 +480,6 @@ pub fn part3<C: Ciphersuite>(
}
let mut signing_share = <<C::Group as Group>::Field>::zero();
let mut verifying_key = <C::Group>::identity();
for (sender_identifier, round2_package) in round2_packages {
// Round 2, Step 2
@ -515,48 +513,33 @@ pub fn part3<C: Ciphersuite>(
// > Each P_i calculates their long-lived private signing share by computing
// > s_i = ∑^n_{=1} f_(i), stores s_i securely, and deletes each f_(i).
signing_share = signing_share + f_ell_i.0;
// Round 2, Step 4
//
// > Each P_i calculates [...] the groups public key Y = ∏^n_{j=1} φ_{j0}.
verifying_key = verifying_key + commitment.first()?.0;
}
signing_share = signing_share + round2_secret_package.secret_share;
verifying_key = verifying_key + round2_secret_package.commitment.first()?.0;
let signing_share = SigningShare(signing_share);
// Round 2, Step 4
//
// > Each P_i calculates their public verification share Y_i = g^{s_i}.
let verifying_share = signing_share.into();
let verifying_key = VerifyingKey {
element: verifying_key,
};
// Round 2, Step 4
//
// > Any participant can compute the public verification share of any other participant
// > by calculating Y_i = ∏_{j=1}^n ∏_{k=0}^{t1} φ_{jk}^{i^k mod q}.
let mut all_verifying_shares =
compute_verifying_shares(round1_packages, round2_secret_package)?;
// Add the participant's own public verification share for consistency
all_verifying_shares.insert(round2_secret_package.identifier, verifying_share);
let commitments: BTreeMap<_, _> = round1_packages
.iter()
.map(|(id, package)| (*id, &package.commitment))
.chain(iter::once((
round2_secret_package.identifier,
&round2_secret_package.commitment,
)))
.collect();
let public_key_package = PublicKeyPackage::from_dkg_commitments(&commitments)?;
let key_package = KeyPackage {
header: Header::default(),
identifier: round2_secret_package.identifier,
signing_share,
verifying_share,
verifying_key,
verifying_key: public_key_package.verifying_key,
min_signers: round2_secret_package.min_signers,
};
let public_key_package = PublicKeyPackage {
header: Header::default(),
verifying_shares: all_verifying_shares,
verifying_key,
};
Ok((key_package, public_key_package))
}

View File

@ -217,7 +217,7 @@ pub fn sign<C: Ciphersuite>(
// Compute the per-message challenge.
let challenge = challenge::<C>(
&group_commitment.0,
&key_package.verifying_key.element,
&key_package.verifying_key,
signing_package.message.as_slice(),
);

View File

@ -341,7 +341,7 @@ pub trait Ciphersuite: Copy + Clone + PartialEq + Debug {
signature: &Signature<Self>,
public_key: &VerifyingKey<Self>,
) -> Result<(), Error<Self>> {
let c = crate::challenge::<Self>(&signature.R, &public_key.element, msg);
let c = crate::challenge::<Self>(&signature.R, public_key, msg);
public_key.verify_prehashed(c, signature)
}
@ -405,14 +405,14 @@ where
/// [RFC]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-3.2
#[cfg_attr(feature = "internals", visibility::make(pub))]
#[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
fn challenge<C>(R: &Element<C>, verifying_key: &Element<C>, msg: &[u8]) -> Challenge<C>
fn challenge<C>(R: &Element<C>, verifying_key: &VerifyingKey<C>, msg: &[u8]) -> Challenge<C>
where
C: Ciphersuite,
{
let mut preimage = vec![];
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(verifying_key).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key.element).as_ref());
preimage.extend_from_slice(msg);
Challenge(C::H2(&preimage[..]))

View File

@ -50,7 +50,7 @@ where
let R = <C::Group>::generator() * k;
// Generate Schnorr challenge
let c = crate::challenge::<C>(&R, &VerifyingKey::<C>::from(*self).element, msg);
let c = crate::challenge::<C>(&R, &VerifyingKey::<C>::from(*self), msg);
let z = k + (c.0 * self.scalar);

View File

@ -11,6 +11,7 @@ use debugless_unwrap::DebuglessUnwrap;
use rand_core::{CryptoRng, RngCore};
use serde_json::Value;
use crate::frost::keys::{generate_with_dealer, IdentifierList, PublicKeyPackage};
use crate::Ciphersuite;
/// Test serialize VerifiableSecretSharingCommitment
@ -107,3 +108,20 @@ pub fn check_deserialize_vss_commitment_error<C: Ciphersuite, R: RngCore + Crypt
assert!(vss_value.is_err());
}
/// Test computing the public key package from a list of commitments.
pub fn check_compute_public_key_package<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
let max_signers = 3;
let min_signers = 2;
let (secret_shares, public_key_package) =
generate_with_dealer::<C, _>(max_signers, min_signers, IdentifierList::Default, &mut rng)
.unwrap();
let members = secret_shares.keys().copied().collect();
let group_commitment = secret_shares.values().next().unwrap().commitment().clone();
assert_eq!(
public_key_package,
PublicKeyPackage::from_commitment(&members, &group_commitment).unwrap()
);
}

View File

@ -26,8 +26,9 @@ where
C: Ciphersuite,
{
/// Create a new VerifyingKey from the given element.
#[cfg(feature = "internals")]
pub fn new(element: <C::Group as Group>::Element) -> Self {
#[cfg_attr(feature = "internals", visibility::make(pub))]
#[cfg_attr(docsrs, doc(cfg(feature = "internals")))]
pub(crate) fn new(element: <C::Group as Group>::Element) -> Self {
Self { element }
}
@ -77,6 +78,20 @@ where
pub fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<(), Error<C>> {
C::verify_signature(msg, signature, self)
}
/// Computes the group public key given the group commitment.
#[cfg_attr(feature = "internals", visibility::make(pub))]
pub(crate) fn from_commitment(
commitment: &crate::frost::keys::VerifiableSecretSharingCommitment<C>,
) -> Result<VerifyingKey<C>, Error<C>> {
Ok(VerifyingKey {
element: commitment
.coefficients()
.first()
.ok_or(Error::IncorrectCommitment)?
.value(),
})
}
}
impl<C> Debug for VerifyingKey<C>

View File

@ -30,3 +30,9 @@ fn check_deserialize_vss_commitment_error() {
rng, &ELEMENTS,
);
}
#[test]
fn check_compute_public_key_package() {
let rng = thread_rng();
frost_core::tests::vss_commitment::check_compute_public_key_package::<Ed25519Sha512, _>(rng);
}

View File

@ -30,3 +30,9 @@ fn check_deserialize_vss_commitment_error() {
rng, &ELEMENTS,
);
}
#[test]
fn check_compute_public_key_package() {
let rng = thread_rng();
frost_core::tests::vss_commitment::check_compute_public_key_package::<Ed448Shake256, _>(rng);
}

View File

@ -30,3 +30,9 @@ fn check_deserialize_vss_commitment_error() {
rng, &ELEMENTS,
);
}
#[test]
fn check_compute_public_key_package() {
let rng = thread_rng();
frost_core::tests::vss_commitment::check_compute_public_key_package::<P256Sha256, _>(rng);
}

View File

@ -33,3 +33,11 @@ fn check_deserialize_vss_commitment_error() {
_,
>(rng, &ELEMENTS);
}
#[test]
fn check_compute_public_key_package() {
let rng = thread_rng();
frost_core::tests::vss_commitment::check_compute_public_key_package::<Ristretto255Sha512, _>(
rng,
);
}

View File

@ -30,3 +30,9 @@ fn check_deserialize_vss_commitment_error() {
rng, &ELEMENTS,
);
}
#[test]
fn check_compute_public_key_package() {
let rng = thread_rng();
frost_core::tests::vss_commitment::check_compute_public_key_package::<Secp256K1Sha256, _>(rng);
}