ensure taproot signatures always use even nonce points

BIP340 signatures are usually represented with x-only (even parity)
nonce points. As a step towards normalizing this for the frost-secp256k1-tr
crate, we should ensure all Signature struct instances always use the
effective nonce point, including the DKG proof-of-knowledge.
This commit is contained in:
conduition 2024-04-24 16:55:22 +00:00 committed by zebra-lucky
parent 20c2c98a93
commit 15688ab30a
9 changed files with 35 additions and 30 deletions

View File

@ -126,7 +126,7 @@ where
for item in self.signatures.iter() {
let z = item.sig.z;
let R = <C>::effective_nonce_element(item.sig.R);
let R = item.sig.R;
let vk = <C>::effective_pubkey_element(&item.vk, &item.sig_params);
let blind = <<C::Group as Group>::Field>::random(&mut rng);

View File

@ -36,7 +36,7 @@ use rand_core::{CryptoRng, RngCore};
use crate::{
Challenge, Ciphersuite, Element, Error, Field, Group, Header, Identifier, Scalar, Signature,
SigningKey, VerifyingKey,
SigningKey,
};
use super::{
@ -314,7 +314,7 @@ pub fn part1<C: Ciphersuite, R: RngCore + CryptoRng>(
/// Generates the challenge for the proof of knowledge to a secret for the DKG.
fn challenge<C>(
identifier: Identifier<C>,
verifying_key: &VerifyingKey<C>,
verifying_key: &Element<C>,
R: &Element<C>,
) -> Option<Challenge<C>>
where
@ -323,7 +323,7 @@ where
let mut preimage = vec![];
preimage.extend_from_slice(identifier.serialize().as_ref());
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key.element).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key).as_ref());
preimage.extend_from_slice(<C::Group>::serialize(R).as_ref());
Some(Challenge(C::HDKG(&preimage[..])?))
@ -344,14 +344,23 @@ pub(crate) fn compute_proof_of_knowledge<C: Ciphersuite, R: RngCore + CryptoRng>
// > a_{i0} by calculating σ_i = (R_i, μ_i), such that k ← Z_q, R_i = g^k,
// > c_i = H(i, Φ, g^{a_{i0}} , R_i), μ_i = k + a_{i0} · c_i, with Φ being
// > a context string to prevent replay attacks.
let k = <<C::Group as Group>::Field>::random(&mut rng);
let R_i = <C::Group>::generator() * k;
let c_i = challenge::<C>(identifier, &commitment.verifying_key()?, &R_i)
.ok_or(Error::DKGNotSupported)?;
let mut k = <<C::Group as Group>::Field>::random(&mut rng);
let mut R_i = <C::Group>::generator() * k;
k = <C>::effective_nonce_secret(k, &R_i);
R_i = <C>::effective_nonce_element(R_i);
let verifying_key = commitment.verifying_key()?;
let sig_params = Default::default();
let phi_ell0 = <C>::effective_pubkey_element(&verifying_key, &sig_params);
let c_i = challenge::<C>(identifier, &phi_ell0, &R_i).ok_or(Error::DKGNotSupported)?;
let a_i0 = *coefficients
.first()
.expect("coefficients must have at least one element");
let mu_i = k + a_i0 * c_i.0;
let a_i0_effective = <C>::effective_secret_key(a_i0, &verifying_key, &sig_params);
let mu_i = k + a_i0_effective * c_i.0;
Ok(Signature { R: R_i, z: mu_i })
}
@ -371,9 +380,12 @@ pub(crate) fn verify_proof_of_knowledge<C: Ciphersuite>(
let ell = identifier;
let R_ell = proof_of_knowledge.R;
let mu_ell = proof_of_knowledge.z;
let phi_ell0 = commitment.verifying_key()?;
let verifying_key = commitment.verifying_key()?;
let phi_ell0 = <C>::effective_pubkey_element(&verifying_key, &Default::default());
let c_ell = challenge::<C>(ell, &phi_ell0, &R_ell).ok_or(Error::DKGNotSupported)?;
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0.element * c_ell.0 {
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0 * c_ell.0 {
return Err(Error::InvalidProofOfKnowledge { culprit: ell });
}
Ok(())

View File

@ -623,6 +623,7 @@ where
// Compute the group commitment from signing commitments produced in round one.
let group_commitment = compute_group_commitment(signing_package, &binding_factor_list)?;
let R = <C>::effective_nonce_element(group_commitment.0);
// The aggregation of the signature shares by summing them up, resulting in
// a plain Schnorr signature.
@ -636,12 +637,8 @@ where
z = z + signature_share.share;
}
let signature: Signature<C> = <C>::aggregate_sig_finalize(
z,
group_commitment.0,
&pubkeys.verifying_key,
&signing_package.sig_target,
);
let signature: Signature<C> =
<C>::aggregate_sig_finalize(z, R, &pubkeys.verifying_key, &signing_package.sig_target);
// Verify the aggregate signature
let verification_result = pubkeys
@ -654,11 +651,7 @@ where
#[cfg(feature = "cheater-detection")]
if let Err(err) = verification_result {
// Compute the per-message challenge.
let challenge = <C>::challenge(
&group_commitment.0,
&pubkeys.verifying_key,
&signing_package.sig_target,
);
let challenge = <C>::challenge(&R, &pubkeys.verifying_key, &signing_package.sig_target);
// Verify the signature shares.
for (signature_share_identifier, signature_share) in signature_shares {

View File

@ -58,8 +58,9 @@ where
let secret = <C>::effective_secret_key(self.scalar, &public, &sig_target.sig_params);
let mut k = random_nonzero::<C, R>(&mut rng);
let R = <C::Group>::generator() * k;
let mut R = <C::Group>::generator() * k;
k = <C>::effective_nonce_secret(k, &R);
R = <C>::effective_nonce_element(R);
// Generate Schnorr challenge
let c: Challenge<C> = <C>::challenge(&R, &public, &sig_target);

View File

@ -76,7 +76,7 @@ where
// h * ( z * B - c * A - R) == 0
//
// where h is the cofactor
let R = C::effective_nonce_element(signature.R);
let R = signature.R;
let vk = C::effective_pubkey_element(&self, sig_params);
let zB = C::Group::generator() * signature.z;

View File

@ -389,7 +389,6 @@ impl Ciphersuite for Secp256K1Sha256 {
} else {
k + (c * secret)
};
Signature::new(R, z)
}

View File

@ -1104,6 +1104,6 @@
]
},
"final_output": {
"sig": "0354997f922511dba38d16973092a331f4039477bf4a2d77b438a317862795b26793c1a85a62387eabeb5073b01e63afea1c4755b4db6ad5c66758b3c05c76d67a"
"sig": "0254997f922511dba38d16973092a331f4039477bf4a2d77b438a317862795b26793c1a85a62387eabeb5073b01e63afea1c4755b4db6ad5c66758b3c05c76d67a"
}
}

View File

@ -72,6 +72,6 @@
]
},
"final_output": {
"sig": "030c776a9516a77808b70a31e74f1464814a6fcf897fb3a6bd84c7a9a9a7a5bcb8d8bfc2b385379c093bcc0579abc5f6f696e8f2c0c01f28ff7b5ef55397fc3c9a"
"sig": "020c776a9516a77808b70a31e74f1464814a6fcf897fb3a6bd84c7a9a9a7a5bcb8d8bfc2b385379c093bcc0579abc5f6f696e8f2c0c01f28ff7b5ef55397fc3c9a"
}
}

View File

@ -13,7 +13,7 @@
"signing_key": "68e3f6904c6043973515a36bf7801a71597da35733f21305d75a5234f06e4529",
"coefficient": "25d2d840a3e2718a431ec69e14ee8a015b000d43c7a9868060f01d5aa52a19d1",
"vss_commitments": ["03e7ba4acb164d2bd5eba4f47b3a788109ddb3f88f1181792424fa332123a25ea8", "037495e920a1f032916193aa80ea97a4c3a611dec9ab47ccc969deb664f5f88bbe"],
"proof_of_knowledge": "03c5e534b1770fc7517983df70823c8a1c879cd9aed515437bdad242cfbdab5e82b0a92d1d6e57e421cbd75159b89d2508c774753476110250fabfa97ff667254d",
"proof_of_knowledge": "026689a8d414eb4961308e21f8caa1045236efded4f3de9209dc07547e88be3b42e192de9bed27fb78a7a4d4e35a0422f11f52631b8e66d69e609398eaff2770b8",
"signing_shares": {
"2": "1dd3cb3e2370e6af22917415f0ad584514807b58b3cc40d2230a26e115f02771",
"3": "dd25ee86acd01f996618aa0d1153f5e8fbc929a8e8a18b8f0a15f91d087217e2"
@ -26,7 +26,7 @@
"signing_key": "2619be8223b23e0453ddc630a4d164e81f7d8a9e07af33c4d4d02190df8bec13",
"coefficient": "f7ba0cbbffbea8aaceb3ade54bdbf35bafb1cda15b65ad490e0c63dd069a7c9f",
"vss_commitments": ["03ef10370a008cd95e179dc51e2cb7828f30b72d254e5166484f927c84ab326582", "022ce0dac0db217ba326fbbe3e6132d45e2a4bfa0a0c3790d91eacce9a1c2d6a10"],
"proof_of_knowledge": "038ef8fa5a833beb3fb0d83907de2ac3cad158927afc04739f5d52ae50681874a6d43da5d6985bc1190d649342cc3999b30b15e57f177f59cbf2d21a64d6b313e2",
"proof_of_knowledge": "0219df66bda7724ccfa6a5ea76aac9cc167880d55717fe6887b89aeea94408cc9ce47b65a55f9d00479e9d3ea2c7402e81803e2e724d45d70c2cb93e3b0deb5f78",
"signing_shares": {
"1": "b489a711942526abbb5330a8215d2e740f7dbddec3452006993a8cea3ac278cb",
"3": "20255dc07b1fb78bdf90bd85fd2389c988c8250faee11826656a09142fa9fc97"
@ -39,7 +39,7 @@
"signing_key": "9a267f4cde8087a6eca0969425846209b41b515b73195ebbeeef8a991103f1ec",
"coefficient": "42ff6f39ce4f97f279781378ebcf93df47add84d75882cd31b266e83f76e25f6",
"vss_commitments": ["02da186c3863c5600b471a2799cb6f15ae4d8315a2f225c177798880e75ac820a0", "03e6a36e7fa4b117c1aa428886672e3a35d926bb4c585a9b07d8ee9a3387420067"],
"proof_of_knowledge": "03705c01e6fad6abac2f06211948d93a134c0beb00e98d7e7dc772f166acf1b3c99a674f3d712ebd7e421e59e90310facefcf04a7e7134b0f92f34d0b23afa375e",
"proof_of_knowledge": "026e115d9e63fd15d432b380ccf1ec4ed03340fcf96caeae8985aedb5f905b1a65dc422ffe5878988fbbc55454857736c7755d9c8f5ee6822c8833ea21d54dba36",
"signing_shares": {
"1": "da5c7f5238079835fe71f746364bb8756a7dcb228aeea686fa2aaa44dfec929c",
"2": "0d47e4b622ee3804bff8cfe088653efefe865cce0c065aecbf7e318182b89e2d"