summaryrefslogtreecommitdiffstats
path: root/vendor/signature/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:47:55 +0000
commit2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4 (patch)
tree033cc839730fda84ff08db877037977be94e5e3a /vendor/signature/src
parentInitial commit. (diff)
downloadcargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.tar.xz
cargo-2aadc03ef15cb5ca5cc2af8a7c08e070742f0ac4.zip
Adding upstream version 0.70.1+ds1.upstream/0.70.1+ds1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/signature/src')
-rw-r--r--vendor/signature/src/encoding.rs31
-rw-r--r--vendor/signature/src/error.rs103
-rw-r--r--vendor/signature/src/hazmat.rs70
-rw-r--r--vendor/signature/src/keypair.rs29
-rw-r--r--vendor/signature/src/lib.rs168
-rw-r--r--vendor/signature/src/prehash_signature.rs31
-rw-r--r--vendor/signature/src/signer.rs118
-rw-r--r--vendor/signature/src/verifier.rs41
8 files changed, 591 insertions, 0 deletions
diff --git a/vendor/signature/src/encoding.rs b/vendor/signature/src/encoding.rs
new file mode 100644
index 0000000..8bc475b
--- /dev/null
+++ b/vendor/signature/src/encoding.rs
@@ -0,0 +1,31 @@
+//! Encoding support.
+
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
+
+/// Support for decoding/encoding signatures as bytes.
+pub trait SignatureEncoding:
+ Clone + Sized + for<'a> TryFrom<&'a [u8]> + TryInto<Self::Repr>
+{
+ /// Byte representation of a signature.
+ type Repr: 'static + AsRef<[u8]> + Clone + Send + Sync;
+
+ /// Encode signature as its byte representation.
+ fn to_bytes(&self) -> Self::Repr {
+ self.clone()
+ .try_into()
+ .ok()
+ .expect("signature encoding error")
+ }
+
+ /// Encode signature as a byte vector.
+ #[cfg(feature = "alloc")]
+ fn to_vec(&self) -> Vec<u8> {
+ self.to_bytes().as_ref().to_vec()
+ }
+
+ /// Get the length of this signature when encoded.
+ fn encoded_len(&self) -> usize {
+ self.to_bytes().as_ref().len()
+ }
+}
diff --git a/vendor/signature/src/error.rs b/vendor/signature/src/error.rs
new file mode 100644
index 0000000..1bfaf33
--- /dev/null
+++ b/vendor/signature/src/error.rs
@@ -0,0 +1,103 @@
+//! Signature error types
+
+use core::fmt::{self, Debug, Display};
+
+#[cfg(feature = "std")]
+use std::boxed::Box;
+
+/// Result type.
+///
+/// A result with the `signature` crate's [`Error`] type.
+pub type Result<T> = core::result::Result<T, Error>;
+
+/// Signature errors.
+///
+/// This type is deliberately opaque as to avoid sidechannel leakage which
+/// could potentially be used recover signing private keys or forge signatures
+/// (e.g. [BB'06]).
+///
+/// When the `std` feature is enabled, it impls [`std::error::Error`] and
+/// supports an optional [`std::error::Error::source`], which can be used by
+/// things like remote signers (e.g. HSM, KMS) to report I/O or auth errors.
+///
+/// [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher
+#[derive(Default)]
+#[non_exhaustive]
+pub struct Error {
+ /// Source of the error (if applicable).
+ #[cfg(feature = "std")]
+ source: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
+}
+
+impl Error {
+ /// Create a new error with no associated source
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Create a new error with an associated source.
+ ///
+ /// **NOTE:** The "source" should **NOT** be used to propagate cryptographic
+ /// errors e.g. signature parsing or verification errors. The intended use
+ /// cases are for propagating errors related to external signers, e.g.
+ /// communication/authentication errors with HSMs, KMS, etc.
+ #[cfg(feature = "std")]
+ pub fn from_source(
+ source: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
+ ) -> Self {
+ Self {
+ source: Some(source.into()),
+ }
+ }
+}
+
+impl Debug for Error {
+ #[cfg(not(feature = "std"))]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("signature::Error {}")
+ }
+
+ #[cfg(feature = "std")]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("signature::Error { source: ")?;
+
+ if let Some(source) = &self.source {
+ write!(f, "Some({})", source)?;
+ } else {
+ f.write_str("None")?;
+ }
+
+ f.write_str(" }")
+ }
+}
+
+impl Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.write_str("signature error")?;
+
+ #[cfg(feature = "std")]
+ {
+ if let Some(source) = &self.source {
+ write!(f, ": {}", source)?;
+ }
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl From<Box<dyn std::error::Error + Send + Sync + 'static>> for Error {
+ fn from(source: Box<dyn std::error::Error + Send + Sync + 'static>) -> Error {
+ Self::from_source(source)
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for Error {
+ fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+ self.source
+ .as_ref()
+ .map(|source| source.as_ref() as &(dyn std::error::Error + 'static))
+ }
+}
diff --git a/vendor/signature/src/hazmat.rs b/vendor/signature/src/hazmat.rs
new file mode 100644
index 0000000..d2f3e95
--- /dev/null
+++ b/vendor/signature/src/hazmat.rs
@@ -0,0 +1,70 @@
+//! Hazardous Materials: low-level APIs which can be insecure if misused.
+//!
+//! The traits in this module are not generally recommended, and should only be
+//! used in special cases where they are specifically needed.
+//!
+//! Using them incorrectly can introduce security vulnerabilities. Please
+//! carefully read the documentation before attempting to use them.
+
+use crate::Error;
+
+#[cfg(feature = "rand_core")]
+use crate::rand_core::CryptoRngCore;
+
+/// Sign the provided message prehash, returning a digital signature.
+pub trait PrehashSigner<S> {
+ /// Attempt to sign the given message digest, returning a digital signature
+ /// on success, or an error if something went wrong.
+ ///
+ /// The `prehash` parameter should be the output of a secure cryptographic
+ /// hash function.
+ ///
+ /// This API takes a `prehash` byte slice as there can potentially be many
+ /// compatible lengths for the message digest for a given concrete signature
+ /// algorithm.
+ ///
+ /// Allowed lengths are algorithm-dependent and up to a particular
+ /// implementation to decide.
+ fn sign_prehash(&self, prehash: &[u8]) -> Result<S, Error>;
+}
+
+/// Sign the provided message prehash using the provided external randomness source, returning a digital signature.
+#[cfg(feature = "rand_core")]
+pub trait RandomizedPrehashSigner<S> {
+ /// Attempt to sign the given message digest, returning a digital signature
+ /// on success, or an error if something went wrong.
+ ///
+ /// The `prehash` parameter should be the output of a secure cryptographic
+ /// hash function.
+ ///
+ /// This API takes a `prehash` byte slice as there can potentially be many
+ /// compatible lengths for the message digest for a given concrete signature
+ /// algorithm.
+ ///
+ /// Allowed lengths are algorithm-dependent and up to a particular
+ /// implementation to decide.
+ fn sign_prehash_with_rng(
+ &self,
+ rng: &mut impl CryptoRngCore,
+ prehash: &[u8],
+ ) -> Result<S, Error>;
+}
+
+/// Verify the provided message prehash using `Self` (e.g. a public key)
+pub trait PrehashVerifier<S> {
+ /// Use `Self` to verify that the provided signature for a given message
+ /// `prehash` is authentic.
+ ///
+ /// The `prehash` parameter should be the output of a secure cryptographic
+ /// hash function.
+ ///
+ /// Returns `Error` if it is inauthentic or some other error occurred, or
+ /// otherwise returns `Ok(())`.
+ ///
+ /// # ⚠️ Security Warning
+ ///
+ /// If `prehash` is something other than the output of a cryptographically
+ /// secure hash function, an attacker can potentially forge signatures by
+ /// solving a system of linear equations.
+ fn verify_prehash(&self, prehash: &[u8], signature: &S) -> Result<(), Error>;
+}
diff --git a/vendor/signature/src/keypair.rs b/vendor/signature/src/keypair.rs
new file mode 100644
index 0000000..d4795f2
--- /dev/null
+++ b/vendor/signature/src/keypair.rs
@@ -0,0 +1,29 @@
+//! Signing keypairs.
+
+/// Signing keypair with an associated verifying key.
+///
+/// This represents a type which holds both a signing key and a verifying key.
+pub trait Keypair {
+ /// Verifying key type for this keypair.
+ type VerifyingKey: Clone;
+
+ /// Get the verifying key which can verify signatures produced by the
+ /// signing key portion of this keypair.
+ fn verifying_key(&self) -> Self::VerifyingKey;
+}
+
+/// Signing keypair with an associated verifying key.
+///
+/// This represents a type which holds both a signing key and a verifying key.
+pub trait KeypairRef: AsRef<Self::VerifyingKey> {
+ /// Verifying key type for this keypair.
+ type VerifyingKey: Clone;
+}
+
+impl<K: KeypairRef> Keypair for K {
+ type VerifyingKey = <Self as KeypairRef>::VerifyingKey;
+
+ fn verifying_key(&self) -> Self::VerifyingKey {
+ self.as_ref().clone()
+ }
+}
diff --git a/vendor/signature/src/lib.rs b/vendor/signature/src/lib.rs
new file mode 100644
index 0000000..ba1feb4
--- /dev/null
+++ b/vendor/signature/src/lib.rs
@@ -0,0 +1,168 @@
+#![no_std]
+#![doc = include_str!("../README.md")]
+#![doc(
+ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg",
+ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg"
+)]
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![forbid(unsafe_code)]
+#![warn(
+ clippy::mod_module_files,
+ clippy::unwrap_used,
+ missing_docs,
+ rust_2018_idioms,
+ unused_lifetimes,
+ unused_qualifications
+)]
+
+//! # Design
+//!
+//! This crate provides a common set of traits for signing and verifying
+//! digital signatures intended to be implemented by libraries which produce
+//! or contain implementations of digital signature algorithms, and used by
+//! libraries which want to produce or verify digital signatures while
+//! generically supporting any compatible backend.
+//!
+//! ## Goals
+//!
+//! The traits provided by this crate were designed with the following goals
+//! in mind:
+//!
+//! - Provide an easy-to-use, misuse resistant API optimized for consumers
+//! (as opposed to implementers) of its traits.
+//! - Support common type-safe wrappers around "bag-of-bytes" representations
+//! which can be directly parsed from or written to the "wire".
+//! - Expose a trait/object-safe API where signers/verifiers spanning multiple
+//! homogeneous provider implementations can be seamlessly leveraged together
+//! in the same logical "keyring" so long as they operate on the same
+//! underlying signature type.
+//! - Allow one provider type to potentially implement support (including
+//! being generic over) several signature types.
+//! - Keep signature algorithm customizations / "knobs" out-of-band from the
+//! signing/verification APIs, ideally pushing such concerns into the type
+//! system so that algorithm mismatches are caught as type errors.
+//! - Opaque error type which minimizes information leaked from cryptographic
+//! failures, as "rich" error types in these scenarios are often a source
+//! of sidechannel information for attackers (e.g. [BB'06])
+//!
+//! [BB'06]: https://en.wikipedia.org/wiki/Daniel_Bleichenbacher
+//!
+//! ## Implementation
+//!
+//! To accomplish the above goals, the [`Signer`] and [`Verifier`] traits
+//! provided by this are generic over a signature value, and use generic
+//! parameters rather than associated types. Notably, they use such a parameter
+//! for the return value, allowing it to be inferred by the type checker based
+//! on the desired signature type.
+//!
+//! ## Alternatives considered
+//!
+//! This crate is based on many years of exploration of how to encapsulate
+//! digital signature systems in the most flexible, developer-friendly way.
+//! During that time many design alternatives were explored, tradeoffs
+//! compared, and ultimately the provided API was selected.
+//!
+//! The tradeoffs made in this API have all been to improve simplicity,
+//! ergonomics, type safety, and flexibility for *consumers* of the traits.
+//! At times, this has come at a cost to implementers. Below are some concerns
+//! we are cognizant of which were considered in the design of the API:
+//!
+//! - "Bag-of-bytes" serialization precludes signature providers from using
+//! their own internal representation of a signature, which can be helpful
+//! for many reasons (e.g. advanced signature system features like batch
+//! verification).
+//! - Associated types, rather than generic parameters of traits, could allow
+//! more customization of the types used by a particular signature system,
+//! e.g. using custom error types.
+//!
+//! It may still make sense to continue to explore the above tradeoffs, but
+//! with a *new* set of traits which are intended to be implementor-friendly,
+//! rather than consumer friendly. The existing [`Signer`] and [`Verifier`]
+//! traits could have blanket impls for the "provider-friendly" traits.
+//! However, as noted above this is a design space easily explored after
+//! stabilizing the consumer-oriented traits, and thus we consider these
+//! more important.
+//!
+//! That said, below are some caveats of trying to design such traits, and
+//! why we haven't actively pursued them:
+//!
+//! - Generics in the return position are already used to select which trait
+//! impl to use, i.e. for a particular signature algorithm/system. Avoiding
+//! a unified, concrete signature type adds another dimension to complexity
+//! and compiler errors, and in our experience makes them unsuitable for this
+//! sort of API. We believe such an API is the natural one for signature
+//! systems, reflecting the natural way they are written absent a trait.
+//! - Associated types preclude multiple (or generic) implementations of the
+//! same trait. These parameters are common in signature systems, notably
+//! ones which support different digest algorithms.
+//! - Digital signatures are almost always larger than the present 32-entry
+//! trait impl limitation on array types, which complicates trait signatures
+//! for these types (particularly things like `From` or `Borrow` bounds).
+//! This may be more interesting to explore after const generics.
+//!
+//! ## Unstable features
+//!
+//! Despite being post-1.0, this crate includes off-by-default unstable
+//! optional features, each of which depends on a pre-1.0
+//! crate.
+//!
+//! These features are considered exempt from SemVer. See the
+//! [SemVer policy](#semver-policy) above for more information.
+//!
+//! The following unstable features are presently supported:
+//!
+//! - `derive`: for implementers of signature systems using [`DigestSigner`]
+//! and [`DigestVerifier`], the `derive` feature can be used to
+//! derive [`Signer`] and [`Verifier`] traits which prehash the input
+//! message using the [`PrehashSignature::Digest`] algorithm for
+//! a given signature type. When the `derive` feature is enabled
+//! import the proc macros with `use signature::{Signer, Verifier}` and then
+//! add a `derive(Signer)` or `derive(Verifier)` attribute to the given
+//! digest signer/verifier type. Enabling this feature also enables `digest`
+//! support (see immediately below).
+//! - `digest`: enables the [`DigestSigner`] and [`DigestVerifier`]
+//! traits which are based on the [`Digest`] trait from the [`digest`] crate.
+//! These traits are used for representing signature systems based on the
+//! [Fiat-Shamir heuristic] which compute a random challenge value to sign
+//! by computing a cryptographically secure digest of the input message.
+//! - `rand_core`: enables the [`RandomizedSigner`] trait for signature
+//! systems which rely on a cryptographically secure random number generator
+//! for security.
+//!
+//! NOTE: the [`async-signature`] crate contains experimental `async` support
+//! for [`Signer`] and [`DigestSigner`].
+//!
+//! [`async-signature`]: https://docs.rs/async-signature
+//! [`digest`]: https://docs.rs/digest/
+//! [`Digest`]: https://docs.rs/digest/latest/digest/trait.Digest.html
+//! [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic
+
+#[cfg(feature = "alloc")]
+extern crate alloc;
+#[cfg(feature = "std")]
+extern crate std;
+
+pub mod hazmat;
+
+mod encoding;
+mod error;
+mod keypair;
+mod signer;
+mod verifier;
+
+#[cfg(feature = "digest")]
+mod prehash_signature;
+
+pub use crate::{encoding::*, error::*, keypair::*, signer::*, verifier::*};
+
+#[cfg(feature = "derive")]
+pub use derive::{Signer, Verifier};
+
+#[cfg(all(feature = "derive", feature = "digest"))]
+pub use derive::{DigestSigner, DigestVerifier};
+
+#[cfg(feature = "digest")]
+pub use {crate::prehash_signature::*, digest};
+
+#[cfg(feature = "rand_core")]
+pub use rand_core;
diff --git a/vendor/signature/src/prehash_signature.rs b/vendor/signature/src/prehash_signature.rs
new file mode 100644
index 0000000..d9a8645
--- /dev/null
+++ b/vendor/signature/src/prehash_signature.rs
@@ -0,0 +1,31 @@
+//! `PrehashSignature` trait.
+
+/// For intra-doc link resolution.
+#[allow(unused_imports)]
+use crate::{
+ signer::{DigestSigner, Signer},
+ verifier::{DigestVerifier, Verifier},
+};
+
+/// Marker trait for `Signature` types computable as `𝐒(𝐇(𝒎))`
+/// i.e. ones which prehash a message to be signed as `𝐇(𝒎)`
+///
+/// Where:
+///
+/// - `𝐒`: signature algorithm
+/// - `𝐇`: hash (a.k.a. digest) function
+/// - `𝒎`: message
+///
+/// This approach is relatively common in signature schemes based on the
+/// [Fiat-Shamir heuristic].
+///
+/// For signature types that implement this trait, when the `derive` crate
+/// feature is enabled a custom derive for [`Signer`] is available for any
+/// types that impl [`DigestSigner`], and likewise for deriving [`Verifier`] for
+/// types which impl [`DigestVerifier`].
+///
+/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic
+pub trait PrehashSignature {
+ /// Preferred `Digest` algorithm to use when computing this signature type.
+ type Digest: digest::Digest;
+}
diff --git a/vendor/signature/src/signer.rs b/vendor/signature/src/signer.rs
new file mode 100644
index 0000000..b339ddf
--- /dev/null
+++ b/vendor/signature/src/signer.rs
@@ -0,0 +1,118 @@
+//! Traits for generating digital signatures
+
+use crate::error::Error;
+
+#[cfg(feature = "digest")]
+use crate::digest::Digest;
+
+#[cfg(feature = "rand_core")]
+use crate::rand_core::CryptoRngCore;
+
+/// Sign the provided message bytestring using `Self` (e.g. a cryptographic key
+/// or connection to an HSM), returning a digital signature.
+pub trait Signer<S> {
+ /// Sign the given message and return a digital signature
+ fn sign(&self, msg: &[u8]) -> S {
+ self.try_sign(msg).expect("signature operation failed")
+ }
+
+ /// Attempt to sign the given message, returning a digital signature on
+ /// success, or an error if something went wrong.
+ ///
+ /// The main intended use case for signing errors is when communicating
+ /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens.
+ fn try_sign(&self, msg: &[u8]) -> Result<S, Error>;
+}
+
+/// Sign the provided message bytestring using `&mut Self` (e.g. an evolving
+/// cryptographic key such as a stateful hash-based signature), returning a
+/// digital signature.
+pub trait SignerMut<S> {
+ /// Sign the given message, update the state, and return a digital signature.
+ fn sign(&mut self, msg: &[u8]) -> S {
+ self.try_sign(msg).expect("signature operation failed")
+ }
+
+ /// Attempt to sign the given message, updating the state, and returning a
+ /// digital signature on success, or an error if something went wrong.
+ ///
+ /// Signing can fail, e.g., if the number of time periods allowed by the
+ /// current key is exceeded.
+ fn try_sign(&mut self, msg: &[u8]) -> Result<S, Error>;
+}
+
+/// Blanket impl of [`SignerMut`] for all [`Signer`] types.
+impl<S, T: Signer<S>> SignerMut<S> for T {
+ fn try_sign(&mut self, msg: &[u8]) -> Result<S, Error> {
+ T::try_sign(self, msg)
+ }
+}
+
+/// Sign the given prehashed message [`Digest`] using `Self`.
+///
+/// ## Notes
+///
+/// This trait is primarily intended for signature algorithms based on the
+/// [Fiat-Shamir heuristic], a method for converting an interactive
+/// challenge/response-based proof-of-knowledge protocol into an offline
+/// digital signature through the use of a random oracle, i.e. a digest
+/// function.
+///
+/// The security of such protocols critically rests upon the inability of
+/// an attacker to solve for the output of the random oracle, as generally
+/// otherwise such signature algorithms are a system of linear equations and
+/// therefore doing so would allow the attacker to trivially forge signatures.
+///
+/// To prevent misuse which would potentially allow this to be possible, this
+/// API accepts a [`Digest`] instance, rather than a raw digest value.
+///
+/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic
+#[cfg(feature = "digest")]
+pub trait DigestSigner<D: Digest, S> {
+ /// Sign the given prehashed message [`Digest`], returning a signature.
+ ///
+ /// Panics in the event of a signing error.
+ fn sign_digest(&self, digest: D) -> S {
+ self.try_sign_digest(digest)
+ .expect("signature operation failed")
+ }
+
+ /// Attempt to sign the given prehashed message [`Digest`], returning a
+ /// digital signature on success, or an error if something went wrong.
+ fn try_sign_digest(&self, digest: D) -> Result<S, Error>;
+}
+
+/// Sign the given message using the provided external randomness source.
+#[cfg(feature = "rand_core")]
+pub trait RandomizedSigner<S> {
+ /// Sign the given message and return a digital signature
+ fn sign_with_rng(&self, rng: &mut impl CryptoRngCore, msg: &[u8]) -> S {
+ self.try_sign_with_rng(rng, msg)
+ .expect("signature operation failed")
+ }
+
+ /// Attempt to sign the given message, returning a digital signature on
+ /// success, or an error if something went wrong.
+ ///
+ /// The main intended use case for signing errors is when communicating
+ /// with external signers, e.g. cloud KMS, HSMs, or other hardware tokens.
+ fn try_sign_with_rng(&self, rng: &mut impl CryptoRngCore, msg: &[u8]) -> Result<S, Error>;
+}
+
+/// Combination of [`DigestSigner`] and [`RandomizedSigner`] with support for
+/// computing a signature over a digest which requires entropy from an RNG.
+#[cfg(all(feature = "digest", feature = "rand_core"))]
+pub trait RandomizedDigestSigner<D: Digest, S> {
+ /// Sign the given prehashed message `Digest`, returning a signature.
+ ///
+ /// Panics in the event of a signing error.
+ fn sign_digest_with_rng(&self, rng: &mut impl CryptoRngCore, digest: D) -> S {
+ self.try_sign_digest_with_rng(rng, digest)
+ .expect("signature operation failed")
+ }
+
+ /// Attempt to sign the given prehashed message `Digest`, returning a
+ /// digital signature on success, or an error if something went wrong.
+ fn try_sign_digest_with_rng(&self, rng: &mut impl CryptoRngCore, digest: D)
+ -> Result<S, Error>;
+}
diff --git a/vendor/signature/src/verifier.rs b/vendor/signature/src/verifier.rs
new file mode 100644
index 0000000..65409a9
--- /dev/null
+++ b/vendor/signature/src/verifier.rs
@@ -0,0 +1,41 @@
+//! Trait for verifying digital signatures
+
+use crate::error::Error;
+
+#[cfg(feature = "digest")]
+use crate::digest::Digest;
+
+/// Verify the provided message bytestring using `Self` (e.g. a public key)
+pub trait Verifier<S> {
+ /// Use `Self` to verify that the provided signature for a given message
+ /// bytestring is authentic.
+ ///
+ /// Returns `Error` if it is inauthentic, or otherwise returns `()`.
+ fn verify(&self, msg: &[u8], signature: &S) -> Result<(), Error>;
+}
+
+/// Verify the provided signature for the given prehashed message [`Digest`]
+/// is authentic.
+///
+/// ## Notes
+///
+/// This trait is primarily intended for signature algorithms based on the
+/// [Fiat-Shamir heuristic], a method for converting an interactive
+/// challenge/response-based proof-of-knowledge protocol into an offline
+/// digital signature through the use of a random oracle, i.e. a digest
+/// function.
+///
+/// The security of such protocols critically rests upon the inability of
+/// an attacker to solve for the output of the random oracle, as generally
+/// otherwise such signature algorithms are a system of linear equations and
+/// therefore doing so would allow the attacker to trivially forge signatures.
+///
+/// To prevent misuse which would potentially allow this to be possible, this
+/// API accepts a [`Digest`] instance, rather than a raw digest value.
+///
+/// [Fiat-Shamir heuristic]: https://en.wikipedia.org/wiki/Fiat%E2%80%93Shamir_heuristic
+#[cfg(feature = "digest")]
+pub trait DigestVerifier<D: Digest, S> {
+ /// Verify the signature against the given [`Digest`] output.
+ fn verify_digest(&self, digest: D, signature: &S) -> Result<(), Error>;
+}