add integration tests to cover taproot-tweaked signing
This commit is contained in:
parent
5d2d683e1d
commit
20c2c98a93
|
@ -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};
|
||||
|
||||
|
@ -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
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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.
|
||||
|
@ -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>> =
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
))
|
||||
|
@ -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,
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
@ -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>(
|
||||
|
|
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
|
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
use frost_secp256k1_tr::*;
|
||||
use rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn check_tweaked_signing_key() {
|
||||
let signing_key = SigningKey::deserialize([0xAA; 32]).unwrap();
|
||||
let untweaked_verifying_key = VerifyingKey::from(signing_key);
|
||||
|
||||
let mut rng = rand::thread_rng();
|
||||
let message = b"message";
|
||||
|
||||
let untweaked_signature = signing_key.sign(&mut rng, &message);
|
||||
|
||||
untweaked_verifying_key
|
||||
.verify(&message, &untweaked_signature)
|
||||
.expect("untweaked signature should be valid under untweaked verifying key");
|
||||
|
||||
let signing_target = SigningTarget::new(
|
||||
&message,
|
||||
SigningParameters {
|
||||
tapscript_merkle_root: Some(vec![]),
|
||||
},
|
||||
);
|
||||
|
||||
let tweaked_signature = signing_key.sign(&mut rng, signing_target.clone());
|
||||
|
||||
untweaked_verifying_key
|
||||
.verify(&message, &tweaked_signature)
|
||||
.expect_err("tweaked signature should not be valid under untweaked verifying key");
|
||||
|
||||
let tweaked_verifying_key = untweaked_verifying_key.effective_key(signing_target.sig_params());
|
||||
tweaked_verifying_key
|
||||
.verify(&message, &tweaked_signature)
|
||||
.expect("tweaked signature should be valid under tweaked verifying key");
|
||||
|
||||
untweaked_verifying_key
|
||||
.verify(signing_target.clone(), &tweaked_signature)
|
||||
.expect(
|
||||
"tweaked signature should be valid under untweaked verifying key\
|
||||
when signing params are provided",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_tweaked_sign_with_dkg() {
|
||||
let rng = thread_rng();
|
||||
|
||||
frost_core::tests::ciphersuite_generic::check_sign_with_dkg::<Secp256K1Sha256, _>(
|
||||
rng,
|
||||
SigningTarget::new(
|
||||
b"message",
|
||||
SigningParameters {
|
||||
tapscript_merkle_root: Some(vec![]),
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn check_tweaked_sign_with_dealer() {
|
||||
let rng = thread_rng();
|
||||
|
||||
frost_core::tests::ciphersuite_generic::check_sign_with_dealer::<Secp256K1Sha256, _>(
|
||||
rng,
|
||||
SigningTarget::new(
|
||||
b"message",
|
||||
SigningParameters {
|
||||
tapscript_merkle_root: Some(vec![]),
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_tweaked_sign_with_dealer_and_identifiers() {
|
||||
let rng = thread_rng();
|
||||
|
||||
frost_core::tests::ciphersuite_generic::check_sign_with_dealer_and_identifiers::<
|
||||
Secp256K1Sha256,
|
||||
_,
|
||||
>(
|
||||
rng,
|
||||
SigningTarget::new(
|
||||
b"message",
|
||||
SigningParameters {
|
||||
tapscript_merkle_root: Some(vec![]),
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
|
@ -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]
|
||||
|
@ -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]
|
||||
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue