Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cover taproot-tweaked signing with integration tests #4

Merged
merged 4 commits into from
Mar 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frost-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ where
// Verify the aggregate signature
let verification_result = pubkeys
.verifying_key
.verify(signing_package.message(), &signature);
.verify(signing_package.sig_target.clone(), &signature);

// Only if the verification of the aggregate signature failed; verify each share to find the cheater.
// This approach is more efficient since we don't need to verify all shares
Expand Down
38 changes: 25 additions & 13 deletions frost-core/src/tests/ciphersuite_generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use std::{collections::BTreeMap, convert::TryFrom};

use crate as frost;
use crate::{
keys::PublicKeyPackage, Error, Field, Group, Identifier, Signature, SigningKey, VerifyingKey,
keys::PublicKeyPackage, Error, Field, Group, Identifier, Signature, SigningKey, SigningTarget,
VerifyingKey,
};
use rand_core::{CryptoRng, RngCore};

Expand Down Expand Up @@ -100,7 +101,8 @@ pub fn check_share_generation_fails_with_invalid_signers<C: Ciphersuite, R: RngC
/// Test FROST signing with trusted dealer with a Ciphersuite.
pub fn check_sign_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
mut rng: R,
) -> (Vec<u8>, Signature<C>, VerifyingKey<C>) {
signing_target: SigningTarget<C>,
) -> (SigningTarget<C>, Signature<C>, VerifyingKey<C>) {
////////////////////////////////////////////////////////////////////////////
// Key generation
////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -144,10 +146,11 @@ pub fn check_sign_with_dealer<C: Ciphersuite, R: RngCore + CryptoRng>(
.collect(),
&mut rng,
pubkeys.clone(),
signing_target.clone(),
);
assert_eq!(r, Err(Error::InvalidSignature));

check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
check_sign(min_signers, key_packages, rng, pubkeys, signing_target).unwrap()
}

/// Test FROST signing with trusted dealer fails with invalid numbers of signers.
Expand Down Expand Up @@ -192,7 +195,8 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
key_packages: BTreeMap<frost::Identifier<C>, frost::keys::KeyPackage<C>>,
mut rng: R,
pubkey_package: PublicKeyPackage<C>,
) -> Result<(Vec<u8>, Signature<C>, VerifyingKey<C>), Error<C>> {
signing_target: SigningTarget<C>,
) -> Result<(SigningTarget<C>, Signature<C>, VerifyingKey<C>), Error<C>> {
let mut nonces_map: BTreeMap<frost::Identifier<C>, frost::round1::SigningNonces<C>> =
BTreeMap::new();
let mut commitments_map: BTreeMap<frost::Identifier<C>, frost::round1::SigningCommitments<C>> =
Expand Down Expand Up @@ -220,8 +224,7 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
// - decide what message to sign
// - take one (unused) commitment per signing participant
let mut signature_shares = BTreeMap::new();
let message = "message to sign".as_bytes();
let signing_package = frost::SigningPackage::new(commitments_map, message);
let signing_package = frost::SigningPackage::new(commitments_map, signing_target.clone());

////////////////////////////////////////////////////////////////////////////
// Round 2: each participant generates their signature share
Expand Down Expand Up @@ -268,7 +271,14 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
// key (the verification key).
pubkey_package
.verifying_key
.verify(message, &group_signature)?;
.verify(signing_target.clone(), &group_signature)?;

// Check that the effective verifying key can be verified against the raw message,
// without exposing the SigningParameters.
pubkey_package
.verifying_key
.effective_key(signing_target.sig_params())
.verify(signing_target.message(), &group_signature)?;

// Check that the threshold signature can be verified by the group public
// key (the verification key) from KeyPackage.verifying_key
Expand All @@ -277,11 +287,11 @@ pub fn check_sign<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(

key_package
.verifying_key
.verify(message, &group_signature)?;
.verify(signing_target.clone(), &group_signature)?;
}

Ok((
message.to_owned(),
signing_target,
group_signature,
pubkey_package.verifying_key,
))
Expand Down Expand Up @@ -363,7 +373,8 @@ fn check_aggregate_invalid_share_identifier_for_verifying_shares<C: Ciphersuite
/// Test FROST signing with DKG with a Ciphersuite.
pub fn check_sign_with_dkg<C: Ciphersuite + PartialEq, R: RngCore + CryptoRng>(
mut rng: R,
) -> (Vec<u8>, Signature<C>, VerifyingKey<C>)
signing_target: SigningTarget<C>,
) -> (SigningTarget<C>, Signature<C>, VerifyingKey<C>)
where
C::Group: std::cmp::PartialEq,
{
Expand Down Expand Up @@ -520,7 +531,7 @@ where
let pubkeys = frost::keys::PublicKeyPackage::new(verifying_keys, verifying_key.unwrap());

// Proceed with the signing test.
check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
check_sign(min_signers, key_packages, rng, pubkeys, signing_target).unwrap()
}

/// Check that calling dkg::part3() with distinct sets of participants fail.
Expand Down Expand Up @@ -564,7 +575,8 @@ fn check_part3_different_participants<C: Ciphersuite>(
/// Identifiers.
pub fn check_sign_with_dealer_and_identifiers<C: Ciphersuite, R: RngCore + CryptoRng>(
mut rng: R,
) -> (Vec<u8>, Signature<C>, VerifyingKey<C>) {
signing_target: SigningTarget<C>,
) -> (SigningTarget<C>, Signature<C>, VerifyingKey<C>) {
// Check error cases first
// Check repeated identifiers

Expand Down Expand Up @@ -630,7 +642,7 @@ pub fn check_sign_with_dealer_and_identifiers<C: Ciphersuite, R: RngCore + Crypt
let key_package = frost::keys::KeyPackage::try_from(v).unwrap();
key_packages.insert(k, key_package);
}
check_sign(min_signers, key_packages, rng, pubkeys).unwrap()
check_sign(min_signers, key_packages, rng, pubkeys, signing_target).unwrap()
}

fn check_part2_error<C: Ciphersuite>(
Expand Down
3 changes: 1 addition & 2 deletions frost-core/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,6 @@ pub trait Ciphersuite: Copy + Clone + PartialEq + Debug {
signature: &Signature<Self>,
public_key: &VerifyingKey<Self>,
) -> Result<(), Error<Self>> {
let sig_target = sig_target.into();
let c = <Self>::challenge(&signature.R, public_key, sig_target);

public_key.verify_prehashed(c, signature, &sig_target.sig_params)
Expand Down Expand Up @@ -394,6 +393,6 @@ pub trait Ciphersuite: Copy + Clone + PartialEq + Debug {
_verifying_key: &VerifyingKey<Self>,
_sig_params: &Self::SigningParameters,
) -> <Self::Group as Group>::Element {
verifying_share.to_element()
verifying_share.0
}
}
12 changes: 9 additions & 3 deletions frost-ed25519/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ fn check_zero_key_fails() {
fn check_sign_with_dkg() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ed25519Sha512, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ed25519Sha512, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -68,7 +71,10 @@ fn check_rts() {
fn check_sign_with_dealer() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ed25519Sha512, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ed25519Sha512, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -220,7 +226,7 @@ fn check_sign_with_dealer_and_identifiers() {
frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<
Ed25519Sha512,
_,
>(rng);
>(rng, b"message".into());
}

#[test]
Expand Down
10 changes: 6 additions & 4 deletions frost-ed25519/tests/interoperability_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ fn check_interoperability_in_sign_with_dkg() {
// and the interoperability check. A smaller number of iterations is used
// because DKG takes longer and otherwise the test would be too slow.
for _ in 0..32 {
let (msg, group_signature, group_pubkey) =
let (target, group_signature, group_pubkey) =
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ed25519Sha512, _>(
rng.clone(),
b"message".into(),
);

helpers::verify_signature(&msg, group_signature, group_pubkey);
helpers::verify_signature(target.message(), group_signature, group_pubkey);
}
}

Expand All @@ -28,13 +29,14 @@ fn check_interoperability_in_sign_with_dealer() {
// Test with multiple keys/signatures to better exercise the key generation
// and the interoperability check.
for _ in 0..256 {
let (msg, group_signature, group_pubkey) =
let (target, group_signature, group_pubkey) =
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ed25519Sha512, _>(
rng.clone(),
b"message".into(),
);

// Check that the threshold signature can be verified by the `ed25519_dalek` crate
// public key (interoperability test)
helpers::verify_signature(&msg, group_signature, group_pubkey);
helpers::verify_signature(target.message(), group_signature, group_pubkey);
}
}
12 changes: 9 additions & 3 deletions frost-ed448/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ fn check_zero_key_fails() {
fn check_sign_with_dkg() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ed448Shake256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ed448Shake256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -68,7 +71,10 @@ fn check_rts() {
fn check_sign_with_dealer() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ed448Shake256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ed448Shake256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -220,7 +226,7 @@ fn check_sign_with_dealer_and_identifiers() {
frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<
Ed448Shake256,
_,
>(rng);
>(rng, b"message".into());
}

#[test]
Expand Down
11 changes: 9 additions & 2 deletions frost-p256/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ fn check_zero_key_fails() {
fn check_sign_with_dkg() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<P256Sha256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<P256Sha256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -68,7 +71,10 @@ fn check_rts() {
fn check_sign_with_dealer() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<P256Sha256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<P256Sha256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -217,6 +223,7 @@ fn check_sign_with_dealer_and_identifiers() {

frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<P256Sha256, _>(
rng,
b"message".into(),
);
}

Expand Down
12 changes: 9 additions & 3 deletions frost-ristretto255/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ fn check_zero_key_fails() {
fn check_sign_with_dkg() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ristretto255Sha512, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Ristretto255Sha512, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -68,7 +71,10 @@ fn check_rts() {
fn check_sign_with_dealer() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ristretto255Sha512, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Ristretto255Sha512, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -220,7 +226,7 @@ fn check_sign_with_dealer_and_identifiers() {
frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<
Ristretto255Sha512,
_,
>(rng);
>(rng, b"message".into());
}

#[test]
Expand Down
12 changes: 9 additions & 3 deletions frost-secp256k1-tr/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ fn check_zero_key_fails() {
fn check_sign_with_dkg() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Secp256K1Sha256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Secp256K1Sha256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -68,7 +71,10 @@ fn check_rts() {
fn check_sign_with_dealer() {
let rng = thread_rng();

frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Secp256K1Sha256, _>(rng);
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Secp256K1Sha256, _>(
rng,
b"message".into(),
);
}

#[test]
Expand Down Expand Up @@ -220,7 +226,7 @@ fn check_sign_with_dealer_and_identifiers() {
frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<
Secp256K1Sha256,
_,
>(rng);
>(rng, b"message".into());
}

#[test]
Expand Down
Loading