Hash serialized scalars entirely; update test vectors to V10 (#139)
* v9 * update to v10 vectors * update spec links * Make Rustdoc happy * Make Rustdoc happy * refactor coefficient generation into a function * rustdoc Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com>
This commit is contained in:
parent
45d16cb801
commit
828279d847
|
@ -89,7 +89,7 @@ where
|
|||
//
|
||||
// [`binding_factor_for_participant`] in the spec
|
||||
//
|
||||
// [`binding_factor_for_participant`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-07.html#section-4.3
|
||||
// [`binding_factor_for_participant`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-4.3
|
||||
// TODO: switch from Vec to BTreeMap, as this can be made more efficient.
|
||||
fn index(&self, identifier: Identifier<C>) -> &Self::Output {
|
||||
for (i, factor) in self.0.iter() {
|
||||
|
@ -108,7 +108,7 @@ where
|
|||
{
|
||||
// [`compute_binding_factors`] in the spec
|
||||
//
|
||||
// [`compute_binding_factors`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-07.html#section-4.4
|
||||
// [`compute_binding_factors`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-4.4
|
||||
fn from(signing_package: &SigningPackage<C>) -> BindingFactorList<C> {
|
||||
let preimages = signing_package.rho_preimages();
|
||||
|
||||
|
@ -244,7 +244,13 @@ where
|
|||
let mut rho_input = vec![];
|
||||
|
||||
rho_input.extend_from_slice(&rho_input_prefix);
|
||||
rho_input.extend_from_slice(&u16::from(c.identifier).to_be_bytes());
|
||||
rho_input.extend_from_slice(
|
||||
<<C::Group as Group>::Field as Field>::serialize(
|
||||
// unwrap() is OK because this will become infallible after refactoring (#102)
|
||||
&c.identifier.to_scalar().unwrap(),
|
||||
)
|
||||
.as_ref(),
|
||||
);
|
||||
(c.identifier, rho_input)
|
||||
})
|
||||
.collect()
|
||||
|
@ -275,7 +281,7 @@ where
|
|||
///
|
||||
/// Implements [`compute_group_commitment`] from the spec.
|
||||
///
|
||||
/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#section-4.4
|
||||
/// [`compute_group_commitment`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-4.5
|
||||
fn try_from(signing_package: &SigningPackage<C>) -> Result<GroupCommitment<C>, &'static str> {
|
||||
let binding_factor_list: BindingFactorList<C> = signing_package.into();
|
||||
|
||||
|
@ -370,9 +376,9 @@ where
|
|||
// The aggregation of the signature shares by summing them up, resulting in
|
||||
// a plain Schnorr signature.
|
||||
//
|
||||
// Implements [`frost_aggregate`] from the spec.
|
||||
// Implements [`aggregate`] from the spec.
|
||||
//
|
||||
// [`frost_aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#section-5.3-4
|
||||
// [`aggregate`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-5.3
|
||||
let mut z = <<C::Group as Group>::Field as Field>::zero();
|
||||
|
||||
for signature_share in signature_shares {
|
||||
|
|
|
@ -5,6 +5,7 @@ use std::{
|
|||
convert::TryFrom,
|
||||
default::Default,
|
||||
fmt::{self, Debug},
|
||||
iter,
|
||||
};
|
||||
|
||||
use hex::FromHex;
|
||||
|
@ -13,6 +14,16 @@ use zeroize::{DefaultIsZeroes, Zeroize};
|
|||
|
||||
use crate::{frost::Identifier, Ciphersuite, Error, Field, Group, Scalar, VerifyingKey};
|
||||
|
||||
/// Return a vector of randomly generated polynomial coefficients ([`Scalar`]s).
|
||||
pub(crate) fn generate_coefficients<C: Ciphersuite, R: RngCore + CryptoRng>(
|
||||
size: usize,
|
||||
mut rng: R,
|
||||
) -> Vec<<<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar> {
|
||||
iter::repeat_with(|| <<C::Group as Group>::Field as Field>::random(&mut rng))
|
||||
.take(size)
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// A group secret to be split between participants.
|
||||
///
|
||||
/// This is similar to a [`crate::SigningKey`], but this secret is not intended to be used
|
||||
|
@ -261,7 +272,7 @@ where
|
|||
/// This also implements `derive_group_info()` from the [spec] (which is very similar),
|
||||
/// but only for this participant.
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#appendix-B.2-5
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#appendix-C.2-4
|
||||
pub fn verify(&self) -> Result<(VerifyingShare<C>, VerifyingKey<C>), &'static str> {
|
||||
let f_result = <C::Group as Group>::generator() * self.value.0;
|
||||
|
||||
|
@ -311,7 +322,7 @@ pub struct SharePackage<C: Ciphersuite> {
|
|||
///
|
||||
/// Implements [`trusted_dealer_keygen`] from the spec.
|
||||
///
|
||||
/// [`trusted_dealer_keygen`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#appendix-B
|
||||
/// [`trusted_dealer_keygen`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#appendix-C
|
||||
pub fn keygen_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
|
||||
num_signers: u8,
|
||||
threshold: u8,
|
||||
|
@ -322,7 +333,10 @@ pub fn keygen_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
|
|||
|
||||
let secret = SharedSecret::random(&mut rng);
|
||||
let group_public = VerifyingKey::from(&secret);
|
||||
let secret_shares = generate_secret_shares(&secret, num_signers, threshold, rng)?;
|
||||
|
||||
let coefficients = generate_coefficients::<C, R>(threshold as usize - 1, rng);
|
||||
|
||||
let secret_shares = generate_secret_shares(&secret, num_signers, threshold, coefficients)?;
|
||||
let mut share_packages: Vec<SharePackage<C>> = Vec::with_capacity(num_signers as usize);
|
||||
let mut signer_pubkeys: HashMap<Identifier<C>, VerifyingShare<C>> =
|
||||
HashMap::with_capacity(num_signers as usize);
|
||||
|
@ -430,10 +444,11 @@ pub struct PublicKeyPackage<C: Ciphersuite> {
|
|||
pub group_public: VerifyingKey<C>,
|
||||
}
|
||||
|
||||
/// Creates secret shares for a given secret.
|
||||
/// Creates secret shares for a given secret using the given coefficients.
|
||||
///
|
||||
/// This function accepts a secret from which shares are generated. While in
|
||||
/// FROST this secret should always be generated randomly, we allow this secret
|
||||
/// This function accepts a secret from which shares are generated,
|
||||
/// and a list of threshold-1 coefficients. While in FROST this secret
|
||||
/// and coefficients should always be generated randomly, we allow them
|
||||
/// to be specified for this internal function for testability.
|
||||
///
|
||||
/// Internally, [`generate_secret_shares`] performs verifiable secret sharing, which
|
||||
|
@ -441,19 +456,18 @@ pub struct PublicKeyPackage<C: Ciphersuite> {
|
|||
/// commitments to those shares.
|
||||
///
|
||||
/// More specifically, [`generate_secret_shares`]:
|
||||
/// - Randomly samples of coefficients [a, b, c], this represents a secret
|
||||
/// polynomial f
|
||||
/// - Interpret [secret, `coefficients[0]`, ...] as a secret polynomial f
|
||||
/// - For each participant i, their secret share is f(i)
|
||||
/// - The commitment to the secret polynomial f is [g^a, g^b, g^c]
|
||||
/// - The commitment to the secret polynomial f is [g^secret, `g^coefficients[0]`, ...]
|
||||
///
|
||||
/// Implements [`secret_key_shard`] from the spec.
|
||||
/// Implements [`secret_share_shard`] from the spec.
|
||||
///
|
||||
/// [`secret_key_shard`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#appendix-B.1
|
||||
pub fn generate_secret_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
|
||||
/// [`secret_share_shard`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#appendix-C.1
|
||||
pub(crate) fn generate_secret_shares<C: Ciphersuite>(
|
||||
secret: &SharedSecret<C>,
|
||||
numshares: u8,
|
||||
threshold: u8,
|
||||
mut rng: R,
|
||||
coefficients: Vec<Scalar<C>>,
|
||||
) -> Result<Vec<SecretShare<C>>, &'static str> {
|
||||
if threshold < 2 {
|
||||
return Err("Threshold cannot be less than 2");
|
||||
|
@ -469,17 +483,15 @@ pub fn generate_secret_shares<C: Ciphersuite, R: RngCore + CryptoRng>(
|
|||
|
||||
let numcoeffs = threshold - 1;
|
||||
|
||||
let mut coefficients: Vec<Scalar<C>> = Vec::with_capacity(threshold as usize);
|
||||
if coefficients.len() != numcoeffs as usize {
|
||||
return Err("Must pass threshold-1 coefficients");
|
||||
}
|
||||
|
||||
let mut secret_shares: Vec<SecretShare<C>> = Vec::with_capacity(numshares as usize);
|
||||
|
||||
let mut commitment: VerifiableSecretSharingCommitment<C> =
|
||||
VerifiableSecretSharingCommitment(Vec::with_capacity(threshold as usize));
|
||||
|
||||
for _ in 0..numcoeffs {
|
||||
coefficients.push(<<C::Group as Group>::Field as Field>::random(&mut rng));
|
||||
}
|
||||
|
||||
// Verifiable secret sharing, to make sure that participants can ensure their
|
||||
// secret is consistent with every other participant's.
|
||||
commitment.0.push(CoefficientCommitment(
|
||||
|
|
|
@ -26,7 +26,7 @@ where
|
|||
///
|
||||
/// An implementation of `nonce_generate(secret)` from the [spec].
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#name-nonce-generation
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-nonce-generation
|
||||
pub fn new<R>(secret: &SigningShare<C>, rng: &mut R) -> Self
|
||||
where
|
||||
R: CryptoRng + RngCore,
|
||||
|
@ -209,7 +209,7 @@ where
|
|||
{
|
||||
/// Computes the [signature commitment share] from these round one signing commitments.
|
||||
///
|
||||
/// [signature commitment share]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#name-signature-share-verificatio
|
||||
/// [signature commitment share]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-signature-share-verificatio
|
||||
pub(super) fn to_group_commitment_share(
|
||||
self,
|
||||
binding_factor: &frost::Rho<C>,
|
||||
|
@ -259,14 +259,12 @@ pub struct GroupCommitmentShare<C: Ciphersuite>(pub(super) <C::Group as Group>::
|
|||
/// Outputs:
|
||||
/// - A byte string containing the serialized representation of B.
|
||||
///
|
||||
/// [`encode_group_commitment_list()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#section-4.3
|
||||
/// [`encode_group_commitment_list()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-list-operations
|
||||
pub(super) fn encode_group_commitments<C: Ciphersuite>(
|
||||
signing_commitments: Vec<SigningCommitments<C>>,
|
||||
) -> Vec<u8> {
|
||||
// B MUST be sorted in ascending order by signer identifier.
|
||||
//
|
||||
// https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#encoding-operations-dep-encoding
|
||||
//
|
||||
// TODO: AtLeastOne or other explicitly Sorted wrapper types?
|
||||
let mut sorted_signing_commitments = signing_commitments;
|
||||
sorted_signing_commitments.sort_by_key(|a| a.identifier);
|
||||
|
@ -274,7 +272,11 @@ pub(super) fn encode_group_commitments<C: Ciphersuite>(
|
|||
let mut bytes = vec![];
|
||||
|
||||
for item in sorted_signing_commitments {
|
||||
bytes.extend_from_slice(&u16::from(item.identifier).to_be_bytes()); // TODO: 2-bytes until spec moves off u16
|
||||
bytes.extend_from_slice(
|
||||
// unwrap() is OK because this will become infallible after refactoring (#102)
|
||||
<<C::Group as Group>::Field as Field>::serialize(&item.identifier.to_scalar().unwrap())
|
||||
.as_ref(),
|
||||
);
|
||||
bytes.extend_from_slice(<C::Group as Group>::serialize(&item.hiding.0).as_ref());
|
||||
bytes.extend_from_slice(<C::Group as Group>::serialize(&item.binding.0).as_ref());
|
||||
}
|
||||
|
@ -327,7 +329,7 @@ where
|
|||
/// Generates the signing nonces and commitments to be used in the signing
|
||||
/// operation.
|
||||
///
|
||||
/// [`commit`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-5.1
|
||||
/// [`commit`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-round-one-commitment
|
||||
pub fn commit<C, R>(
|
||||
participant_identifier: Identifier<C>,
|
||||
secret: &SigningShare<C>,
|
||||
|
|
|
@ -80,7 +80,7 @@ where
|
|||
///
|
||||
/// This is the final step of [`verify_signature_share`] from the spec.
|
||||
///
|
||||
/// [`verify_signature_share`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#section-5.3
|
||||
/// [`verify_signature_share`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-signature-share-verificatio
|
||||
pub fn verify(
|
||||
&self,
|
||||
group_commitment_share: &round1::GroupCommitmentShare<C>,
|
||||
|
@ -127,7 +127,7 @@ where
|
|||
/// Assumes the participant has already determined which nonce corresponds with
|
||||
/// the commitment that was assigned by the coordinator in the SigningPackage.
|
||||
///
|
||||
/// [`sign`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-03.html#section-5.2
|
||||
/// [`sign`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-round-two-signature-share-g
|
||||
pub fn sign<C: Ciphersuite>(
|
||||
signing_package: &SigningPackage<C>,
|
||||
signer_nonces: &round1::SigningNonces<C>,
|
||||
|
|
|
@ -62,7 +62,7 @@ pub trait Field: Copy + Clone {
|
|||
|
||||
/// Generate a random scalar from the entire space [0, l-1]
|
||||
///
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.3>
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.3>
|
||||
fn random<R: RngCore + CryptoRng>(rng: &mut R) -> Self::Scalar;
|
||||
|
||||
/// Generate a random scalar from the entire space [1, l-1]
|
||||
|
@ -73,7 +73,7 @@ pub trait Field: Copy + Clone {
|
|||
/// A member function of a [`Field`] that maps a [`Scalar`] to a unique byte array buf of
|
||||
/// fixed length Ne.
|
||||
///
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.7>
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.8>
|
||||
fn serialize(scalar: &Self::Scalar) -> Self::Serialization;
|
||||
|
||||
/// A member function of a [`Field`] that attempts to map a byte array `buf` to a [`Scalar`].
|
||||
|
@ -82,7 +82,7 @@ pub trait Field: Copy + Clone {
|
|||
/// [`Field`]. This function can raise an [`Error`] if deserialization fails or if the
|
||||
/// resulting [`Scalar`] is zero
|
||||
///
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.8>
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.9>
|
||||
fn deserialize(buf: &Self::Serialization) -> Result<Self::Scalar, Error>;
|
||||
}
|
||||
|
||||
|
@ -125,20 +125,20 @@ pub trait Group: Copy + Clone + PartialEq {
|
|||
|
||||
/// Additive [identity] of the prime order group.
|
||||
///
|
||||
/// [identity]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.2
|
||||
/// [identity]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.2
|
||||
fn identity() -> Self::Element;
|
||||
|
||||
/// The fixed generator element of the prime order group.
|
||||
///
|
||||
/// The 'base' of ['ScalarBaseMult()'] from the spec.
|
||||
///
|
||||
/// [`ScalarBaseMult()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1
|
||||
/// [`ScalarBaseMult()`]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.5
|
||||
fn generator() -> Self::Element;
|
||||
|
||||
/// A member function of a group _G_ that maps an [`Element`] to a unique byte array buf of
|
||||
/// fixed length Ne.
|
||||
///
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.5>
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.6>
|
||||
fn serialize(element: &Self::Element) -> Self::Serialization;
|
||||
|
||||
/// A member function of a [`Group`] that attempts to map a byte array `buf` to an [`Element`].
|
||||
|
@ -147,7 +147,7 @@ pub trait Group: Copy + Clone + PartialEq {
|
|||
/// [`Group`]. This function can raise an [`Error`] if deserialization fails or if the
|
||||
/// resulting [`Element`] is the identity element of the group
|
||||
///
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.1-3.6>
|
||||
/// <https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.1-3.7>
|
||||
fn deserialize(buf: &Self::Serialization) -> Result<Self::Element, Error>;
|
||||
}
|
||||
|
||||
|
@ -157,7 +157,7 @@ pub type Element<C> = <<C as Ciphersuite>::Group as Group>::Element;
|
|||
/// A [FROST ciphersuite] specifies the underlying prime-order group details and cryptographic hash
|
||||
/// function.
|
||||
///
|
||||
/// [FROST ciphersuite]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#name-ciphersuites
|
||||
/// [FROST ciphersuite]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-ciphersuites
|
||||
pub trait Ciphersuite: Copy + Clone + PartialEq {
|
||||
/// The prime order group (or subgroup) that this ciphersuite operates over.
|
||||
type Group: Group;
|
||||
|
@ -173,28 +173,28 @@ pub trait Ciphersuite: Copy + Clone + PartialEq {
|
|||
///
|
||||
/// Maps arbitrary inputs to non-zero `Self::Scalar` elements of the prime-order group scalar field.
|
||||
///
|
||||
/// [H1]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [H1]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-cryptographic-hash-function
|
||||
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
|
||||
|
||||
/// [H2] for a FROST ciphersuite.
|
||||
///
|
||||
/// Maps arbitrary inputs to non-zero `Self::Scalar` elements of the prime-order group scalar field.
|
||||
///
|
||||
/// [H2]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [H2]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-cryptographic-hash-function
|
||||
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
|
||||
|
||||
/// [H3] for a FROST ciphersuite.
|
||||
///
|
||||
/// Maps arbitrary inputs to non-zero `Self::Scalar` elements of the prime-order group scalar field.
|
||||
///
|
||||
/// [H3]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [H3]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-cryptographic-hash-function
|
||||
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
|
||||
|
||||
/// [H4] for a FROST ciphersuite.
|
||||
///
|
||||
/// Usually an an alias for the ciphersuite hash function _H_ with domain separation applied.
|
||||
///
|
||||
/// [H4]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [H4]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-cryptographic-hash-function
|
||||
fn H4(m: &[u8]) -> Self::HashOutput;
|
||||
|
||||
/// [H5] for a FROST ciphersuite.
|
||||
|
@ -226,7 +226,7 @@ pub trait Ciphersuite: Copy + Clone + PartialEq {
|
|||
|
||||
/// A type refinement for the scalar field element representing the per-message _[challenge]_.
|
||||
///
|
||||
/// [challenge]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#name-signature-challenge-computa
|
||||
/// [challenge]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-signature-challenge-computa
|
||||
#[derive(Clone)]
|
||||
pub struct Challenge<C: Ciphersuite>(
|
||||
pub(crate) <<<C as Ciphersuite>::Group as Group>::Field as Field>::Scalar,
|
||||
|
@ -252,8 +252,8 @@ where
|
|||
///
|
||||
/// This is the only invocation of the H2 hash function from the [RFC].
|
||||
///
|
||||
/// [FROST]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-4.7
|
||||
/// [RFC]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-3.2
|
||||
/// [FROST]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#name-signature-challenge-computa
|
||||
/// [RFC]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-3.2
|
||||
fn challenge<C>(
|
||||
R: &<C::Group as Group>::Element,
|
||||
verifying_key: &<C::Group as Group>::Element,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Ciphersuite-generic test functions.
|
||||
use std::{collections::HashMap, convert::TryFrom};
|
||||
|
||||
use crate::frost::{self, Identifier};
|
||||
use crate::frost::{self, keys::generate_coefficients, Identifier};
|
||||
use rand_core::{CryptoRng, RngCore};
|
||||
|
||||
use crate::Ciphersuite;
|
||||
|
@ -13,7 +13,13 @@ pub mod vectors;
|
|||
pub fn check_share_generation<C: Ciphersuite, R: RngCore + CryptoRng>(mut rng: R) {
|
||||
let secret = frost::keys::SharedSecret::<C>::random(&mut rng);
|
||||
|
||||
let secret_shares = frost::keys::generate_secret_shares(&secret, 5, 3, rng).unwrap();
|
||||
let numshares = 5;
|
||||
let threshold = 3;
|
||||
|
||||
let coefficients = generate_coefficients::<C, R>(threshold as usize - 1, rng);
|
||||
|
||||
let secret_shares =
|
||||
frost::keys::generate_secret_shares(&secret, numshares, threshold, coefficients).unwrap();
|
||||
|
||||
for secret_share in secret_shares.iter() {
|
||||
assert!(secret_share.verify().is_ok());
|
||||
|
|
|
@ -7,7 +7,7 @@ use serde_json::Value;
|
|||
|
||||
use crate::{
|
||||
frost::{self, keys::*, round1::*, round2::*, *},
|
||||
Ciphersuite, Field, Group, VerifyingKey,
|
||||
Ciphersuite, Field, Group, Scalar, VerifyingKey,
|
||||
};
|
||||
|
||||
/// Parse test vectors for a given ciphersuite.
|
||||
|
@ -15,9 +15,11 @@ use crate::{
|
|||
pub fn parse_test_vectors<C: Ciphersuite>(
|
||||
json_vectors: &Value,
|
||||
) -> (
|
||||
SharedSecret<C>,
|
||||
VerifyingKey<C>,
|
||||
HashMap<Identifier<C>, KeyPackage<C>>,
|
||||
Vec<u8>,
|
||||
Vec<Scalar<C>>,
|
||||
HashMap<Identifier<C>, SigningNonces<C>>,
|
||||
HashMap<Identifier<C>, SigningCommitments<C>>,
|
||||
HashMap<Identifier<C>, Vec<u8>>,
|
||||
|
@ -27,12 +29,28 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
) {
|
||||
let inputs = &json_vectors["inputs"];
|
||||
|
||||
let secret_key_str = inputs["group_secret_key"].as_str().unwrap();
|
||||
let secret_key_bytes = hex::decode(secret_key_str).unwrap();
|
||||
let secret_key =
|
||||
SharedSecret::from_bytes(secret_key_bytes.try_into().debugless_unwrap()).unwrap();
|
||||
|
||||
let message = inputs["message"].as_str().unwrap();
|
||||
let message_bytes = hex::decode(message).unwrap();
|
||||
|
||||
let share_polynomial_coefficients = inputs["share_polynomial_coefficients"]
|
||||
.as_array()
|
||||
.unwrap()
|
||||
.iter()
|
||||
.map(|v| {
|
||||
let vec = hex::decode(v.as_str().unwrap()).unwrap();
|
||||
<<C::Group as Group>::Field as Field>::deserialize(&vec.try_into().debugless_unwrap())
|
||||
.unwrap()
|
||||
})
|
||||
.collect();
|
||||
|
||||
let mut key_packages: HashMap<Identifier<C>, KeyPackage<C>> = HashMap::new();
|
||||
|
||||
let possible_signers = json_vectors["inputs"]["signers"]
|
||||
let possible_participants = json_vectors["inputs"]["participants"]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.iter();
|
||||
|
@ -40,9 +58,10 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
let group_public =
|
||||
VerifyingKey::<C>::from_hex(inputs["group_public_key"].as_str().unwrap()).unwrap();
|
||||
|
||||
for (i, secret_share) in possible_signers {
|
||||
for (i, secret_share) in possible_participants {
|
||||
let secret =
|
||||
SigningShare::<C>::from_hex(secret_share["signer_share"].as_str().unwrap()).unwrap();
|
||||
SigningShare::<C>::from_hex(secret_share["participant_share"].as_str().unwrap())
|
||||
.unwrap();
|
||||
let signer_public = secret.into();
|
||||
|
||||
let key_package = KeyPackage::<C> {
|
||||
|
@ -64,7 +83,11 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
let mut binding_factor_inputs: HashMap<Identifier<C>, Vec<u8>> = HashMap::new();
|
||||
let mut binding_factors: HashMap<Identifier<C>, Rho<C>> = HashMap::new();
|
||||
|
||||
for (i, signer) in round_one_outputs["signers"].as_object().unwrap().iter() {
|
||||
for (i, signer) in round_one_outputs["participants"]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.iter()
|
||||
{
|
||||
let identifier = u16::from_str(i).unwrap().try_into().unwrap();
|
||||
|
||||
let signing_nonces = SigningNonces::<C> {
|
||||
|
@ -103,7 +126,11 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
|
||||
let mut signature_shares: HashMap<Identifier<C>, SignatureShare<C>> = HashMap::new();
|
||||
|
||||
for (i, signer) in round_two_outputs["signers"].as_object().unwrap().iter() {
|
||||
for (i, signer) in round_two_outputs["participants"]
|
||||
.as_object()
|
||||
.unwrap()
|
||||
.iter()
|
||||
{
|
||||
let sig_share = <<C::Group as Group>::Field as Field>::Serialization::try_from(
|
||||
hex::decode(signer["sig_share"].as_str().unwrap()).unwrap(),
|
||||
)
|
||||
|
@ -129,9 +156,11 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
let signature_bytes = FromHex::from_hex(final_output["sig"].as_str().unwrap()).unwrap();
|
||||
|
||||
(
|
||||
secret_key,
|
||||
group_public,
|
||||
key_packages,
|
||||
message_bytes,
|
||||
share_polynomial_coefficients,
|
||||
signer_nonces,
|
||||
signer_commitments,
|
||||
binding_factor_inputs,
|
||||
|
@ -144,9 +173,11 @@ pub fn parse_test_vectors<C: Ciphersuite>(
|
|||
/// Test with the given test vectors for a ciphersuite.
|
||||
pub fn check_sign_with_test_vectors<C: Ciphersuite>(json_vectors: &Value) {
|
||||
let (
|
||||
secret_key,
|
||||
group_public,
|
||||
key_packages,
|
||||
message_bytes,
|
||||
share_polynomials_coefficients,
|
||||
signer_nonces,
|
||||
signer_commitments,
|
||||
binding_factor_inputs,
|
||||
|
@ -159,11 +190,29 @@ pub fn check_sign_with_test_vectors<C: Ciphersuite>(json_vectors: &Value) {
|
|||
// Key generation
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
let numshares = key_packages.len();
|
||||
let threshold = share_polynomials_coefficients.len() + 1;
|
||||
let secret_shares = generate_secret_shares(
|
||||
&secret_key,
|
||||
numshares as u8,
|
||||
threshold as u8,
|
||||
share_polynomials_coefficients,
|
||||
)
|
||||
.unwrap();
|
||||
let secret_shares: HashMap<_, _> = secret_shares
|
||||
.iter()
|
||||
.map(|share| (share.identifier, share))
|
||||
.collect();
|
||||
|
||||
for key_package in key_packages.values() {
|
||||
assert_eq!(
|
||||
*key_package.public(),
|
||||
frost::keys::VerifyingShare::from(*key_package.secret_share())
|
||||
);
|
||||
assert_eq!(
|
||||
key_package.secret_share(),
|
||||
secret_shares[key_package.identifier()].secret()
|
||||
)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -100,8 +100,8 @@ impl Group for RistrettoGroup {
|
|||
|
||||
/// Context string 'FROST-RISTRETTO255-SHA512-v5' from the ciphersuite in the [spec]
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.2-1
|
||||
const CONTEXT_STRING: &str = "FROST-RISTRETTO255-SHA512-v8";
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-1
|
||||
const CONTEXT_STRING: &str = "FROST-RISTRETTO255-SHA512-v10";
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Ristretto255Sha512;
|
||||
|
@ -115,7 +115,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H1 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.1
|
||||
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -129,7 +129,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H2 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.2
|
||||
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -143,7 +143,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H3 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#name-frostristretto255-sha-512
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.3
|
||||
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -157,7 +157,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H4 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.4
|
||||
fn H4(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -171,7 +171,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H5 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.5
|
||||
fn H5(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"config": {
|
||||
"MAX_SIGNERS": "3",
|
||||
"NUM_SIGNERS": "2",
|
||||
"MIN_SIGNERS": "2",
|
||||
"MAX_PARTICIPANTS": "3",
|
||||
"NUM_PARTICIPANTS": "2",
|
||||
"MIN_PARTICIPANTS": "2",
|
||||
"name": "FROST(ristretto255, SHA-512)",
|
||||
"group": "ristretto255",
|
||||
"hash": "SHA-512"
|
||||
|
@ -11,51 +11,58 @@
|
|||
"group_secret_key": "1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab265f2ebc4f970b",
|
||||
"group_public_key": "e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d05083c7254f57",
|
||||
"message": "74657374",
|
||||
"signers": {
|
||||
"share_polynomial_coefficients": [
|
||||
"410f8b744b19325891d73736923525a4f596c805d060dfb9c98009d34e3fec02"
|
||||
],
|
||||
"participants": {
|
||||
"1": {
|
||||
"signer_share": "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e"
|
||||
"participant_share": "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e"
|
||||
},
|
||||
"2": {
|
||||
"signer_share": "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01"
|
||||
"participant_share": "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01"
|
||||
},
|
||||
"3": {
|
||||
"signer_share": "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04"
|
||||
"participant_share": "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_one_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"hiding_nonce": "1eaee906e0554a5e533415e971eefa909f3c614c7c75e27f381b0270a9afe308",
|
||||
"binding_nonce": "16175fc2e7545baf7180e8f5b6e1e73c4f2769323cc76754bdd79fe93ab0bd0b",
|
||||
"hiding_nonce_commitment": "80d35700fda011d9e2b2fad4f237bf88f2978d954382dfd36a517ab0497a474f",
|
||||
"binding_nonce_commitment": "40f0fecaf94e656b3f802ba9827fca9fa994c13c98a5ff257973f8bdbc733324",
|
||||
"binding_factor_input": "fe9082dcc1ae1ae11380ac4cf0b6e2770af565ff5af9016254dc7c9d4869cbae0f6e4d94b23e5781b91bc74a25e0c773446b2640290d07c83f0b067ff870a80179b2d1262816a7a4fad96b747bd6b35ccf4a912a793c5701d54852db80904a767cbbd6e37377eec77f407b22890c01190995066cce59d88a14ac56ac40b3bdc90001",
|
||||
"binding_factor": "c0f5ee2613c448137bae256a4e95d56deb8c59f934332c0c0041720b8819680f"
|
||||
"hiding_nonce_randomness": "0a016efd0abf8e556fd67288950bb7fc0843be63e306c7264bc9d24d1d65e0ee",
|
||||
"binding_nonce_randomness": "35b6bab19e3e931e36c612ccc6b3c9d3a3479d2704aac3324b79c7bb6665acfb",
|
||||
"hiding_nonce": "de3e8f526dcb51a1b9b48cc284aeca27c385aa3ba1a92a0c8440d51e1a1d2f00",
|
||||
"binding_nonce": "fa8dca5ec7a05d5a7b782be847ba3dde1509de1dbcf0569fc980cff795db5404",
|
||||
"hiding_nonce_commitment": "3677297a5df660bf63bb8fcae79b7f98cf4f2e99f61bc762de9795cacd1cba62",
|
||||
"binding_nonce_commitment": "142aece8aa8b16766664d8aaa5a5e709404bb8443309ef1ea9ad9254794a1f09",
|
||||
"binding_factor_input": "c70ac0b3effa113b8f4d8a6b1393ef7f0910862d143fde83e410db94f3818295ff49ed5aed0e57b2712f2ce0f9166f1ffdce282786c7ee8c2db2df295c61dc5fd0f93a769d09d44352c4e709c2e239fc34a1b89db44cb2410602285ffd70f3fa0a62dd70cfdb369ac0a7efc587f6f671a88412b2570280da24bd36f8ffda6d280100000000000000000000000000000000000000000000000000000000000000",
|
||||
"binding_factor": "dbaa0ae3c5663816cdc646281be46b0b09eca6a1ecf7781f29475be27d30fd08"
|
||||
},
|
||||
"3": {
|
||||
"hiding_nonce": "48d78b8c2de1a515513f9d3fc464a19a72304fac522f17cc647706cb22c21403",
|
||||
"binding_nonce": "5c0f10966b3f1386660a87de0fafd69decbe9ffae1a152a88b7d83bb4fb1c908",
|
||||
"hiding_nonce_commitment": "20dec6ad0795f82009a1a94b6ad79f01a1e95ae8e308d8d8fae8285982308113",
|
||||
"binding_nonce_commitment": "98437dafb20fdb18255464072bee514889aeeec324f149d49747143c3613056d",
|
||||
"binding_factor_input": "fe9082dcc1ae1ae11380ac4cf0b6e2770af565ff5af9016254dc7c9d4869cbae0f6e4d94b23e5781b91bc74a25e0c773446b2640290d07c83f0b067ff870a80179b2d1262816a7a4fad96b747bd6b35ccf4a912a793c5701d54852db80904a767cbbd6e37377eec77f407b22890c01190995066cce59d88a14ac56ac40b3bdc90003",
|
||||
"binding_factor": "8ea449e545706bb3b42c66423005451457e4bb4dea2c2d0b1d157e6bb652ec09"
|
||||
"hiding_nonce_randomness": "ac4e65529397de3a868a902e9040e38b26547c18b7267fa1d1bbfe4ed14d6b5f",
|
||||
"binding_nonce_randomness": "74213c820b7266c4990a0758f4c520685375cb98822499406654bdb1a426582e",
|
||||
"hiding_nonce": "e07061a9ab6735de9a75b0c64f086c5b999894611d0cdc03f85c4e87c8aae602",
|
||||
"binding_nonce": "38b17578e8e6ad4077071ce6b0bf9cb85ac35fee7868dcb6d9bfa97f0e153e0e",
|
||||
"hiding_nonce_commitment": "f8d758ad9373754c1d2bca9c38478e4eb857aa032836ade6eb0726f5e1d08037",
|
||||
"binding_nonce_commitment": "529823e80220849c195072a26acca88f65639d4181927bb7fcd96e43d9a34649",
|
||||
"binding_factor_input": "c70ac0b3effa113b8f4d8a6b1393ef7f0910862d143fde83e410db94f3818295ff49ed5aed0e57b2712f2ce0f9166f1ffdce282786c7ee8c2db2df295c61dc5fd0f93a769d09d44352c4e709c2e239fc34a1b89db44cb2410602285ffd70f3fa0a62dd70cfdb369ac0a7efc587f6f671a88412b2570280da24bd36f8ffda6d280300000000000000000000000000000000000000000000000000000000000000",
|
||||
"binding_factor": "aa076fec41410f6c0667e47443fcd1ed828854d84b19d1d08624d084720c7d05"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_two_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"sig_share": "5ae13621ebeef844e39454eb3478a50c4531d25939e1065f44f5b04a8535090e"
|
||||
"sig_share": "a5f046916a6a111672111e47f9825586e1188da8a0f3b7c61f2b6b432c636e07"
|
||||
},
|
||||
"3": {
|
||||
"sig_share": "aa432dcf274a9441c205e76fe43497be99efe374f9853477bd5add2075f6970c"
|
||||
"sig_share": "4c175c7e43bd197980c2021774036eb288f54179f079fbf21b7d2f9f52846401"
|
||||
}
|
||||
}
|
||||
},
|
||||
"final_output": {
|
||||
"sig": "9c407badb8cacf10f306d94e31fb2a71d6a8398039802b4d80a127847239720617516e93f8d57a2ecffd43b83ab35db6de20b6ce32673bd601508e6bfa2ba10a"
|
||||
"sig": "94b11def3f919503c3544452ad2a59f198f64cc323bd758bb1c65b42032a7473f107a30fae272b8ff2d3205e6d86c3386a0ecf21916db3b93ba89ae27ee7d208"
|
||||
}
|
||||
}
|
|
@ -136,8 +136,8 @@ impl Group for P256Group {
|
|||
|
||||
/// Context string from the ciphersuite in the [spec]
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-1
|
||||
const CONTEXT_STRING: &str = "FROST-P256-SHA256-v8";
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-1
|
||||
const CONTEXT_STRING: &str = "FROST-P256-SHA256-v10";
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
/// An implementation of the FROST ciphersuite FROST(P-256, SHA-256).
|
||||
|
@ -152,7 +152,7 @@ impl Ciphersuite for P256Sha256 {
|
|||
|
||||
/// H1 for FROST(P-256, SHA-256)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-2.2.2.1
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-2.2.2.1
|
||||
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let mut u = [P256ScalarField::zero()];
|
||||
let dst = CONTEXT_STRING.to_owned() + "rho";
|
||||
|
@ -163,7 +163,7 @@ impl Ciphersuite for P256Sha256 {
|
|||
|
||||
/// H2 for FROST(P-256, SHA-256)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-2.2.2.2
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-2.2.2.2
|
||||
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let mut u = [P256ScalarField::zero()];
|
||||
let dst = CONTEXT_STRING.to_owned() + "chal";
|
||||
|
@ -174,7 +174,7 @@ impl Ciphersuite for P256Sha256 {
|
|||
|
||||
/// H3 for FROST(P-256, SHA-256)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-2.2.2.4
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-2.2.2.3
|
||||
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let mut u = [P256ScalarField::zero()];
|
||||
let dst = CONTEXT_STRING.to_owned() + "nonce";
|
||||
|
@ -185,7 +185,7 @@ impl Ciphersuite for P256Sha256 {
|
|||
|
||||
/// H4 for FROST(P-256, SHA-256)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-2.2.2.3
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-2.2.2.4
|
||||
fn H4(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha256::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -199,7 +199,7 @@ impl Ciphersuite for P256Sha256 {
|
|||
|
||||
/// H5 for FROST(P-256, SHA-256)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.4-2.2.2.3
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.4-2.2.2.5
|
||||
fn H5(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha256::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"config": {
|
||||
"MAX_SIGNERS": "3",
|
||||
"NUM_SIGNERS": "2",
|
||||
"MIN_SIGNERS": "2",
|
||||
"MAX_PARTICIPANTS": "3",
|
||||
"NUM_PARTICIPANTS": "2",
|
||||
"MIN_PARTICIPANTS": "2",
|
||||
"name": "FROST(P-256, SHA-256)",
|
||||
"group": "P-256",
|
||||
"hash": "SHA-256"
|
||||
|
@ -11,51 +11,58 @@
|
|||
"group_secret_key": "8ba9bba2e0fd8c4767154d35a0b7562244a4aaf6f36c8fb8735fa48b301bd8de",
|
||||
"group_public_key": "023a309ad94e9fe8a7ba45dfc58f38bf091959d3c99cfbd02b4dc00585ec45ab70",
|
||||
"message": "74657374",
|
||||
"signers": {
|
||||
"share_polynomial_coefficients": [
|
||||
"80f25e6c0709353e46bfbe882a11bdbb1f8097e46340eb8673b7e14556e6c3a4"
|
||||
],
|
||||
"participants": {
|
||||
"1": {
|
||||
"signer_share": "0c9c1a0fe806c184add50bbdcac913dda73e482daf95dcb9f35dbb0d8a9f7731"
|
||||
"participant_share": "0c9c1a0fe806c184add50bbdcac913dda73e482daf95dcb9f35dbb0d8a9f7731"
|
||||
},
|
||||
"2": {
|
||||
"signer_share": "8d8e787bef0ff6c2f494ca45f4dad198c6bee01212d6c84067159c52e1863ad5"
|
||||
"participant_share": "8d8e787bef0ff6c2f494ca45f4dad198c6bee01212d6c84067159c52e1863ad5"
|
||||
},
|
||||
"3": {
|
||||
"signer_share": "0e80d6e8f6192c003b5488ce1eec8f5429587d48cf001541e713b2d53c09d928"
|
||||
"participant_share": "0e80d6e8f6192c003b5488ce1eec8f5429587d48cf001541e713b2d53c09d928"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_one_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"hiding_nonce": "e9165dad654fc20a9e31ca6f32ac032ec327b551a50e8ac5cf25f5c4c9e20757",
|
||||
"binding_nonce": "e9059a232598a0fba0e495a687580e624ab425337c3221246fb2c716905bc9e7",
|
||||
"hiding_nonce_commitment": "0228df2e7f6c254b40a9f8853cf6c4f21eacbb6f0663027384966816b57e513304",
|
||||
"binding_nonce_commitment": "02f5b7f48786f8b83ebefed6249825650c4fa657da66ae0da1b2613dedbe122ec8",
|
||||
"binding_factor_input": "3617acb73b44df565fbcbbbd1824142c473ad1d6c8007c4b72a298d1eaae5766b730d2e6594ea697a5971f15e989ac47ecc015692ad88b615a41e652a306c7e50001",
|
||||
"binding_factor": "95f987c0ab590507a8c4deaf506ffc182d3626e30386306f7ab3aaf0b0013cd3"
|
||||
"hiding_nonce_randomness": "3029ae05a266703f618e60c26653f6b8f35a759ec2adecf8b7d9e1719375494e",
|
||||
"binding_nonce_randomness": "86755fd9be109ff0549833931080ac344b0d775a029fca0329f8ce732060f81e",
|
||||
"hiding_nonce": "9aa66350b0f72b27ce4668323b4280cd49709177ed8373977c22a75546c9995d",
|
||||
"binding_nonce": "bd8b05d7fd0ff5a5ed65b1f105478f7718a981741fa8fa9b55ac6d3c8fc59a05",
|
||||
"hiding_nonce_commitment": "03071549b356988df0f7187585e2d82d6f916700cfdd49634d0c27965139fd53ec",
|
||||
"binding_nonce_commitment": "02151f45451b719bf68f6c609967ebea3c78c9ece4c04a564a0c50d22f0f534112",
|
||||
"binding_factor_input": "47d0b1c45754dd58dc369bc4c1a9b24ffbb67ceb6d6e25c302e9875202f7d2b4755d9beaba0a02b01315bd42fa11590d5a4d531d1f7f81c5fc70a82ecada72e90000000000000000000000000000000000000000000000000000000000000001",
|
||||
"binding_factor": "0e9709d66649a0a245f28666bd01c863a6a647f213fd49eeaacfeca15402ddf4"
|
||||
},
|
||||
"3": {
|
||||
"hiding_nonce": "b9d136e29eb758bd77cb83c317ac4e336cf8cda830c089deddf6d5ec81da9884",
|
||||
"binding_nonce": "5261e2d00ce227e67bb9b38990294e2c82970f335b2e6d9f1d07a72ba43d01f0",
|
||||
"hiding_nonce_commitment": "02f87bd95ab5e08ea292a96e21caf9bdc5002ebf6e3ce14f922817d26a4d08144d",
|
||||
"binding_nonce_commitment": "0263cb513e347fcf8492c7f97843ed4c3797f2f3fe925b1e68f65fb90826fe9597",
|
||||
"binding_factor_input": "3617acb73b44df565fbcbbbd1824142c473ad1d6c8007c4b72a298d1eaae5766b730d2e6594ea697a5971f15e989ac47ecc015692ad88b615a41e652a306c7e50003",
|
||||
"binding_factor": "2f21db4f811b13f938a13b8f2633467d250703fe5bd63cd24f08bef6fd2f3c29"
|
||||
"hiding_nonce_randomness": "2741900f778d51f4431644a62a69f1623d7569ecf2d628d60cb28e27db949161",
|
||||
"binding_nonce_randomness": "a62404370cb2a2e0aebef27ec72c1433a627dfcc5f0cdf5ba4799fc326a66a3f",
|
||||
"hiding_nonce": "4c1aec8e84c496b80af98415fada2e6a4b1f902d4bc6c9682699b8aeffd97419",
|
||||
"binding_nonce": "eeaf5ef7af01e55050fb8acafc9c9306ef1cc13214677ba33e7bc51e8677e892",
|
||||
"hiding_nonce_commitment": "0351cd636672cac59d384498dd9db2b72ea8e701a702867c17e3ecf675d9a9fc91",
|
||||
"binding_nonce_commitment": "032bddd1ab4bfda79c707742f0e314ff2be9594058ba590613ba9840886bab1a59",
|
||||
"binding_factor_input": "47d0b1c45754dd58dc369bc4c1a9b24ffbb67ceb6d6e25c302e9875202f7d2b4755d9beaba0a02b01315bd42fa11590d5a4d531d1f7f81c5fc70a82ecada72e90000000000000000000000000000000000000000000000000000000000000003",
|
||||
"binding_factor": "0b5c759331915b25c5eb5307617e01aa99bc5c89a403d9c6b59949045a4c0a77"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_two_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"sig_share": "bdaa275f10ca57e3a3a9a7a0d95aeabb517897d8482873a8f9713d458f94756f"
|
||||
"sig_share": "ec5b8ab47d55903698492a07bb322ab6e7d3cf32581dcedf43c4fa18b46f3e10"
|
||||
},
|
||||
"3": {
|
||||
"sig_share": "0e8fd85386939e8974a8748e66641df0fe043323c52487a2b10b8a397897de21"
|
||||
"sig_share": "c97da3580560e88725a8e393d46fee18ecd2e00148e5e303d4a510fae9c11da5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"final_output": {
|
||||
"sig": "03c41521412528dce484c35b6b9b7cc8150102ab3e4bdf858d702270c05098e6c6cc39ffb2975df66d18521c2f3fbf08ac4f7ccafc0d4cfb4baa7cc77f082c5390"
|
||||
"sig": "036b3eba585ff5d40df29893fb6f60572803aef97800cfaaaa5cf0f0f19d8237f7b5d92e0d82b678bcbdf20d9b8fa218d017bfb485f9ec135e24b04050a1cd3664"
|
||||
}
|
||||
}
|
|
@ -109,8 +109,8 @@ impl Group for RistrettoGroup {
|
|||
|
||||
/// Context string 'FROST-RISTRETTO255-SHA512-v5' from the ciphersuite in the [spec]
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#section-6.2-1
|
||||
const CONTEXT_STRING: &str = "FROST-RISTRETTO255-SHA512-v8";
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-1
|
||||
const CONTEXT_STRING: &str = "FROST-RISTRETTO255-SHA512-v10";
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
/// An implementation of the FROST(ristretto255, SHA-512) ciphersuite.
|
||||
|
@ -125,7 +125,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H1 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.1
|
||||
fn H1(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -139,7 +139,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H2 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.2
|
||||
fn H2(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -153,7 +153,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H3 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-05.html#name-frostristretto255-sha-512
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.3
|
||||
fn H3(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -167,7 +167,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H4 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.4
|
||||
fn H4(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
@ -181,7 +181,7 @@ impl Ciphersuite for Ristretto255Sha512 {
|
|||
|
||||
/// H5 for FROST(ristretto255, SHA-512)
|
||||
///
|
||||
/// [spec]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash-function-dep-hash
|
||||
/// [spec]: https://www.ietf.org/archive/id/draft-irtf-cfrg-frost-10.html#section-6.2-2.2.2.5
|
||||
fn H5(m: &[u8]) -> Self::HashOutput {
|
||||
let h = Sha512::new()
|
||||
.chain(CONTEXT_STRING.as_bytes())
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"config": {
|
||||
"MAX_SIGNERS": "3",
|
||||
"NUM_SIGNERS": "2",
|
||||
"MIN_SIGNERS": "2",
|
||||
"MAX_PARTICIPANTS": "3",
|
||||
"NUM_PARTICIPANTS": "2",
|
||||
"MIN_PARTICIPANTS": "2",
|
||||
"name": "FROST(ristretto255, SHA-512)",
|
||||
"group": "ristretto255",
|
||||
"hash": "SHA-512"
|
||||
|
@ -11,51 +11,58 @@
|
|||
"group_secret_key": "1b25a55e463cfd15cf14a5d3acc3d15053f08da49c8afcf3ab265f2ebc4f970b",
|
||||
"group_public_key": "e2a62f39eede11269e3bd5a7d97554f5ca384f9f6d3dd9c3c0d05083c7254f57",
|
||||
"message": "74657374",
|
||||
"signers": {
|
||||
"share_polynomial_coefficients": [
|
||||
"410f8b744b19325891d73736923525a4f596c805d060dfb9c98009d34e3fec02"
|
||||
],
|
||||
"participants": {
|
||||
"1": {
|
||||
"signer_share": "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e"
|
||||
"participant_share": "5c3430d391552f6e60ecdc093ff9f6f4488756aa6cebdbad75a768010b8f830e"
|
||||
},
|
||||
"2": {
|
||||
"signer_share": "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01"
|
||||
"participant_share": "b06fc5eac20b4f6e1b271d9df2343d843e1e1fb03c4cbb673f2872d459ce6f01"
|
||||
},
|
||||
"3": {
|
||||
"signer_share": "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04"
|
||||
"participant_share": "f17e505f0e2581c6acfe54d3846a622834b5e7b50cad9a2109a97ba7a80d5c04"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_one_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"hiding_nonce": "1eaee906e0554a5e533415e971eefa909f3c614c7c75e27f381b0270a9afe308",
|
||||
"binding_nonce": "16175fc2e7545baf7180e8f5b6e1e73c4f2769323cc76754bdd79fe93ab0bd0b",
|
||||
"hiding_nonce_commitment": "80d35700fda011d9e2b2fad4f237bf88f2978d954382dfd36a517ab0497a474f",
|
||||
"binding_nonce_commitment": "40f0fecaf94e656b3f802ba9827fca9fa994c13c98a5ff257973f8bdbc733324",
|
||||
"binding_factor_input": "fe9082dcc1ae1ae11380ac4cf0b6e2770af565ff5af9016254dc7c9d4869cbae0f6e4d94b23e5781b91bc74a25e0c773446b2640290d07c83f0b067ff870a80179b2d1262816a7a4fad96b747bd6b35ccf4a912a793c5701d54852db80904a767cbbd6e37377eec77f407b22890c01190995066cce59d88a14ac56ac40b3bdc90001",
|
||||
"binding_factor": "c0f5ee2613c448137bae256a4e95d56deb8c59f934332c0c0041720b8819680f"
|
||||
"hiding_nonce_randomness": "0a016efd0abf8e556fd67288950bb7fc0843be63e306c7264bc9d24d1d65e0ee",
|
||||
"binding_nonce_randomness": "35b6bab19e3e931e36c612ccc6b3c9d3a3479d2704aac3324b79c7bb6665acfb",
|
||||
"hiding_nonce": "de3e8f526dcb51a1b9b48cc284aeca27c385aa3ba1a92a0c8440d51e1a1d2f00",
|
||||
"binding_nonce": "fa8dca5ec7a05d5a7b782be847ba3dde1509de1dbcf0569fc980cff795db5404",
|
||||
"hiding_nonce_commitment": "3677297a5df660bf63bb8fcae79b7f98cf4f2e99f61bc762de9795cacd1cba62",
|
||||
"binding_nonce_commitment": "142aece8aa8b16766664d8aaa5a5e709404bb8443309ef1ea9ad9254794a1f09",
|
||||
"binding_factor_input": "c70ac0b3effa113b8f4d8a6b1393ef7f0910862d143fde83e410db94f3818295ff49ed5aed0e57b2712f2ce0f9166f1ffdce282786c7ee8c2db2df295c61dc5fd0f93a769d09d44352c4e709c2e239fc34a1b89db44cb2410602285ffd70f3fa0a62dd70cfdb369ac0a7efc587f6f671a88412b2570280da24bd36f8ffda6d280100000000000000000000000000000000000000000000000000000000000000",
|
||||
"binding_factor": "dbaa0ae3c5663816cdc646281be46b0b09eca6a1ecf7781f29475be27d30fd08"
|
||||
},
|
||||
"3": {
|
||||
"hiding_nonce": "48d78b8c2de1a515513f9d3fc464a19a72304fac522f17cc647706cb22c21403",
|
||||
"binding_nonce": "5c0f10966b3f1386660a87de0fafd69decbe9ffae1a152a88b7d83bb4fb1c908",
|
||||
"hiding_nonce_commitment": "20dec6ad0795f82009a1a94b6ad79f01a1e95ae8e308d8d8fae8285982308113",
|
||||
"binding_nonce_commitment": "98437dafb20fdb18255464072bee514889aeeec324f149d49747143c3613056d",
|
||||
"binding_factor_input": "fe9082dcc1ae1ae11380ac4cf0b6e2770af565ff5af9016254dc7c9d4869cbae0f6e4d94b23e5781b91bc74a25e0c773446b2640290d07c83f0b067ff870a80179b2d1262816a7a4fad96b747bd6b35ccf4a912a793c5701d54852db80904a767cbbd6e37377eec77f407b22890c01190995066cce59d88a14ac56ac40b3bdc90003",
|
||||
"binding_factor": "8ea449e545706bb3b42c66423005451457e4bb4dea2c2d0b1d157e6bb652ec09"
|
||||
"hiding_nonce_randomness": "ac4e65529397de3a868a902e9040e38b26547c18b7267fa1d1bbfe4ed14d6b5f",
|
||||
"binding_nonce_randomness": "74213c820b7266c4990a0758f4c520685375cb98822499406654bdb1a426582e",
|
||||
"hiding_nonce": "e07061a9ab6735de9a75b0c64f086c5b999894611d0cdc03f85c4e87c8aae602",
|
||||
"binding_nonce": "38b17578e8e6ad4077071ce6b0bf9cb85ac35fee7868dcb6d9bfa97f0e153e0e",
|
||||
"hiding_nonce_commitment": "f8d758ad9373754c1d2bca9c38478e4eb857aa032836ade6eb0726f5e1d08037",
|
||||
"binding_nonce_commitment": "529823e80220849c195072a26acca88f65639d4181927bb7fcd96e43d9a34649",
|
||||
"binding_factor_input": "c70ac0b3effa113b8f4d8a6b1393ef7f0910862d143fde83e410db94f3818295ff49ed5aed0e57b2712f2ce0f9166f1ffdce282786c7ee8c2db2df295c61dc5fd0f93a769d09d44352c4e709c2e239fc34a1b89db44cb2410602285ffd70f3fa0a62dd70cfdb369ac0a7efc587f6f671a88412b2570280da24bd36f8ffda6d280300000000000000000000000000000000000000000000000000000000000000",
|
||||
"binding_factor": "aa076fec41410f6c0667e47443fcd1ed828854d84b19d1d08624d084720c7d05"
|
||||
}
|
||||
}
|
||||
},
|
||||
"round_two_outputs": {
|
||||
"participants": "1,3",
|
||||
"signers": {
|
||||
"participant_list": "1,3",
|
||||
"participants": {
|
||||
"1": {
|
||||
"sig_share": "5ae13621ebeef844e39454eb3478a50c4531d25939e1065f44f5b04a8535090e"
|
||||
"sig_share": "a5f046916a6a111672111e47f9825586e1188da8a0f3b7c61f2b6b432c636e07"
|
||||
},
|
||||
"3": {
|
||||
"sig_share": "aa432dcf274a9441c205e76fe43497be99efe374f9853477bd5add2075f6970c"
|
||||
"sig_share": "4c175c7e43bd197980c2021774036eb288f54179f079fbf21b7d2f9f52846401"
|
||||
}
|
||||
}
|
||||
},
|
||||
"final_output": {
|
||||
"sig": "9c407badb8cacf10f306d94e31fb2a71d6a8398039802b4d80a127847239720617516e93f8d57a2ecffd43b83ab35db6de20b6ce32673bd601508e6bfa2ba10a"
|
||||
"sig": "94b11def3f919503c3544452ad2a59f198f64cc323bd758bb1c65b42032a7473f107a30fae272b8ff2d3205e6d86c3386a0ecf21916db3b93ba89ae27ee7d208"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue