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:
Conrado Gouvea 2022-10-03 15:41:02 -03:00 committed by GitHub
parent 45d16cb801
commit 828279d847
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 251 additions and 155 deletions

View File

@ -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 {

View File

@ -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(

View File

@ -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>,

View File

@ -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>,

View File

@ -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,

View File

@ -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());

View File

@ -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()
)
}
/////////////////////////////////////////////////////////////////////////////

View File

@ -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())

View File

@ -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"
}
}

View File

@ -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())

View File

@ -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"
}
}

View File

@ -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())

View File

@ -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"
}
}