Make verification per-ciphersuite (#103)

* add VerifySignature method to Ciphersuite with default implementation

* VerifySignature -> verify_signature; fix comment

* add comment to verify_signature about batch verification

* fix batch support after rebase

* derive Eq when possible and disable clippy::derive_partial_eq_without_eq which is emitting false positives

* Make verify_prehashed() an associated method of the generic VerifyingKey

Co-authored-by: Deirdre Connolly <durumcrustulum@gmail.com>
This commit is contained in:
Conrado Gouvea 2022-09-02 23:26:41 -03:00 committed by GitHub
parent 86e1218fa9
commit d1ddf72136
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 33 additions and 14 deletions

View File

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

View File

@ -33,7 +33,7 @@ pub use self::identifier::Identifier;
/// of commitments, and a specific message.
///
/// <https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md>
#[derive(Clone, PartialEq)]
#[derive(Clone, PartialEq, Eq)]
pub struct Rho<C: Ciphersuite>(<<C::Group as Group>::Field as Field>::Scalar);
impl<C> Rho<C>
@ -199,7 +199,7 @@ where
/// The product of all signers' individual commitments, published as part of the
/// final signature.
#[derive(PartialEq)]
#[derive(PartialEq, Eq)]
pub struct GroupCommitment<C: Ciphersuite>(pub(super) <C::Group as Group>::Element);
// impl<C> Debug for GroupCommitment<C> where C: Ciphersuite {

View File

@ -14,7 +14,7 @@ use zeroize::{DefaultIsZeroes, Zeroize};
use crate::{frost::Identifier, Ciphersuite, Error, Field, Group, Scalar, VerifyingKey};
/// A secret scalar value representing a signer's secret key.
#[derive(Clone, Copy, PartialEq)]
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct Secret<C: Ciphersuite>(pub(crate) Scalar<C>);
impl<C> Secret<C>
@ -104,7 +104,7 @@ where
}
/// A public group element that represents a single signer's public key.
#[derive(Copy, Clone, PartialEq)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Public<C>(pub(super) <C::Group as Group>::Element)
where
C: Ciphersuite;

View File

@ -11,7 +11,7 @@ use crate::{frost, Ciphersuite, Error, Field, Group};
use super::{keys::Secret, Identifier};
/// A scalar that is a signing nonce.
#[derive(Clone, PartialEq, Zeroize)]
#[derive(Clone, PartialEq, Eq, Zeroize)]
pub struct Nonce<C: Ciphersuite>(pub(super) <<C::Group as Group>::Field as Field>::Scalar);
impl<C> Nonce<C>

View File

@ -1,4 +1,6 @@
#![allow(non_snake_case)]
// It's emitting false positives; see https://github.com/rust-lang/rust-clippy/issues/9413
#![allow(clippy::derive_partial_eq_without_eq)]
#![deny(missing_docs)]
#![doc = include_str!("../README.md")]
#![forbid(unsafe_code)]
@ -191,6 +193,25 @@ pub trait Ciphersuite: Copy + Clone {
///
/// [H4]: https://github.com/cfrg/draft-irtf-cfrg-frost/blob/master/draft-irtf-cfrg-frost.md#cryptographic-hash
fn H4(m: &[u8]) -> <<Self::Group as Group>::Field as Field>::Scalar;
/// Verify a signature for this ciphersuite. The default implementation uses the "cofactored"
/// equation (it multiplies by the cofactor returned by [`Group::cofactor()`]).
///
/// # Cryptographic Safety
///
/// You may override this to provide a tailored implementation, but if the ciphersuite defines it,
/// it must also multiply by the cofactor to comply with the RFC. Note that batch verification
/// (see [`crate::batch::Verifier`]) also uses the default implementation regardless whether a
/// tailored implementation was provided.
fn verify_signature(
msg: &[u8],
signature: &Signature<Self>,
public_key: &VerifyingKey<Self>,
) -> Result<(), Error> {
let c = crate::challenge::<Self>(&signature.R, &public_key.element, msg);
public_key.verify_prehashed(c, signature)
}
}
/// A type refinement for the scalar field element representing the per-message _[challenge]_.

View File

@ -33,19 +33,12 @@ where
<C::Group as Group>::serialize(&self.element)
}
/// Verify a purported `signature` over `msg` made by this verification key.
pub fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<(), Error> {
let c = crate::challenge::<C>(&signature.R, &self.element, msg);
self.verify_prehashed(signature, c)
}
/// Verify a purported `signature` with a pre-hashed [`Challenge`] made by this verification
/// key.
pub(crate) fn verify_prehashed(
&self,
signature: &Signature<C>,
challenge: Challenge<C>,
signature: &Signature<C>,
) -> Result<(), Error> {
// Verify check is h * ( - z * B + R + c * A) == 0
// h * ( z * B - c * A - R) == 0
@ -61,6 +54,11 @@ where
Err(Error::InvalidSignature)
}
}
/// Verify a purported `signature` over `msg` made by this verification key.
pub fn verify(&self, msg: &[u8], signature: &Signature<C>) -> Result<(), Error> {
C::verify_signature(msg, signature, self)
}
}
impl<C> Debug for VerifyingKey<C>