From a0df08e30abc01fb25ab427c48a52ff7fb5b3467 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 31 Oct 2023 13:30:05 -0300 Subject: [PATCH] remove frost module (#568) --- frost-core/CHANGELOG.md | 5 +- frost-core/README.md | 14 +- frost-core/src/benches.rs | 3 +- frost-core/src/error.rs | 2 +- frost-core/src/frost.rs | 513 ------------------ frost-core/src/{frost => }/identifier.rs | 0 frost-core/src/{frost => }/keys.rs | 4 +- frost-core/src/{frost => }/keys/dkg.rs | 4 +- frost-core/src/{frost => }/keys/repairable.rs | 4 +- frost-core/src/lib.rs | 499 ++++++++++++++++- frost-core/src/{frost => }/round1.rs | 5 +- frost-core/src/{frost => }/round2.rs | 5 +- frost-core/src/tests/ciphersuite_generic.rs | 4 +- .../src/tests/coefficient_commitment.rs | 7 +- frost-core/src/tests/repairable.rs | 14 +- frost-core/src/tests/vectors.rs | 4 +- frost-core/src/tests/vss_commitment.rs | 4 +- frost-core/src/verifying_key.rs | 2 +- frost-ed25519/src/lib.rs | 2 +- frost-ed448/src/lib.rs | 2 +- frost-p256/src/lib.rs | 2 +- frost-rerandomized/src/lib.rs | 9 +- frost-rerandomized/src/tests.rs | 4 +- frost-ristretto255/src/lib.rs | 2 +- frost-secp256k1/src/lib.rs | 2 +- gencode/src/main.rs | 2 +- 26 files changed, 550 insertions(+), 568 deletions(-) rename frost-core/src/{frost => }/identifier.rs (100%) rename frost-core/src/{frost => }/keys.rs (99%) rename frost-core/src/{frost => }/keys/dkg.rs (99%) rename frost-core/src/{frost => }/keys/repairable.rs (96%) rename frost-core/src/{frost => }/round1.rs (99%) rename frost-core/src/{frost => }/round2.rs (98%) diff --git a/frost-core/CHANGELOG.md b/frost-core/CHANGELOG.md index c3768b6..5ab954a 100644 --- a/frost-core/CHANGELOG.md +++ b/frost-core/CHANGELOG.md @@ -4,8 +4,11 @@ Entries are listed in reverse chronological order. ## Unreleased -## 0.8.0 +## 1.0.0-rc.0 +* The `frost-core::frost` module contents were merged into `frost-core`, thus + eliminating the `frost` module. You can adapt any calling code with e.g. + changing `use frost_core::frost::*` to `use frost-core::*`. * Both serde serialization and the default byte-oriented serialization now include a version field (a u8) at the beginning which is always 0 for now. The ciphersuite ID field was moved from the last field to the second field, after diff --git a/frost-core/README.md b/frost-core/README.md index a298498..aac4cf2 100644 --- a/frost-core/README.md +++ b/frost-core/README.md @@ -2,12 +2,20 @@ Base traits and types in Rust that implement ['Two-Round Threshold Schnorr Signatures with FROST'](https://datatracker.ietf.org/doc/draft-irtf-cfrg-frost/) generically for -`frost-core::Ciphersuite` implementations. +[`Ciphersuite`] implementations. + +For key generation, refer to the [`keys`] module. For round-specific +types and functions, refer to the [`round1`] and [`round2`] modules. This module +contains types and functions not directly related to key generation and the +FROST rounds. + ## Status ⚠ -The FROST specification is not yet finalized, and this codebase has not yet been audited or -released. The APIs and types in `frost-core` are subject to change. +The FROST specification is not yet finalized, though no significant changes are +expected at this point. This code base has been audited by NCC. The APIs and +types in `frost-core` are subject to change during the release candidate phase, +and will follow SemVer guarantees after 1.0.0. ## Usage diff --git a/frost-core/src/benches.rs b/frost-core/src/benches.rs index fc1496b..74931bc 100644 --- a/frost-core/src/benches.rs +++ b/frost-core/src/benches.rs @@ -6,7 +6,8 @@ use std::collections::BTreeMap; use criterion::{BenchmarkId, Criterion, Throughput}; use rand_core::{CryptoRng, RngCore}; -use crate::{batch, frost, Ciphersuite, Signature, SigningKey, VerifyingKey}; +use crate as frost; +use crate::{batch, Ciphersuite, Signature, SigningKey, VerifyingKey}; struct Item { vk: VerifyingKey, diff --git a/frost-core/src/error.rs b/frost-core/src/error.rs index 0490665..3a768ba 100644 --- a/frost-core/src/error.rs +++ b/frost-core/src/error.rs @@ -2,7 +2,7 @@ use thiserror::Error; -use crate::{frost::Identifier, Ciphersuite}; +use crate::{Ciphersuite, Identifier}; #[derive(Error, Debug, Clone, Copy, Eq, PartialEq)] pub struct ParticipantError(Identifier); diff --git a/frost-core/src/frost.rs b/frost-core/src/frost.rs index 6e788c9..8b13789 100644 --- a/frost-core/src/frost.rs +++ b/frost-core/src/frost.rs @@ -1,514 +1 @@ -//! An implementation of FROST (Flexible Round-Optimized Schnorr Threshold) -//! signatures. -//! -//! For key generation, refer to the [`keys`] module. -//! For round-specific types and functions, refer to the [`round1`] and -//! [`round2`] modules. -//! -//! This module contains types and functions not directly related to key -//! generation and the FROST rounds. -use std::{ - collections::{BTreeMap, BTreeSet}, - fmt::{self, Debug}, -}; - -use derive_getters::Getters; -#[cfg(any(test, feature = "test-impl"))] -use hex::FromHex; - -mod identifier; -pub mod keys; -pub mod round1; -pub mod round2; - -use crate::{ - scalar_mul::VartimeMultiscalarMul, Ciphersuite, Deserialize, Element, Error, Field, Group, - Header, Scalar, Serialize, Signature, VerifyingKey, -}; - -pub use self::identifier::Identifier; - -/// The binding factor, also known as _rho_ (ρ) -/// -/// Ensures each signature share is strongly bound to a signing set, specific set -/// of commitments, and a specific message. -/// -/// -#[derive(Clone, PartialEq, Eq)] -pub struct BindingFactor(Scalar); - -impl BindingFactor -where - C: Ciphersuite, -{ - /// Deserializes [`BindingFactor`] from bytes. - pub fn deserialize( - bytes: <::Field as Field>::Serialization, - ) -> Result> { - <::Field>::deserialize(&bytes) - .map(|scalar| Self(scalar)) - .map_err(|e| e.into()) - } - - /// Serializes [`BindingFactor`] to bytes. - pub fn serialize(&self) -> <::Field as Field>::Serialization { - <::Field>::serialize(&self.0) - } -} - -impl Debug for BindingFactor -where - C: Ciphersuite, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_tuple("BindingFactor") - .field(&hex::encode(self.serialize())) - .finish() - } -} - -/// A list of binding factors and their associated identifiers. -#[derive(Clone)] -pub struct BindingFactorList(BTreeMap, BindingFactor>); - -impl BindingFactorList -where - C: Ciphersuite, -{ - /// Create a new [`BindingFactorList`] from a map of identifiers to binding factors. - #[cfg(feature = "internals")] - pub fn new(binding_factors: BTreeMap, BindingFactor>) -> Self { - Self(binding_factors) - } - - /// Return iterator through all factors. - pub fn iter(&self) -> impl Iterator, &BindingFactor)> { - self.0.iter() - } - - /// Get the [`BindingFactor`] for the given identifier, or None if not found. - pub fn get(&self, key: &Identifier) -> Option<&BindingFactor> { - self.0.get(key) - } -} - -/// [`compute_binding_factors`] in the spec -/// -/// [`compute_binding_factors`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-4.4 -#[cfg_attr(feature = "internals", visibility::make(pub))] -#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] -pub(crate) fn compute_binding_factor_list( - signing_package: &SigningPackage, - verifying_key: &VerifyingKey, - additional_prefix: &[u8], -) -> BindingFactorList -where - C: Ciphersuite, -{ - let preimages = signing_package.binding_factor_preimages(verifying_key, additional_prefix); - - BindingFactorList( - preimages - .iter() - .map(|(identifier, preimage)| { - let binding_factor = C::H1(preimage); - (*identifier, BindingFactor(binding_factor)) - }) - .collect(), - ) -} - -#[cfg(any(test, feature = "test-impl"))] -impl FromHex for BindingFactor -where - C: Ciphersuite, -{ - type Error = &'static str; - - fn from_hex>(hex: T) -> Result { - let v: Vec = FromHex::from_hex(hex).map_err(|_| "invalid hex")?; - match v.try_into() { - Ok(bytes) => Self::deserialize(bytes).map_err(|_| "malformed scalar encoding"), - Err(_) => Err("malformed scalar encoding"), - } - } -} - -/// Generates a lagrange coefficient. -/// -/// The Lagrange polynomial for a set of points (x_j, y_j) for 0 <= j <= k -/// is ∑_{i=0}^k y_i.ℓ_i(x), where ℓ_i(x) is the Lagrange basis polynomial: -/// -/// ℓ_i(x) = ∏_{0≤j≤k; j≠i} (x - x_j) / (x_i - x_j). -/// -/// This computes ℓ_j(x) for the set of points `xs` and for the j corresponding -/// to the given xj. -/// -/// If `x` is None, it uses 0 for it (since Identifiers can't be 0) -#[cfg_attr(feature = "internals", visibility::make(pub))] -#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] -fn compute_lagrange_coefficient( - x_set: &BTreeSet>, - x: Option>, - x_i: Identifier, -) -> Result, Error> { - if x_set.is_empty() { - return Err(Error::IncorrectNumberOfIdentifiers); - } - let mut num = <::Field>::one(); - let mut den = <::Field>::one(); - - let mut x_i_found = false; - - for x_j in x_set.iter() { - if x_i == *x_j { - x_i_found = true; - continue; - } - - if let Some(x) = x { - num *= x - *x_j; - den *= x_i - *x_j; - } else { - // Both signs inverted just to avoid requiring Neg (-*xj) - num *= *x_j; - den *= *x_j - x_i; - } - } - if !x_i_found { - return Err(Error::UnknownIdentifier); - } - - Ok( - num * <::Field>::invert(&den) - .map_err(|_| Error::DuplicatedIdentifier)?, - ) -} - -/// Generates the lagrange coefficient for the i'th participant (for `signer_id`). -/// -/// Implements [`derive_interpolating_value()`] from the spec. -/// -/// [`derive_interpolating_value()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#name-polynomials -#[cfg_attr(feature = "internals", visibility::make(pub))] -#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] -fn derive_interpolating_value( - signer_id: &Identifier, - signing_package: &SigningPackage, -) -> Result, Error> { - compute_lagrange_coefficient( - &signing_package - .signing_commitments() - .keys() - .cloned() - .collect(), - None, - *signer_id, - ) -} - -/// Generated by the coordinator of the signing operation and distributed to -/// each signing party -#[derive(Clone, Debug, PartialEq, Eq, Getters)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))] -#[cfg_attr(feature = "serde", serde(deny_unknown_fields))] -pub struct SigningPackage { - /// Serialization header - #[getter(skip)] - pub(crate) header: Header, - /// The set of commitments participants published in the first round of the - /// protocol. - signing_commitments: BTreeMap, round1::SigningCommitments>, - /// Message which each participant will sign. - /// - /// Each signer should perform protocol-specific verification on the - /// message. - #[cfg_attr( - feature = "serde", - serde( - serialize_with = "serdect::slice::serialize_hex_lower_or_bin", - deserialize_with = "serdect::slice::deserialize_hex_or_bin_vec" - ) - )] - message: Vec, -} - -impl SigningPackage -where - C: Ciphersuite, -{ - /// Create a new `SigningPackage` - /// - /// The `signing_commitments` are sorted by participant `identifier`. - pub fn new( - signing_commitments: BTreeMap, round1::SigningCommitments>, - message: &[u8], - ) -> SigningPackage { - SigningPackage { - header: Header::default(), - signing_commitments, - message: message.to_vec(), - } - } - - /// Get a signing commitment by its participant identifier, or None if not found. - pub fn signing_commitment( - &self, - identifier: &Identifier, - ) -> Option> { - self.signing_commitments.get(identifier).copied() - } - - /// Compute the preimages to H1 to compute the per-signer binding factors - // We separate this out into its own method so it can be tested - #[cfg_attr(feature = "internals", visibility::make(pub))] - #[cfg_attr(docsrs, doc(cfg(feature = "internals")))] - pub fn binding_factor_preimages( - &self, - verifying_key: &VerifyingKey, - additional_prefix: &[u8], - ) -> Vec<(Identifier, Vec)> { - let mut binding_factor_input_prefix = vec![]; - - // The length of a serialized verifying key of the same cipersuite does - // not change between runs of the protocol, so we don't need to hash to - // get a fixed length. - binding_factor_input_prefix.extend_from_slice(verifying_key.serialize().as_ref()); - - // The message is hashed with H4 to force the variable-length message - // into a fixed-length byte string, same for hashing the variable-sized - // (between runs of the protocol) set of group commitments, but with H5. - binding_factor_input_prefix.extend_from_slice(C::H4(self.message.as_slice()).as_ref()); - binding_factor_input_prefix.extend_from_slice( - C::H5(&round1::encode_group_commitments(self.signing_commitments())[..]).as_ref(), - ); - binding_factor_input_prefix.extend_from_slice(additional_prefix); - - self.signing_commitments() - .keys() - .map(|identifier| { - let mut binding_factor_input = vec![]; - - binding_factor_input.extend_from_slice(&binding_factor_input_prefix); - binding_factor_input.extend_from_slice(identifier.serialize().as_ref()); - (*identifier, binding_factor_input) - }) - .collect() - } -} - -#[cfg(feature = "serialization")] -impl SigningPackage -where - C: Ciphersuite, -{ - /// Serialize the struct into a Vec. - pub fn serialize(&self) -> Result, Error> { - Serialize::serialize(&self) - } - - /// Deserialize the struct from a slice of bytes. - pub fn deserialize(bytes: &[u8]) -> Result> { - Deserialize::deserialize(bytes) - } -} - -/// The product of all signers' individual commitments, published as part of the -/// final signature. -#[derive(Clone, PartialEq, Eq)] -pub struct GroupCommitment(pub(super) Element); - -impl GroupCommitment -where - C: Ciphersuite, -{ - /// Return the underlying element. - #[cfg(feature = "internals")] - pub fn to_element(self) -> ::Element { - self.0 - } -} - -/// Generates the group commitment which is published as part of the joint -/// Schnorr signature. -/// -/// Implements [`compute_group_commitment`] from the spec. -/// -/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-4.5 -#[cfg_attr(feature = "internals", visibility::make(pub))] -#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] -fn compute_group_commitment( - signing_package: &SigningPackage, - binding_factor_list: &BindingFactorList, -) -> Result, Error> -where - C: Ciphersuite, -{ - let identity = ::identity(); - - let mut group_commitment = ::identity(); - - // Number of signing participants we are iterating over. - let n = signing_package.signing_commitments().len(); - - let mut binding_scalars = Vec::with_capacity(n); - - let mut binding_elements = Vec::with_capacity(n); - - for (commitment_identifier, commitment) in signing_package.signing_commitments() { - // The following check prevents a party from accidentally revealing their share. - // Note that the '&&' operator would be sufficient. - if identity == commitment.binding.0 || identity == commitment.hiding.0 { - return Err(Error::IdentityCommitment); - } - - let binding_factor = binding_factor_list - .get(commitment_identifier) - .ok_or(Error::UnknownIdentifier)?; - - // Collect the binding commitments and their binding factors for one big - // multiscalar multiplication at the end. - binding_elements.push(commitment.binding.0); - binding_scalars.push(binding_factor.0); - - group_commitment = group_commitment + commitment.hiding.0; - } - - let accumulated_binding_commitment: Element = - VartimeMultiscalarMul::::vartime_multiscalar_mul(binding_scalars, binding_elements); - - group_commitment = group_commitment + accumulated_binding_commitment; - - Ok(GroupCommitment(group_commitment)) -} - -//////////////////////////////////////////////////////////////////////////////// -// Aggregation -//////////////////////////////////////////////////////////////////////////////// - -/// Aggregates the signature shares to produce a final signature that -/// can be verified with the group public key. -/// -/// `signature_shares` maps the identifier of each participant to the -/// [`round2::SignatureShare`] they sent. These identifiers must come from whatever mapping -/// the coordinator has between communication channels and participants, i.e. -/// they must have assurance that the [`round2::SignatureShare`] came from -/// the participant with that identifier. -/// -/// This operation is performed by a coordinator that can communicate with all -/// the signing participants before publishing the final signature. The -/// coordinator can be one of the participants or a semi-trusted third party -/// (who is trusted to not perform denial of service attacks, but does not learn -/// any secret information). Note that because the coordinator is trusted to -/// report misbehaving parties in order to avoid publishing an invalid -/// signature, if the coordinator themselves is a signer and misbehaves, they -/// can avoid that step. However, at worst, this results in a denial of -/// service attack due to publishing an invalid signature. - -pub fn aggregate( - signing_package: &SigningPackage, - signature_shares: &BTreeMap, round2::SignatureShare>, - pubkeys: &keys::PublicKeyPackage, -) -> Result, Error> -where - C: Ciphersuite, -{ - // Check if signing_package.signing_commitments and signature_shares have - // the same set of identifiers, and if they are all in pubkeys.verifying_shares. - if signing_package.signing_commitments().len() != signature_shares.len() { - return Err(Error::UnknownIdentifier); - } - if !signing_package.signing_commitments().keys().all(|id| { - #[cfg(feature = "cheater-detection")] - return signature_shares.contains_key(id) && pubkeys.verifying_shares().contains_key(id); - #[cfg(not(feature = "cheater-detection"))] - return signature_shares.contains_key(id); - }) { - return Err(Error::UnknownIdentifier); - } - - // Encodes the signing commitment list produced in round one as part of generating [`BindingFactor`], the - // binding factor. - let binding_factor_list: BindingFactorList = - compute_binding_factor_list(signing_package, &pubkeys.verifying_key, &[]); - - // Compute the group commitment from signing commitments produced in round one. - let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?; - - // The aggregation of the signature shares by summing them up, resulting in - // a plain Schnorr signature. - // - // Implements [`aggregate`] from the spec. - // - // [`aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-5.3 - let mut z = <::Field>::zero(); - - for signature_share in signature_shares.values() { - z = z + signature_share.share; - } - - let signature = Signature { - R: group_commitment.0, - z, - }; - - // Verify the aggregate signature - let verification_result = pubkeys - .verifying_key - .verify(signing_package.message(), &signature); - - // Only if the verification of the aggregate signature failed; verify each share to find the cheater. - // This approach is more efficient since we don't need to verify all shares - // if the aggregate signature is valid (which should be the common case). - #[cfg(feature = "cheater-detection")] - if let Err(err) = verification_result { - // Compute the per-message challenge. - let challenge = crate::challenge::( - &group_commitment.0, - &pubkeys.verifying_key, - signing_package.message().as_slice(), - ); - - // Verify the signature shares. - for (signature_share_identifier, signature_share) in signature_shares { - // Look up the public key for this signer, where `signer_pubkey` = _G.ScalarBaseMult(s[i])_, - // and where s[i] is a secret share of the constant term of _f_, the secret polynomial. - let signer_pubkey = pubkeys - .verifying_shares - .get(signature_share_identifier) - .ok_or(Error::UnknownIdentifier)?; - - // Compute Lagrange coefficient. - let lambda_i = derive_interpolating_value(signature_share_identifier, signing_package)?; - - let binding_factor = binding_factor_list - .get(signature_share_identifier) - .ok_or(Error::UnknownIdentifier)?; - - // Compute the commitment share. - let R_share = signing_package - .signing_commitment(signature_share_identifier) - .ok_or(Error::UnknownIdentifier)? - .to_group_commitment_share(binding_factor); - - // Compute relation values to verify this signature share. - signature_share.verify( - *signature_share_identifier, - &R_share, - signer_pubkey, - lambda_i, - &challenge, - )?; - } - - // We should never reach here; but we return the verification error to be safe. - return Err(err); - } - - #[cfg(not(feature = "cheater-detection"))] - verification_result?; - - Ok(signature) -} diff --git a/frost-core/src/frost/identifier.rs b/frost-core/src/identifier.rs similarity index 100% rename from frost-core/src/frost/identifier.rs rename to frost-core/src/identifier.rs diff --git a/frost-core/src/frost/keys.rs b/frost-core/src/keys.rs similarity index 99% rename from frost-core/src/frost/keys.rs rename to frost-core/src/keys.rs index 60d6140..4425f92 100644 --- a/frost-core/src/frost/keys.rs +++ b/frost-core/src/keys.rs @@ -17,8 +17,8 @@ use rand_core::{CryptoRng, RngCore}; use zeroize::{DefaultIsZeroes, Zeroize}; use crate::{ - frost::Identifier, Ciphersuite, Deserialize, Element, Error, Field, Group, Header, Scalar, - Serialize, SigningKey, VerifyingKey, + Ciphersuite, Deserialize, Element, Error, Field, Group, Header, Identifier, Scalar, Serialize, + SigningKey, VerifyingKey, }; #[cfg(feature = "serde")] diff --git a/frost-core/src/frost/keys/dkg.rs b/frost-core/src/keys/dkg.rs similarity index 99% rename from frost-core/src/frost/keys/dkg.rs rename to frost-core/src/keys/dkg.rs index 24f2f13..8c4ea78 100644 --- a/frost-core/src/frost/keys/dkg.rs +++ b/frost-core/src/keys/dkg.rs @@ -35,8 +35,8 @@ use std::{collections::BTreeMap, iter}; use rand_core::{CryptoRng, RngCore}; use crate::{ - frost::Identifier, Challenge, Ciphersuite, Element, Error, Field, Group, Header, Scalar, - Signature, SigningKey, VerifyingKey, + Challenge, Ciphersuite, Element, Error, Field, Group, Header, Identifier, Scalar, Signature, + SigningKey, VerifyingKey, }; use super::{ diff --git a/frost-core/src/frost/keys/repairable.rs b/frost-core/src/keys/repairable.rs similarity index 96% rename from frost-core/src/frost/keys/repairable.rs rename to frost-core/src/keys/repairable.rs index fb07de9..169e0ab 100644 --- a/frost-core/src/frost/keys/repairable.rs +++ b/frost-core/src/keys/repairable.rs @@ -7,8 +7,8 @@ use std::collections::{BTreeMap, BTreeSet}; use crate::{ - frost::{compute_lagrange_coefficient, Identifier}, - Ciphersuite, CryptoRng, Error, Field, Group, Header, RngCore, Scalar, + compute_lagrange_coefficient, Ciphersuite, CryptoRng, Error, Field, Group, Header, Identifier, + RngCore, Scalar, }; use super::{generate_coefficients, SecretShare, SigningShare, VerifiableSecretSharingCommitment}; diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index 2c99e7b..0ceaa25 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -11,13 +11,18 @@ #![doc = document_features::document_features!()] use std::{ + collections::{BTreeMap, BTreeSet}, default::Default, - fmt::Debug, + fmt::{self, Debug}, marker::PhantomData, ops::{Add, Mul, Sub}, }; +use derive_getters::Getters; +#[cfg(any(test, feature = "test-impl"))] +use hex::FromHex; use rand_core::{CryptoRng, RngCore}; +use zeroize::Zeroize; // Re-export serde #[cfg(feature = "serde")] @@ -27,7 +32,10 @@ pub mod batch; #[cfg(any(test, feature = "test-impl"))] pub mod benches; mod error; -pub mod frost; +mod identifier; +pub mod keys; +pub mod round1; +pub mod round2; mod scalar_mul; mod signature; mod signing_key; @@ -35,11 +43,12 @@ mod signing_key; pub mod tests; mod verifying_key; +pub use self::identifier::Identifier; +use crate::scalar_mul::VartimeMultiscalarMul; pub use error::{Error, FieldError, GroupError}; pub use signature::Signature; pub use signing_key::SigningKey; pub use verifying_key::VerifyingKey; -use zeroize::Zeroize; /// A prime order finite field GF(q) over which all scalar values for our prime order group can be /// multiplied are defined. @@ -560,3 +569,487 @@ impl serde::Deserialize<'de>, C: Ciphersuite> Deserialize for T { postcard::from_bytes(bytes).map_err(|_| Error::DeserializationError) } } + +/// The binding factor, also known as _rho_ (ρ) +/// +/// Ensures each signature share is strongly bound to a signing set, specific set +/// of commitments, and a specific message. +/// +/// +#[derive(Clone, PartialEq, Eq)] +pub struct BindingFactor(Scalar); + +impl BindingFactor +where + C: Ciphersuite, +{ + /// Deserializes [`BindingFactor`] from bytes. + pub fn deserialize( + bytes: <::Field as Field>::Serialization, + ) -> Result> { + <::Field>::deserialize(&bytes) + .map(|scalar| Self(scalar)) + .map_err(|e| e.into()) + } + + /// Serializes [`BindingFactor`] to bytes. + pub fn serialize(&self) -> <::Field as Field>::Serialization { + <::Field>::serialize(&self.0) + } +} + +impl Debug for BindingFactor +where + C: Ciphersuite, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.debug_tuple("BindingFactor") + .field(&hex::encode(self.serialize())) + .finish() + } +} + +/// A list of binding factors and their associated identifiers. +#[derive(Clone)] +pub struct BindingFactorList(BTreeMap, BindingFactor>); + +impl BindingFactorList +where + C: Ciphersuite, +{ + /// Create a new [`BindingFactorList`] from a map of identifiers to binding factors. + #[cfg(feature = "internals")] + pub fn new(binding_factors: BTreeMap, BindingFactor>) -> Self { + Self(binding_factors) + } + + /// Return iterator through all factors. + pub fn iter(&self) -> impl Iterator, &BindingFactor)> { + self.0.iter() + } + + /// Get the [`BindingFactor`] for the given identifier, or None if not found. + pub fn get(&self, key: &Identifier) -> Option<&BindingFactor> { + self.0.get(key) + } +} + +/// [`compute_binding_factors`] in the spec +/// +/// [`compute_binding_factors`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-4.4 +#[cfg_attr(feature = "internals", visibility::make(pub))] +#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] +pub(crate) fn compute_binding_factor_list( + signing_package: &SigningPackage, + verifying_key: &VerifyingKey, + additional_prefix: &[u8], +) -> BindingFactorList +where + C: Ciphersuite, +{ + let preimages = signing_package.binding_factor_preimages(verifying_key, additional_prefix); + + BindingFactorList( + preimages + .iter() + .map(|(identifier, preimage)| { + let binding_factor = C::H1(preimage); + (*identifier, BindingFactor(binding_factor)) + }) + .collect(), + ) +} + +#[cfg(any(test, feature = "test-impl"))] +impl FromHex for BindingFactor +where + C: Ciphersuite, +{ + type Error = &'static str; + + fn from_hex>(hex: T) -> Result { + let v: Vec = FromHex::from_hex(hex).map_err(|_| "invalid hex")?; + match v.try_into() { + Ok(bytes) => Self::deserialize(bytes).map_err(|_| "malformed scalar encoding"), + Err(_) => Err("malformed scalar encoding"), + } + } +} + +/// Generates a lagrange coefficient. +/// +/// The Lagrange polynomial for a set of points (x_j, y_j) for 0 <= j <= k +/// is ∑_{i=0}^k y_i.ℓ_i(x), where ℓ_i(x) is the Lagrange basis polynomial: +/// +/// ℓ_i(x) = ∏_{0≤j≤k; j≠i} (x - x_j) / (x_i - x_j). +/// +/// This computes ℓ_j(x) for the set of points `xs` and for the j corresponding +/// to the given xj. +/// +/// If `x` is None, it uses 0 for it (since Identifiers can't be 0) +#[cfg_attr(feature = "internals", visibility::make(pub))] +#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] +fn compute_lagrange_coefficient( + x_set: &BTreeSet>, + x: Option>, + x_i: Identifier, +) -> Result, Error> { + if x_set.is_empty() { + return Err(Error::IncorrectNumberOfIdentifiers); + } + let mut num = <::Field>::one(); + let mut den = <::Field>::one(); + + let mut x_i_found = false; + + for x_j in x_set.iter() { + if x_i == *x_j { + x_i_found = true; + continue; + } + + if let Some(x) = x { + num *= x - *x_j; + den *= x_i - *x_j; + } else { + // Both signs inverted just to avoid requiring Neg (-*xj) + num *= *x_j; + den *= *x_j - x_i; + } + } + if !x_i_found { + return Err(Error::UnknownIdentifier); + } + + Ok( + num * <::Field>::invert(&den) + .map_err(|_| Error::DuplicatedIdentifier)?, + ) +} + +/// Generates the lagrange coefficient for the i'th participant (for `signer_id`). +/// +/// Implements [`derive_interpolating_value()`] from the spec. +/// +/// [`derive_interpolating_value()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#name-polynomials +#[cfg_attr(feature = "internals", visibility::make(pub))] +#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] +fn derive_interpolating_value( + signer_id: &Identifier, + signing_package: &SigningPackage, +) -> Result, Error> { + compute_lagrange_coefficient( + &signing_package + .signing_commitments() + .keys() + .cloned() + .collect(), + None, + *signer_id, + ) +} + +/// Generated by the coordinator of the signing operation and distributed to +/// each signing party +#[derive(Clone, Debug, PartialEq, Eq, Getters)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", serde(bound = "C: Ciphersuite"))] +#[cfg_attr(feature = "serde", serde(deny_unknown_fields))] +pub struct SigningPackage { + /// Serialization header + #[getter(skip)] + pub(crate) header: Header, + /// The set of commitments participants published in the first round of the + /// protocol. + signing_commitments: BTreeMap, round1::SigningCommitments>, + /// Message which each participant will sign. + /// + /// Each signer should perform protocol-specific verification on the + /// message. + #[cfg_attr( + feature = "serde", + serde( + serialize_with = "serdect::slice::serialize_hex_lower_or_bin", + deserialize_with = "serdect::slice::deserialize_hex_or_bin_vec" + ) + )] + message: Vec, +} + +impl SigningPackage +where + C: Ciphersuite, +{ + /// Create a new `SigningPackage` + /// + /// The `signing_commitments` are sorted by participant `identifier`. + pub fn new( + signing_commitments: BTreeMap, round1::SigningCommitments>, + message: &[u8], + ) -> SigningPackage { + SigningPackage { + header: Header::default(), + signing_commitments, + message: message.to_vec(), + } + } + + /// Get a signing commitment by its participant identifier, or None if not found. + pub fn signing_commitment( + &self, + identifier: &Identifier, + ) -> Option> { + self.signing_commitments.get(identifier).copied() + } + + /// Compute the preimages to H1 to compute the per-signer binding factors + // We separate this out into its own method so it can be tested + #[cfg_attr(feature = "internals", visibility::make(pub))] + #[cfg_attr(docsrs, doc(cfg(feature = "internals")))] + pub fn binding_factor_preimages( + &self, + verifying_key: &VerifyingKey, + additional_prefix: &[u8], + ) -> Vec<(Identifier, Vec)> { + let mut binding_factor_input_prefix = vec![]; + + // The length of a serialized verifying key of the same cipersuite does + // not change between runs of the protocol, so we don't need to hash to + // get a fixed length. + binding_factor_input_prefix.extend_from_slice(verifying_key.serialize().as_ref()); + + // The message is hashed with H4 to force the variable-length message + // into a fixed-length byte string, same for hashing the variable-sized + // (between runs of the protocol) set of group commitments, but with H5. + binding_factor_input_prefix.extend_from_slice(C::H4(self.message.as_slice()).as_ref()); + binding_factor_input_prefix.extend_from_slice( + C::H5(&round1::encode_group_commitments(self.signing_commitments())[..]).as_ref(), + ); + binding_factor_input_prefix.extend_from_slice(additional_prefix); + + self.signing_commitments() + .keys() + .map(|identifier| { + let mut binding_factor_input = vec![]; + + binding_factor_input.extend_from_slice(&binding_factor_input_prefix); + binding_factor_input.extend_from_slice(identifier.serialize().as_ref()); + (*identifier, binding_factor_input) + }) + .collect() + } +} + +#[cfg(feature = "serialization")] +impl SigningPackage +where + C: Ciphersuite, +{ + /// Serialize the struct into a Vec. + pub fn serialize(&self) -> Result, Error> { + Serialize::serialize(&self) + } + + /// Deserialize the struct from a slice of bytes. + pub fn deserialize(bytes: &[u8]) -> Result> { + Deserialize::deserialize(bytes) + } +} + +/// The product of all signers' individual commitments, published as part of the +/// final signature. +#[derive(Clone, PartialEq, Eq)] +pub struct GroupCommitment(pub(crate) Element); + +impl GroupCommitment +where + C: Ciphersuite, +{ + /// Return the underlying element. + #[cfg(feature = "internals")] + pub fn to_element(self) -> ::Element { + self.0 + } +} + +/// Generates the group commitment which is published as part of the joint +/// Schnorr signature. +/// +/// Implements [`compute_group_commitment`] from the spec. +/// +/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-4.5 +#[cfg_attr(feature = "internals", visibility::make(pub))] +#[cfg_attr(docsrs, doc(cfg(feature = "internals")))] +fn compute_group_commitment( + signing_package: &SigningPackage, + binding_factor_list: &BindingFactorList, +) -> Result, Error> +where + C: Ciphersuite, +{ + let identity = ::identity(); + + let mut group_commitment = ::identity(); + + // Number of signing participants we are iterating over. + let n = signing_package.signing_commitments().len(); + + let mut binding_scalars = Vec::with_capacity(n); + + let mut binding_elements = Vec::with_capacity(n); + + for (commitment_identifier, commitment) in signing_package.signing_commitments() { + // The following check prevents a party from accidentally revealing their share. + // Note that the '&&' operator would be sufficient. + if identity == commitment.binding.0 || identity == commitment.hiding.0 { + return Err(Error::IdentityCommitment); + } + + let binding_factor = binding_factor_list + .get(commitment_identifier) + .ok_or(Error::UnknownIdentifier)?; + + // Collect the binding commitments and their binding factors for one big + // multiscalar multiplication at the end. + binding_elements.push(commitment.binding.0); + binding_scalars.push(binding_factor.0); + + group_commitment = group_commitment + commitment.hiding.0; + } + + let accumulated_binding_commitment: Element = + VartimeMultiscalarMul::::vartime_multiscalar_mul(binding_scalars, binding_elements); + + group_commitment = group_commitment + accumulated_binding_commitment; + + Ok(GroupCommitment(group_commitment)) +} + +//////////////////////////////////////////////////////////////////////////////// +// Aggregation +//////////////////////////////////////////////////////////////////////////////// + +/// Aggregates the signature shares to produce a final signature that +/// can be verified with the group public key. +/// +/// `signature_shares` maps the identifier of each participant to the +/// [`round2::SignatureShare`] they sent. These identifiers must come from whatever mapping +/// the coordinator has between communication channels and participants, i.e. +/// they must have assurance that the [`round2::SignatureShare`] came from +/// the participant with that identifier. +/// +/// This operation is performed by a coordinator that can communicate with all +/// the signing participants before publishing the final signature. The +/// coordinator can be one of the participants or a semi-trusted third party +/// (who is trusted to not perform denial of service attacks, but does not learn +/// any secret information). Note that because the coordinator is trusted to +/// report misbehaving parties in order to avoid publishing an invalid +/// signature, if the coordinator themselves is a signer and misbehaves, they +/// can avoid that step. However, at worst, this results in a denial of +/// service attack due to publishing an invalid signature. + +pub fn aggregate( + signing_package: &SigningPackage, + signature_shares: &BTreeMap, round2::SignatureShare>, + pubkeys: &keys::PublicKeyPackage, +) -> Result, Error> +where + C: Ciphersuite, +{ + // Check if signing_package.signing_commitments and signature_shares have + // the same set of identifiers, and if they are all in pubkeys.verifying_shares. + if signing_package.signing_commitments().len() != signature_shares.len() { + return Err(Error::UnknownIdentifier); + } + if !signing_package.signing_commitments().keys().all(|id| { + #[cfg(feature = "cheater-detection")] + return signature_shares.contains_key(id) && pubkeys.verifying_shares().contains_key(id); + #[cfg(not(feature = "cheater-detection"))] + return signature_shares.contains_key(id); + }) { + return Err(Error::UnknownIdentifier); + } + + // Encodes the signing commitment list produced in round one as part of generating [`BindingFactor`], the + // binding factor. + let binding_factor_list: BindingFactorList = + compute_binding_factor_list(signing_package, &pubkeys.verifying_key, &[]); + + // Compute the group commitment from signing commitments produced in round one. + let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?; + + // The aggregation of the signature shares by summing them up, resulting in + // a plain Schnorr signature. + // + // Implements [`aggregate`] from the spec. + // + // [`aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-14.html#section-5.3 + let mut z = <::Field>::zero(); + + for signature_share in signature_shares.values() { + z = z + signature_share.share; + } + + let signature = Signature { + R: group_commitment.0, + z, + }; + + // Verify the aggregate signature + let verification_result = pubkeys + .verifying_key + .verify(signing_package.message(), &signature); + + // Only if the verification of the aggregate signature failed; verify each share to find the cheater. + // This approach is more efficient since we don't need to verify all shares + // if the aggregate signature is valid (which should be the common case). + #[cfg(feature = "cheater-detection")] + if let Err(err) = verification_result { + // Compute the per-message challenge. + let challenge = crate::challenge::( + &group_commitment.0, + &pubkeys.verifying_key, + signing_package.message().as_slice(), + ); + + // Verify the signature shares. + for (signature_share_identifier, signature_share) in signature_shares { + // Look up the public key for this signer, where `signer_pubkey` = _G.ScalarBaseMult(s[i])_, + // and where s[i] is a secret share of the constant term of _f_, the secret polynomial. + let signer_pubkey = pubkeys + .verifying_shares + .get(signature_share_identifier) + .ok_or(Error::UnknownIdentifier)?; + + // Compute Lagrange coefficient. + let lambda_i = derive_interpolating_value(signature_share_identifier, signing_package)?; + + let binding_factor = binding_factor_list + .get(signature_share_identifier) + .ok_or(Error::UnknownIdentifier)?; + + // Compute the commitment share. + let R_share = signing_package + .signing_commitment(signature_share_identifier) + .ok_or(Error::UnknownIdentifier)? + .to_group_commitment_share(binding_factor); + + // Compute relation values to verify this signature share. + signature_share.verify( + *signature_share_identifier, + &R_share, + signer_pubkey, + lambda_i, + &challenge, + )?; + } + + // We should never reach here; but we return the verification error to be safe. + return Err(err); + } + + #[cfg(not(feature = "cheater-detection"))] + verification_result?; + + Ok(signature) +} diff --git a/frost-core/src/frost/round1.rs b/frost-core/src/round1.rs similarity index 99% rename from frost-core/src/frost/round1.rs rename to frost-core/src/round1.rs index 1aba6a0..a4febb0 100644 --- a/frost-core/src/frost/round1.rs +++ b/frost-core/src/round1.rs @@ -12,9 +12,8 @@ use hex::FromHex; use rand_core::{CryptoRng, RngCore}; use zeroize::Zeroize; -use crate::{ - frost, Ciphersuite, Deserialize, Element, Error, Field, Group, Header, Scalar, Serialize, -}; +use crate as frost; +use crate::{Ciphersuite, Deserialize, Element, Error, Field, Group, Header, Scalar, Serialize}; #[cfg(feature = "serde")] use crate::ElementSerialization; diff --git a/frost-core/src/frost/round2.rs b/frost-core/src/round2.rs similarity index 98% rename from frost-core/src/frost/round2.rs rename to frost-core/src/round2.rs index 146831b..0449ac9 100644 --- a/frost-core/src/frost/round2.rs +++ b/frost-core/src/round2.rs @@ -2,10 +2,9 @@ use std::fmt::{self, Debug}; +use crate as frost; use crate::{ - challenge, - frost::{self, round1, *}, - Challenge, Ciphersuite, Error, Field, Group, + challenge, Challenge, Ciphersuite, Error, Field, Group, {round1, *}, }; #[cfg(feature = "serde")] diff --git a/frost-core/src/tests/ciphersuite_generic.rs b/frost-core/src/tests/ciphersuite_generic.rs index eb64448..b33ed6b 100644 --- a/frost-core/src/tests/ciphersuite_generic.rs +++ b/frost-core/src/tests/ciphersuite_generic.rs @@ -3,9 +3,9 @@ use std::{collections::BTreeMap, convert::TryFrom}; +use crate as frost; use crate::{ - frost::{self, keys::PublicKeyPackage, Identifier}, - Error, Field, Group, Signature, SigningKey, VerifyingKey, + keys::PublicKeyPackage, Error, Field, Group, Identifier, Signature, SigningKey, VerifyingKey, }; use rand_core::{CryptoRng, RngCore}; diff --git a/frost-core/src/tests/coefficient_commitment.rs b/frost-core/src/tests/coefficient_commitment.rs index 03de69f..36c241c 100644 --- a/frost-core/src/tests/coefficient_commitment.rs +++ b/frost-core/src/tests/coefficient_commitment.rs @@ -2,11 +2,8 @@ use std::convert::TryFrom; -use crate::{ - frost::{self, keys::CoefficientCommitment}, - tests::helpers::generate_element, - Group, -}; +use crate as frost; +use crate::{keys::CoefficientCommitment, tests::helpers::generate_element, Group}; use debugless_unwrap::DebuglessUnwrap; use rand_core::{CryptoRng, RngCore}; use serde_json::Value; diff --git a/frost-core/src/tests/repairable.rs b/frost-core/src/tests/repairable.rs index a53bb6d..8c187a8 100644 --- a/frost-core/src/tests/repairable.rs +++ b/frost-core/src/tests/repairable.rs @@ -6,16 +6,14 @@ use debugless_unwrap::DebuglessUnwrap; use rand_core::{CryptoRng, RngCore}; use serde_json::Value; +use crate as frost; use crate::{ - frost::{ - self, compute_lagrange_coefficient, - keys::{ - repairable::{repair_share_step_1, repair_share_step_2, repair_share_step_3}, - PublicKeyPackage, SecretShare, SigningShare, - }, - Identifier, + compute_lagrange_coefficient, + keys::{ + repairable::{repair_share_step_1, repair_share_step_2, repair_share_step_3}, + PublicKeyPackage, SecretShare, SigningShare, }, - Ciphersuite, Error, Field, Group, Scalar, + Ciphersuite, Error, Field, Group, Identifier, Scalar, }; /// We want to test that recover share matches the original share diff --git a/frost-core/src/tests/vectors.rs b/frost-core/src/tests/vectors.rs index 5c1787a..699e04b 100644 --- a/frost-core/src/tests/vectors.rs +++ b/frost-core/src/tests/vectors.rs @@ -5,9 +5,9 @@ use debugless_unwrap::DebuglessUnwrap; use hex::{self, FromHex}; use serde_json::Value; +use crate as frost; use crate::{ - frost::{self, keys::*, round1::*, round2::*, *}, - Ciphersuite, Field, Group, Scalar, SigningKey, VerifyingKey, + keys::*, round1::*, round2::*, Ciphersuite, Field, Group, Scalar, SigningKey, VerifyingKey, *, }; /// Test vectors for a ciphersuite. diff --git a/frost-core/src/tests/vss_commitment.rs b/frost-core/src/tests/vss_commitment.rs index 3228417..562affc 100644 --- a/frost-core/src/tests/vss_commitment.rs +++ b/frost-core/src/tests/vss_commitment.rs @@ -3,7 +3,7 @@ use std::convert::TryFrom; use crate::{ - frost::keys::{CoefficientCommitment, VerifiableSecretSharingCommitment}, + keys::{CoefficientCommitment, VerifiableSecretSharingCommitment}, tests::helpers::generate_element, Group, }; @@ -11,7 +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::keys::{generate_with_dealer, IdentifierList, PublicKeyPackage}; use crate::Ciphersuite; /// Test serialize VerifiableSecretSharingCommitment diff --git a/frost-core/src/verifying_key.rs b/frost-core/src/verifying_key.rs index 30c8209..572aa35 100644 --- a/frost-core/src/verifying_key.rs +++ b/frost-core/src/verifying_key.rs @@ -82,7 +82,7 @@ where /// 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, + commitment: &crate::keys::VerifiableSecretSharingCommitment, ) -> Result, Error> { Ok(VerifyingKey { element: commitment diff --git a/frost-ed25519/src/lib.rs b/frost-ed25519/src/lib.rs index b152a8c..ca448a8 100644 --- a/frost-ed25519/src/lib.rs +++ b/frost-ed25519/src/lib.rs @@ -17,7 +17,7 @@ use frost_rerandomized::RandomizedCiphersuite; use rand_core::{CryptoRng, RngCore}; use sha2::{Digest, Sha512}; -use frost_core::frost; +use frost_core as frost; #[cfg(test)] mod tests; diff --git a/frost-ed448/src/lib.rs b/frost-ed448/src/lib.rs index edd53e3..63b7a40 100644 --- a/frost-ed448/src/lib.rs +++ b/frost-ed448/src/lib.rs @@ -18,7 +18,7 @@ use sha3::{ Shake256, }; -use frost_core::frost; +use frost_core as frost; #[cfg(test)] mod tests; diff --git a/frost-p256/src/lib.rs b/frost-p256/src/lib.rs index 7fa2fd8..f95a7ed 100644 --- a/frost-p256/src/lib.rs +++ b/frost-p256/src/lib.rs @@ -19,7 +19,7 @@ use p256::{ use rand_core::{CryptoRng, RngCore}; use sha2::{Digest, Sha256}; -use frost_core::frost; +use frost_core as frost; #[cfg(test)] mod tests; diff --git a/frost-rerandomized/src/lib.rs b/frost-rerandomized/src/lib.rs index 38dca60..6d41db1 100644 --- a/frost-rerandomized/src/lib.rs +++ b/frost-rerandomized/src/lib.rs @@ -20,12 +20,9 @@ use derive_getters::Getters; pub use frost_core; use frost_core::{ - frost::{ - self, - keys::{KeyPackage, PublicKeyPackage, SigningShare, VerifyingShare}, - SigningPackage, - }, - Ciphersuite, Error, Field, Group, Scalar, VerifyingKey, + self as frost, + keys::{KeyPackage, PublicKeyPackage, SigningShare, VerifyingShare}, + Ciphersuite, Error, Field, Group, Scalar, SigningPackage, VerifyingKey, }; #[cfg(feature = "serde")] diff --git a/frost-rerandomized/src/tests.rs b/frost-rerandomized/src/tests.rs index 6966d32..15fde19 100644 --- a/frost-rerandomized/src/tests.rs +++ b/frost-rerandomized/src/tests.rs @@ -2,8 +2,8 @@ use std::collections::BTreeMap; -use crate::{frost_core::frost, RandomizedCiphersuite, RandomizedParams, Randomizer}; -use frost_core::{frost::SigningPackage, Field, Group, Signature, VerifyingKey}; +use crate::{frost_core as frost, RandomizedCiphersuite, RandomizedParams, Randomizer}; +use frost_core::{Field, Group, Signature, SigningPackage, VerifyingKey}; use rand_core::{CryptoRng, RngCore}; /// Test re-randomized FROST signing with trusted dealer with a Ciphersuite. diff --git a/frost-ristretto255/src/lib.rs b/frost-ristretto255/src/lib.rs index 548eb66..e007a2f 100644 --- a/frost-ristretto255/src/lib.rs +++ b/frost-ristretto255/src/lib.rs @@ -14,7 +14,7 @@ use frost_rerandomized::RandomizedCiphersuite; use rand_core::{CryptoRng, RngCore}; use sha2::{Digest, Sha512}; -use frost_core::frost; +use frost_core as frost; #[cfg(test)] mod tests; diff --git a/frost-secp256k1/src/lib.rs b/frost-secp256k1/src/lib.rs index a150b4c..1e7d1fb 100644 --- a/frost-secp256k1/src/lib.rs +++ b/frost-secp256k1/src/lib.rs @@ -20,7 +20,7 @@ use k256::{ use rand_core::{CryptoRng, RngCore}; use sha2::{Digest, Sha256}; -use frost_core::frost; +use frost_core as frost; #[cfg(test)] mod tests; diff --git a/gencode/src/main.rs b/gencode/src/main.rs index f4c74d7..0806901 100644 --- a/gencode/src/main.rs +++ b/gencode/src/main.rs @@ -194,7 +194,7 @@ fn main() -> ExitCode { // Copy the frost-core repairable docs into ristretto255. // This will then be copied later down into the other ciphersuites. - let repairable_docs = read_docs("frost-core/src/frost/keys/repairable.rs", &[]); + let repairable_docs = read_docs("frost-core/src/keys/repairable.rs", &[]); replaced |= write_docs( &repairable_docs, "frost-ristretto255/src/keys/repairable.rs",