check number of commitments in sign() (#480)

* check number of commitments in sign()

* make comment clearer
This commit is contained in:
Conrado Gouvea 2023-09-06 06:48:30 -03:00 committed by GitHub
parent 030c4cea81
commit 4ee0d32867
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 124 additions and 33 deletions

View File

@ -9,6 +9,8 @@ Entries are listed in reverse chronological order.
* Challenge hashing during DKG computation was changed to match the paper. * Challenge hashing during DKG computation was changed to match the paper.
This means that code running this version won't interoperate with code This means that code running this version won't interoperate with code
running previous versions. running previous versions.
* A new `min_signers` field was added to `KeyPackage`, which changes its
`new()` method and its serde serialization.
## Released ## Released

View File

@ -56,10 +56,12 @@ pub enum Error<C: Ciphersuite> {
/// The participant's commitment is missing from the Signing Package /// The participant's commitment is missing from the Signing Package
#[error("The Signing Package must contain the participant's Commitment.")] #[error("The Signing Package must contain the participant's Commitment.")]
MissingCommitment, MissingCommitment,
/// The participant's commitment is incorrect /// The participant's commitment is incorrect
#[error("The participant's commitment is incorrect.")] #[error("The participant's commitment is incorrect.")]
IncorrectCommitment, IncorrectCommitment,
/// Incorrect number of commitments.
#[error("Incorrect number of commitments.")]
IncorrectNumberOfCommitments,
/// Signature share verification failed. /// Signature share verification failed.
#[error("Invalid signature share.")] #[error("Invalid signature share.")]
InvalidSignatureShare { InvalidSignatureShare {
@ -144,6 +146,7 @@ where
| Error::InvalidCoefficient | Error::InvalidCoefficient
| Error::UnknownIdentifier | Error::UnknownIdentifier
| Error::IncorrectNumberOfIdentifiers | Error::IncorrectNumberOfIdentifiers
| Error::IncorrectNumberOfCommitments
| Error::IdentifierDerivationNotSupported => None, | Error::IdentifierDerivationNotSupported => None,
} }
} }

View File

@ -576,6 +576,7 @@ pub struct KeyPackage<C: Ciphersuite> {
/// The public verifying key that represents the entire group. /// The public verifying key that represents the entire group.
#[zeroize(skip)] #[zeroize(skip)]
pub(crate) group_public: VerifyingKey<C>, pub(crate) group_public: VerifyingKey<C>,
pub(crate) min_signers: u16,
/// Ciphersuite ID for serialization /// Ciphersuite ID for serialization
#[cfg_attr( #[cfg_attr(
feature = "serde", feature = "serde",
@ -599,12 +600,14 @@ where
secret_share: SigningShare<C>, secret_share: SigningShare<C>,
public: VerifyingShare<C>, public: VerifyingShare<C>,
group_public: VerifyingKey<C>, group_public: VerifyingKey<C>,
min_signers: u16,
) -> Self { ) -> Self {
Self { Self {
identifier, identifier,
secret_share, secret_share,
public, public,
group_public, group_public,
min_signers,
ciphersuite: (), ciphersuite: (),
} }
} }
@ -632,6 +635,7 @@ where
secret_share: secret_share.value, secret_share: secret_share.value,
public, public,
group_public, group_public,
min_signers: secret_share.commitment.0.len() as u16,
ciphersuite: (), ciphersuite: (),
}) })
} }

View File

@ -107,6 +107,8 @@ pub mod round1 {
pub(crate) coefficients: Vec<Scalar<C>>, pub(crate) coefficients: Vec<Scalar<C>>,
/// The public commitment for the participant (C_i) /// The public commitment for the participant (C_i)
pub(crate) commitment: VerifiableSecretSharingCommitment<C>, pub(crate) commitment: VerifiableSecretSharingCommitment<C>,
/// The minimum number of signers.
pub(crate) min_signers: u16,
/// The total number of signers. /// The total number of signers.
pub(crate) max_signers: u16, pub(crate) max_signers: u16,
} }
@ -120,6 +122,7 @@ pub mod round1 {
.field("identifier", &self.identifier) .field("identifier", &self.identifier)
.field("coefficients", &"<redacted>") .field("coefficients", &"<redacted>")
.field("commitment", &self.commitment) .field("commitment", &self.commitment)
.field("min_signers", &self.min_signers)
.field("max_signers", &self.max_signers) .field("max_signers", &self.max_signers)
.finish() .finish()
} }
@ -197,6 +200,8 @@ pub mod round2 {
pub(crate) commitment: VerifiableSecretSharingCommitment<C>, pub(crate) commitment: VerifiableSecretSharingCommitment<C>,
/// The participant's own secret share (f_i(i)). /// The participant's own secret share (f_i(i)).
pub(crate) secret_share: Scalar<C>, pub(crate) secret_share: Scalar<C>,
/// The minimum number of signers.
pub(crate) min_signers: u16,
/// The total number of signers. /// The total number of signers.
pub(crate) max_signers: u16, pub(crate) max_signers: u16,
} }
@ -210,6 +215,7 @@ pub mod round2 {
.field("identifier", &self.identifier) .field("identifier", &self.identifier)
.field("commitment", &self.commitment) .field("commitment", &self.commitment)
.field("secret_share", &"<redacted>") .field("secret_share", &"<redacted>")
.field("min_signers", &self.min_signers)
.field("max_signers", &self.max_signers) .field("max_signers", &self.max_signers)
.finish() .finish()
} }
@ -273,6 +279,7 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
identifier, identifier,
coefficients, coefficients,
commitment: commitment.clone(), commitment: commitment.clone(),
min_signers,
max_signers, max_signers,
}; };
let package = round1::Package { let package = round1::Package {
@ -368,6 +375,7 @@ pub fn part2<C: Ciphersuite>(
identifier: secret_package.identifier, identifier: secret_package.identifier,
commitment: secret_package.commitment, commitment: secret_package.commitment,
secret_share: fii, secret_share: fii,
min_signers: secret_package.min_signers,
max_signers: secret_package.max_signers, max_signers: secret_package.max_signers,
}, },
round2_packages, round2_packages,
@ -518,6 +526,7 @@ pub fn part3<C: Ciphersuite>(
secret_share: signing_share, secret_share: signing_share,
public: verifying_key, public: verifying_key,
group_public, group_public,
min_signers: round2_secret_package.min_signers,
ciphersuite: (), ciphersuite: (),
}; };
let public_key_package = PublicKeyPackage { let public_key_package = PublicKeyPackage {

View File

@ -189,6 +189,10 @@ pub fn sign<C: Ciphersuite>(
signer_nonces: &round1::SigningNonces<C>, signer_nonces: &round1::SigningNonces<C>,
key_package: &frost::keys::KeyPackage<C>, key_package: &frost::keys::KeyPackage<C>,
) -> Result<SignatureShare<C>, Error<C>> { ) -> Result<SignatureShare<C>, Error<C>> {
if signing_package.signing_commitments().len() < key_package.min_signers as usize {
return Err(Error::IncorrectNumberOfCommitments);
}
// Validate the signer's commitment is present in the signing package // Validate the signer's commitment is present in the signing package
let commitment = signing_package let commitment = signing_package
.signing_commitments .signing_commitments

View File

@ -1,4 +1,6 @@
//! Ciphersuite-generic test functions. //! Ciphersuite-generic test functions.
#![allow(clippy::type_complexity)]
use std::{ use std::{
collections::{BTreeMap, HashMap}, collections::{BTreeMap, HashMap},
convert::TryFrom, convert::TryFrom,
@ -117,8 +119,31 @@ pub fn check_sign_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); let key_package = frost::keys::KeyPackage::try_from(v).unwrap();
key_packages.insert(k, key_package); key_packages.insert(k, key_package);
} }
// Check if it fails with not enough signers. Usually this would return an
// error before even running the signing procedure, because `KeyPackage`
// contains the correct `min_signers` value and the signing procedure checks
// if the number of shares is at least `min_signers`. To bypass the check
// and test if the protocol itself fails with not enough signers, we modify
// the `KeyPackages`s, decrementing their saved `min_signers` value before
// running the signing procedure.
let r = check_sign(
min_signers - 1,
key_packages
.iter()
.map(|(id, k)| {
// Decrement `min_signers` as explained above and use
// the updated `KeyPackage`.
let mut k = k.clone();
k.min_signers -= 1;
(*id, k)
})
.collect(),
&mut rng,
pubkeys.clone(),
);
assert_eq!(r, Err(Error::InvalidSignature));
check_sign(min_signers, key_packages, rng, pubkeys) check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
} }
/// Test FROST signing with trusted dealer fails with invalid numbers of signers. /// Test FROST signing with trusted dealer fails with invalid numbers of signers.
@ -163,7 +188,7 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
key_packages: HashMap<frost::Identifier<C>, frost::keys::KeyPackage<C>>, key_packages: HashMap<frost::Identifier<C>, frost::keys::KeyPackage<C>>,
mut rng: R, mut rng: R,
pubkey_package: frost::keys::PublicKeyPackage<C>, pubkey_package: frost::keys::PublicKeyPackage<C>,
) -> (Vec<u8>, Signature<C>, VerifyingKey<C>) { ) -> Result<(Vec<u8>, Signature<C>, VerifyingKey<C>), Error<C>> {
let mut nonces_map: HashMap<frost::Identifier<C>, frost::round1::SigningNonces<C>> = let mut nonces_map: HashMap<frost::Identifier<C>, frost::round1::SigningNonces<C>> =
HashMap::new(); HashMap::new();
let mut commitments_map: BTreeMap<frost::Identifier<C>, frost::round1::SigningCommitments<C>> = let mut commitments_map: BTreeMap<frost::Identifier<C>, frost::round1::SigningCommitments<C>> =
@ -201,11 +226,16 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
for participant_identifier in nonces_map.keys() { for participant_identifier in nonces_map.keys() {
let key_package = key_packages.get(participant_identifier).unwrap(); let key_package = key_packages.get(participant_identifier).unwrap();
let nonces_to_use = &nonces_map.get(participant_identifier).unwrap(); let nonces_to_use = nonces_map.get(participant_identifier).unwrap();
check_sign_errors(
signing_package.clone(),
nonces_to_use.clone(),
key_package.clone(),
);
// Each participant generates their signature share. // Each participant generates their signature share.
let signature_share = let signature_share = frost::round2::sign(&signing_package, nonces_to_use, key_package)?;
frost::round2::sign(&signing_package, nonces_to_use, key_package).unwrap();
signature_shares.insert(*participant_identifier, signature_share); signature_shares.insert(*participant_identifier, signature_share);
} }
@ -221,33 +251,47 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
); );
// Aggregate (also verifies the signature shares) // Aggregate (also verifies the signature shares)
let group_signature = let group_signature = frost::aggregate(&signing_package, &signature_shares, &pubkey_package)?;
frost::aggregate(&signing_package, &signature_shares, &pubkey_package).unwrap();
// Check that the threshold signature can be verified by the group public // Check that the threshold signature can be verified by the group public
// key (the verification key). // key (the verification key).
let is_signature_valid = pubkey_package pubkey_package
.group_public .group_public
.verify(message, &group_signature) .verify(message, &group_signature)?;
.is_ok();
assert!(is_signature_valid);
// Check that the threshold signature can be verified by the group public // Check that the threshold signature can be verified by the group public
// key (the verification key) from KeyPackage.group_public // key (the verification key) from KeyPackage.group_public
for (participant_identifier, _) in nonces_map.clone() { for (participant_identifier, _) in nonces_map.clone() {
let key_package = key_packages.get(&participant_identifier).unwrap(); let key_package = key_packages.get(&participant_identifier).unwrap();
assert!(key_package key_package.group_public.verify(message, &group_signature)?;
.group_public
.verify(message, &group_signature)
.is_ok());
} }
( Ok((
message.to_owned(), message.to_owned(),
group_signature, group_signature,
pubkey_package.group_public, pubkey_package.group_public,
) ))
}
fn check_sign_errors<C: Ciphersuite + PartialEq>(
signing_package: frost::SigningPackage<C>,
signing_nonces: frost::round1::SigningNonces<C>,
key_package: frost::keys::KeyPackage<C>,
) {
// Check if passing not enough commitments causes an error
let mut commitments = signing_package.signing_commitments().clone();
// Remove one commitment that's not from the key_package owner
let id = *commitments
.keys()
.find(|&&id| id != key_package.identifier)
.unwrap();
commitments.remove(&id);
let signing_package = frost::SigningPackage::new(commitments, signing_package.message());
let r = frost::round2::sign(&signing_package, &signing_nonces, &key_package);
assert_eq!(r, Err(Error::IncorrectNumberOfCommitments));
} }
fn check_aggregate_errors<C: Ciphersuite + PartialEq>( fn check_aggregate_errors<C: Ciphersuite + PartialEq>(
@ -461,7 +505,7 @@ where
let pubkeys = frost::keys::PublicKeyPackage::new(verifying_keys, group_public.unwrap()); let pubkeys = frost::keys::PublicKeyPackage::new(verifying_keys, group_public.unwrap());
// Proceed with the signing test. // Proceed with the signing test.
check_sign(min_signers, key_packages, rng, pubkeys) check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
} }
/// Check that calling dkg::part3() with distinct sets of participants fail. /// Check that calling dkg::part3() with distinct sets of participants fail.
@ -571,7 +615,7 @@ pub fn check_sign_with_dealer_and_identifiers<C: Ciphersuite, R: RngCore + Crypt
let key_package = frost::keys::KeyPackage::try_from(v).unwrap(); let key_package = frost::keys::KeyPackage::try_from(v).unwrap();
key_packages.insert(k, key_package); key_packages.insert(k, key_package);
} }
check_sign(min_signers, key_packages, rng, pubkeys) check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
} }
fn check_part2_error<C: Ciphersuite>( fn check_part2_error<C: Ciphersuite>(
@ -653,6 +697,7 @@ pub fn check_sign_with_missing_identifier<C: Ciphersuite, R: RngCore + CryptoRng
let id_1 = Identifier::<C>::try_from(1).unwrap(); let id_1 = Identifier::<C>::try_from(1).unwrap();
let id_2 = Identifier::<C>::try_from(2).unwrap(); let id_2 = Identifier::<C>::try_from(2).unwrap();
let id_3 = Identifier::<C>::try_from(3).unwrap(); let id_3 = Identifier::<C>::try_from(3).unwrap();
let id_4 = Identifier::<C>::try_from(4).unwrap();
let key_packages_inc = vec![id_1, id_2, id_3]; let key_packages_inc = vec![id_1, id_2, id_3];
for participant_identifier in key_packages_inc { for participant_identifier in key_packages_inc {
@ -666,11 +711,14 @@ pub fn check_sign_with_missing_identifier<C: Ciphersuite, R: RngCore + CryptoRng
); );
nonces_map.insert(participant_identifier, nonces); nonces_map.insert(participant_identifier, nonces);
// Participant with id_1 is excluded from the commitments_map so it is missing from the signing package // Participant with id_1 is excluded from the commitments_map so it is missing from the signing package.
// To prevent sign() from returning an error due to incorrect number of commitments,
// add the commitment under another unrelated participant.
if participant_identifier == id_1 { if participant_identifier == id_1 {
continue; commitments_map.insert(id_4, commitments);
} else {
commitments_map.insert(participant_identifier, commitments);
} }
commitments_map.insert(participant_identifier, commitments);
} }
// This is what the signature aggregator / coordinator needs to do: // This is what the signature aggregator / coordinator needs to do:
@ -690,8 +738,7 @@ pub fn check_sign_with_missing_identifier<C: Ciphersuite, R: RngCore + CryptoRng
// Each participant generates their signature share. // Each participant generates their signature share.
let signature_share = frost::round2::sign(&signing_package, nonces_to_use, key_package_1); let signature_share = frost::round2::sign(&signing_package, nonces_to_use, key_package_1);
assert!(signature_share.is_err()); assert_eq!(signature_share, Err(Error::MissingCommitment))
assert!(signature_share == Err(Error::MissingCommitment))
} }
/// Checks the signer's commitment is valid /// Checks the signer's commitment is valid

View File

@ -40,7 +40,7 @@ pub fn parse_test_vectors<C: Ciphersuite>(json_vectors: &Value) -> TestVectors<C
let message = inputs["message"].as_str().unwrap(); let message = inputs["message"].as_str().unwrap();
let message_bytes = hex::decode(message).unwrap(); let message_bytes = hex::decode(message).unwrap();
let share_polynomial_coefficients = inputs["share_polynomial_coefficients"] let share_polynomial_coefficients: Vec<_> = inputs["share_polynomial_coefficients"]
.as_array() .as_array()
.unwrap() .unwrap()
.iter() .iter()
@ -67,8 +67,14 @@ pub fn parse_test_vectors<C: Ciphersuite>(json_vectors: &Value) -> TestVectors<C
.unwrap(); .unwrap();
let signer_public = secret.into(); let signer_public = secret.into();
let key_package = let min_signers = share_polynomial_coefficients.len() + 1;
KeyPackage::<C>::new(i.try_into().unwrap(), secret, signer_public, group_public); let key_package = KeyPackage::<C>::new(
i.try_into().unwrap(),
secret,
signer_public,
group_public,
min_signers as u16,
);
key_packages.insert(*key_package.identifier(), key_package); key_packages.insert(*key_package.identifier(), key_package);
} }

View File

@ -80,7 +80,7 @@ pub fn key_package() -> KeyPackage {
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()); let serialized_element = <C as Ciphersuite>::Group::serialize(&element1());
let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap();
KeyPackage::new(identifier, signing_share, verifying_share, verifying_key) KeyPackage::new(identifier, signing_share, verifying_share, verifying_key, 2)
} }
/// Generate a sample PublicKeyPackage. /// Generate a sample PublicKeyPackage.

View File

@ -71,12 +71,14 @@ fn check_key_package_recreation() {
let signing_share = key_package.secret_share(); let signing_share = key_package.secret_share();
let verifying_share = key_package.public(); let verifying_share = key_package.public();
let verifying_key = key_package.group_public(); let verifying_key = key_package.group_public();
let min_signers = key_package.min_signers();
let new_key_package = KeyPackage::new( let new_key_package = KeyPackage::new(
*identifier, *identifier,
*signing_share, *signing_share,
*verifying_share, *verifying_share,
*verifying_key, *verifying_key,
*min_signers,
); );
assert!(key_package == new_key_package); assert!(key_package == new_key_package);

View File

@ -284,6 +284,7 @@ fn check_key_package_serialization() {
"secret_share": "498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a", "secret_share": "498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a",
"public": "5866666666666666666666666666666666666666666666666666666666666666", "public": "5866666666666666666666666666666666666666666666666666666666666666",
"group_public": "5866666666666666666666666666666666666666666666666666666666666666", "group_public": "5866666666666666666666666666666666666666666666666666666666666666",
"min_signers": 2,
"ciphersuite": "FROST(Ed25519, SHA-512)" "ciphersuite": "FROST(Ed25519, SHA-512)"
}"#; }"#;
let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap(); let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap();

View File

@ -80,7 +80,7 @@ pub fn key_package() -> KeyPackage {
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()); let serialized_element = <C as Ciphersuite>::Group::serialize(&element1());
let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap();
KeyPackage::new(identifier, signing_share, verifying_share, verifying_key) KeyPackage::new(identifier, signing_share, verifying_share, verifying_key, 2)
} }
/// Generate a sample PublicKeyPackage. /// Generate a sample PublicKeyPackage.

View File

@ -71,12 +71,14 @@ fn check_key_package_recreation() {
let signing_share = key_package.secret_share(); let signing_share = key_package.secret_share();
let verifying_share = key_package.public(); let verifying_share = key_package.public();
let verifying_key = key_package.group_public(); let verifying_key = key_package.group_public();
let min_signers = key_package.min_signers();
let new_key_package = KeyPackage::new( let new_key_package = KeyPackage::new(
*identifier, *identifier,
*signing_share, *signing_share,
*verifying_share, *verifying_share,
*verifying_key, *verifying_key,
*min_signers,
); );
assert!(key_package == new_key_package); assert!(key_package == new_key_package);

View File

@ -284,6 +284,7 @@ fn check_key_package_serialization() {
"secret_share": "4d83e51cb78150c2380ad9b3a18148166024e4c9db3cdf82466d3153aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2a00", "secret_share": "4d83e51cb78150c2380ad9b3a18148166024e4c9db3cdf82466d3153aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2a00",
"public": "14fa30f25b790898adc8d74e2c13bdfdc4397ce61cffd33ad7c2a0051e9c78874098a36c7373ea4b62c7c9563720768824bcb66e71463f6900", "public": "14fa30f25b790898adc8d74e2c13bdfdc4397ce61cffd33ad7c2a0051e9c78874098a36c7373ea4b62c7c9563720768824bcb66e71463f6900",
"group_public": "14fa30f25b790898adc8d74e2c13bdfdc4397ce61cffd33ad7c2a0051e9c78874098a36c7373ea4b62c7c9563720768824bcb66e71463f6900", "group_public": "14fa30f25b790898adc8d74e2c13bdfdc4397ce61cffd33ad7c2a0051e9c78874098a36c7373ea4b62c7c9563720768824bcb66e71463f6900",
"min_signers": 2,
"ciphersuite": "FROST(Ed448, SHAKE256)" "ciphersuite": "FROST(Ed448, SHAKE256)"
}"#; }"#;
let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap(); let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap();

View File

@ -80,7 +80,7 @@ pub fn key_package() -> KeyPackage {
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()); let serialized_element = <C as Ciphersuite>::Group::serialize(&element1());
let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap();
KeyPackage::new(identifier, signing_share, verifying_share, verifying_key) KeyPackage::new(identifier, signing_share, verifying_share, verifying_key, 2)
} }
/// Generate a sample PublicKeyPackage. /// Generate a sample PublicKeyPackage.

View File

@ -71,12 +71,14 @@ fn check_key_package_recreation() {
let signing_share = key_package.secret_share(); let signing_share = key_package.secret_share();
let verifying_share = key_package.public(); let verifying_share = key_package.public();
let verifying_key = key_package.group_public(); let verifying_key = key_package.group_public();
let min_signers = key_package.min_signers();
let new_key_package = KeyPackage::new( let new_key_package = KeyPackage::new(
*identifier, *identifier,
*signing_share, *signing_share,
*verifying_share, *verifying_share,
*verifying_key, *verifying_key,
*min_signers,
); );
assert!(key_package == new_key_package); assert!(key_package == new_key_package);

View File

@ -284,6 +284,7 @@ fn check_key_package_serialization() {
"secret_share": "aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1", "secret_share": "aaaaaaaa00000000aaaaaaaaaaaaaaaa7def51c91a0fbf034d26872ca84218e1",
"public": "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", "public": "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"group_public": "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", "group_public": "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
"min_signers": 2,
"ciphersuite": "FROST(P-256, SHA-256)" "ciphersuite": "FROST(P-256, SHA-256)"
}"#; }"#;
let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap(); let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap();

View File

@ -72,6 +72,7 @@ impl<C: Ciphersuite> Randomize<C> for KeyPackage<C> {
randomized_signing_share, randomized_signing_share,
randomized_verifying_share, randomized_verifying_share,
randomized_params.randomized_verifying_key, randomized_params.randomized_verifying_key,
*self.min_signers(),
); );
Ok(randomized_key_package) Ok(randomized_key_package)
} }

View File

@ -80,7 +80,7 @@ pub fn key_package() -> KeyPackage {
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()); let serialized_element = <C as Ciphersuite>::Group::serialize(&element1());
let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap();
KeyPackage::new(identifier, signing_share, verifying_share, verifying_key) KeyPackage::new(identifier, signing_share, verifying_share, verifying_key, 2)
} }
/// Generate a sample PublicKeyPackage. /// Generate a sample PublicKeyPackage.

View File

@ -71,12 +71,14 @@ fn check_key_package_recreation() {
let signing_share = key_package.secret_share(); let signing_share = key_package.secret_share();
let verifying_share = key_package.public(); let verifying_share = key_package.public();
let verifying_key = key_package.group_public(); let verifying_key = key_package.group_public();
let min_signers = key_package.min_signers();
let new_key_package = KeyPackage::new( let new_key_package = KeyPackage::new(
*identifier, *identifier,
*signing_share, *signing_share,
*verifying_share, *verifying_share,
*verifying_key, *verifying_key,
*min_signers,
); );
assert!(key_package == new_key_package); assert!(key_package == new_key_package);

View File

@ -284,6 +284,7 @@ fn check_key_package_serialization() {
"secret_share": "498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a", "secret_share": "498d4e9311420c903913a56c94a694b8aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0a",
"public": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", "public": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76",
"group_public": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76", "group_public": "e2f2ae0a6abc4e71a884a961c500515f58e30b6aa582dd8db6a65945e08d2d76",
"min_signers": 2,
"ciphersuite": "FROST(ristretto255, SHA-512)" "ciphersuite": "FROST(ristretto255, SHA-512)"
}"#; }"#;
let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap(); let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap();

View File

@ -80,7 +80,7 @@ pub fn key_package() -> KeyPackage {
let serialized_element = <C as Ciphersuite>::Group::serialize(&element1()); let serialized_element = <C as Ciphersuite>::Group::serialize(&element1());
let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap(); let verifying_key = VerifyingKey::deserialize(serialized_element).unwrap();
KeyPackage::new(identifier, signing_share, verifying_share, verifying_key) KeyPackage::new(identifier, signing_share, verifying_share, verifying_key, 2)
} }
/// Generate a sample PublicKeyPackage. /// Generate a sample PublicKeyPackage.

View File

@ -71,12 +71,14 @@ fn check_key_package_recreation() {
let signing_share = key_package.secret_share(); let signing_share = key_package.secret_share();
let verifying_share = key_package.public(); let verifying_share = key_package.public();
let verifying_key = key_package.group_public(); let verifying_key = key_package.group_public();
let min_signers = key_package.min_signers();
let new_key_package = KeyPackage::new( let new_key_package = KeyPackage::new(
*identifier, *identifier,
*signing_share, *signing_share,
*verifying_share, *verifying_share,
*verifying_key, *verifying_key,
*min_signers,
); );
assert!(key_package == new_key_package); assert!(key_package == new_key_package);

View File

@ -284,6 +284,7 @@ fn check_key_package_serialization() {
"secret_share": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b81", "secret_share": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa9d1c9e899ca306ad27fe1945de0242b81",
"public": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "public": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"group_public": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", "group_public": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
"min_signers": 2,
"ciphersuite": "FROST(secp256k1, SHA-256)" "ciphersuite": "FROST(secp256k1, SHA-256)"
}"#; }"#;
let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap(); let decoded_key_package: KeyPackage = serde_json::from_str(json).unwrap();