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:
parent
20c2c98a93
commit
15688ab30a
|
@ -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);
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -389,7 +389,6 @@ impl Ciphersuite for Secp256K1Sha256 {
|
|||
} else {
|
||||
k + (c * secret)
|
||||
};
|
||||
|
||||
Signature::new(R, z)
|
||||
}
|
||||
|
||||
|
|
|
@ -1104,6 +1104,6 @@
|
|||
]
|
||||
},
|
||||
"final_output": {
|
||||
"sig": "0354997f922511dba38d16973092a331f4039477bf4a2d77b438a317862795b26793c1a85a62387eabeb5073b01e63afea1c4755b4db6ad5c66758b3c05c76d67a"
|
||||
"sig": "0254997f922511dba38d16973092a331f4039477bf4a2d77b438a317862795b26793c1a85a62387eabeb5073b01e63afea1c4755b4db6ad5c66758b3c05c76d67a"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,6 +72,6 @@
|
|||
]
|
||||
},
|
||||
"final_output": {
|
||||
"sig": "030c776a9516a77808b70a31e74f1464814a6fcf897fb3a6bd84c7a9a9a7a5bcb8d8bfc2b385379c093bcc0579abc5f6f696e8f2c0c01f28ff7b5ef55397fc3c9a"
|
||||
"sig": "020c776a9516a77808b70a31e74f1464814a6fcf897fb3a6bd84c7a9a9a7a5bcb8d8bfc2b385379c093bcc0579abc5f6f696e8f2c0c01f28ff7b5ef55397fc3c9a"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue