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:
parent
86e1218fa9
commit
d1ddf72136
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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]_.
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue