From 77c001c5abdfea97c7710173c196c76253490734 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Fri, 12 Sep 2025 22:02:13 +0200 Subject: [PATCH] Use `Fn(&mut D)` for `Async/Randomized/Digest/Signer/Verifier` --- signature/src/signer.rs | 76 ++++++++++++++++++++++++++------------- signature/src/verifier.rs | 21 +++++++---- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/signature/src/signer.rs b/signature/src/signer.rs index 7fc10764f..c75a90066 100644 --- a/signature/src/signer.rs +++ b/signature/src/signer.rs @@ -3,7 +3,7 @@ use crate::error::Error; #[cfg(feature = "digest")] -use crate::digest::Digest; +use crate::digest::Update; #[cfg(feature = "rand_core")] use crate::rand_core::{CryptoRng, TryCryptoRng}; @@ -55,7 +55,7 @@ pub trait SignerMut { fn try_sign(&mut self, msg: &[u8]) -> Result; } -/// Sign the given prehashed message [`Digest`] using `Self`. +/// Sign the given prehashed message `Digest` using `Self`. /// /// ## Notes /// @@ -71,22 +71,32 @@ pub trait SignerMut { /// 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. +/// 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 { - /// Sign the given prehashed message [`Digest`], returning a signature. +pub trait DigestSigner { + /// Sign a message by updating the received `Digest` with it, + /// returning a signature. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. /// /// Panics in the event of a signing error. - fn sign_digest(&self, digest: D) -> S { - self.try_sign_digest(digest) - .expect("signature operation failed") + fn sign_digest(&self, f: F) -> S { + self.try_sign_digest(|digest| { + f(digest); + Ok(()) + }) + .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; + /// Attempt to sign a message by updating the received `Digest` with it, + /// returning a digital signature on success, or an error if something went wrong. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. + fn try_sign_digest Result<(), Error>>(&self, f: F) -> Result; } /// Sign the given message using the provided external randomness source. @@ -132,21 +142,31 @@ pub trait RandomizedMultipartSigner { /// 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 { - /// Sign the given prehashed message `Digest`, returning a signature. +pub trait RandomizedDigestSigner { + /// Sign a message by updating the received `Digest` with it, + /// returning a signature. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. /// /// Panics in the event of a signing error. - fn sign_digest_with_rng(&self, rng: &mut R, digest: D) -> S { - self.try_sign_digest_with_rng(rng, digest) - .expect("signature operation failed") + fn sign_digest_with_rng(&self, rng: &mut R, f: F) -> S { + self.try_sign_digest_with_rng(rng, |digest| { + f(digest); + Ok(()) + }) + .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( + /// Attempt to sign a message by updating the received `Digest` with it, + /// returning a digital signature on success, or an error if something went wrong. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. + fn try_sign_digest_with_rng Result<(), Error>>( &self, rng: &mut R, - digest: D, + f: F, ) -> Result; } @@ -226,17 +246,23 @@ where } } -/// Asynchronously sign the given prehashed message [`Digest`] using `Self`. +/// Asynchronously sign the given prehashed message `Digest` using `Self`. /// /// This trait is an async equivalent of the [`DigestSigner`] trait. #[cfg(feature = "digest")] pub trait AsyncDigestSigner where - D: Digest, + D: Update, { - /// Attempt to sign the given prehashed message [`Digest`], returning a - /// digital signature on success, or an error if something went wrong. - async fn sign_digest_async(&self, digest: D) -> Result; + /// Attempt to sign a message by updating the received `Digest` with it, + /// returning a digital signature on success, or an error if something went wrong. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. + async fn sign_digest_async Result<(), Error>>( + &self, + f: F, + ) -> Result; } /// Sign the given message using the provided external randomness source. diff --git a/signature/src/verifier.rs b/signature/src/verifier.rs index 7c824f72d..0d17163e3 100644 --- a/signature/src/verifier.rs +++ b/signature/src/verifier.rs @@ -3,7 +3,7 @@ use crate::error::Error; #[cfg(feature = "digest")] -use crate::digest::Digest; +use crate::digest::Update; /// Verify the provided message bytestring using `Self` (e.g. a public key) pub trait Verifier { @@ -21,7 +21,7 @@ pub trait MultipartVerifier { fn multipart_verify(&self, msg: &[&[u8]], signature: &S) -> Result<(), Error>; } -/// Verify the provided signature for the given prehashed message [`Digest`] +/// Verify the provided signature for the given prehashed message `Digest` /// is authentic. /// /// ## Notes @@ -38,11 +38,20 @@ pub trait MultipartVerifier { /// 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. +/// API accepts a message by updating the received `Digest` with it, 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 { - /// Verify the signature against the given [`Digest`] output. - fn verify_digest(&self, digest: D, signature: &S) -> Result<(), Error>; +pub trait DigestVerifier { + /// Verify the signature against the received `Digest` output, + /// by updating it with the message. + /// + /// The given function can be invoked multiple times. It is expected that + /// in each invocation the `Digest` is updated with the entire equal message. + fn verify_digest Result<(), Error>>( + &self, + f: F, + signature: &S, + ) -> Result<(), Error>; }