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

Add frost-secp256k1-tr crate (BIP340/BIP341) [moved] #730

Merged
merged 14 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"frost-p256",
"frost-ristretto255",
"frost-secp256k1",
"frost-secp256k1-tr",
"frost-rerandomized",
"gencode"
]
20 changes: 14 additions & 6 deletions frost-core/src/batch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use crate::{scalar_mul::VartimeMultiscalarMul, Ciphersuite, Element, *};
pub struct Item<C: Ciphersuite> {
vk: VerifyingKey<C>,
sig: Signature<C>,
sig_params: C::SigningParameters,
c: Challenge<C>,
}

Expand All @@ -33,10 +34,15 @@ where
where
M: AsRef<[u8]>,
{
// Compute c now to avoid dependency on the msg lifetime.
let c = crate::challenge(&sig.R, &vk, msg.as_ref())?;

Ok(Self { vk, sig, c })
let sig_target = SigningTarget::from_message(msg);
let c = <C>::challenge(&sig.R, &vk, &sig_target)?;

Ok(Self {
vk,
sig,
sig_params: sig_target.sig_params,
c,
})
}
}

Expand All @@ -52,7 +58,8 @@ where
/// requires borrowing the message data, the `Item` type is unlinked
/// from the lifetime of the message.
pub fn verify_single(self) -> Result<(), Error<C>> {
self.vk.verify_prehashed(self.c, &self.sig)
self.vk
.verify_prehashed(self.c, &self.sig, &self.sig_params)
}
}

Expand Down Expand Up @@ -121,6 +128,7 @@ where
for item in self.signatures.iter() {
let z = item.sig.z;
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);

Expand All @@ -131,7 +139,7 @@ where
Rs.push(R);

VK_coeffs.push(<<C::Group as Group>::Field>::zero() + (blind * item.c.0));
VKs.push(item.vk.to_element());
VKs.push(vk);
}

let scalars = core::iter::once(&P_coeff_acc)
Expand Down
10 changes: 10 additions & 0 deletions frost-core/src/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@
pub(crate) fn from_coefficients(coefficients: &[Scalar<C>], peer: Identifier<C>) -> Self {
Self::new(evaluate_polynomial(peer, coefficients))
}

/// Returns negated SigningShare
pub fn negate(&mut self) {
self.0 .0 = <<C::Group as Group>::Field>::negate(&self.to_scalar());
}
}

impl<C> Debug for SigningShare<C>
Expand Down Expand Up @@ -328,7 +333,7 @@
}

/// Returns VerifiableSecretSharingCommitment from a iterator of serialized
/// CoefficientCommitments (e.g. a Vec<Vec<u8>>).

Check warning on line 336 in frost-core/src/keys.rs

View workflow job for this annotation

GitHub Actions / Check Rust doc

unclosed HTML tag `u8`
pub fn deserialize<I, V>(serialized_coefficient_commitments: I) -> Result<Self, Error<C>>
where
I: IntoIterator<Item = V>,
Expand Down Expand Up @@ -630,6 +635,11 @@
min_signers,
}
}

/// Negate `SigningShare`.
pub fn negate_signing_share(&mut self) {
self.signing_share.negate();
}
}

#[cfg(feature = "serialization")]
Expand Down
45 changes: 27 additions & 18 deletions frost-core/src/keys/dkg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use rand_core::{CryptoRng, RngCore};

use crate::{
Challenge, Ciphersuite, Element, Error, Field, Group, Header, Identifier, Scalar, Signature,
SigningKey, VerifyingKey,
SigningKey,
};

#[cfg(feature = "serialization")]
Expand Down Expand Up @@ -322,7 +322,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>,
) -> Result<Challenge<C>, Error<C>>
where
Expand All @@ -331,7 +331,7 @@ where
let mut preimage = vec![];

preimage.extend_from_slice(identifier.serialize().as_ref());
preimage.extend_from_slice(<C::Group>::serialize(&verifying_key.to_element())?.as_ref());
preimage.extend_from_slice(<C::Group>::serialize(verifying_key)?.as_ref());
preimage.extend_from_slice(<C::Group>::serialize(R)?.as_ref());

Ok(Challenge(
Expand All @@ -354,13 +354,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)?;
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)?;
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 })
}

Expand All @@ -380,9 +390,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)?;
if R_ell != <C::Group>::generator() * mu_ell - phi_ell0.to_element() * c_ell.0 {

if R_ell != <C::Group>::generator() * mu_ell - phi_ell0 * c_ell.0 {
return Err(Error::InvalidProofOfKnowledge { culprit: ell });
}
Ok(())
Expand Down Expand Up @@ -549,16 +562,12 @@ pub fn part3<C: Ciphersuite>(
&round2_secret_package.commitment,
)))
.collect();
let public_key_package = PublicKeyPackage::from_dkg_commitments(&commitments)?;

let key_package = KeyPackage {
header: Header::default(),
identifier: round2_secret_package.identifier,
C::dkg_output_finalize(
round2_secret_package.identifier,
commitments,
signing_share,
verifying_share,
verifying_key: public_key_package.verifying_key,
min_signers: round2_secret_package.min_signers,
};

Ok((key_package, public_key_package))
round2_secret_package.min_signers,
)
}
Loading
Loading