diff --git a/src/pss.rs b/src/pss.rs index 46dbd3f..b4e8dd0 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -5,6 +5,8 @@ use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use core::marker::PhantomData; use digest::{Digest, DynDigest}; use rand_core::{CryptoRng, RngCore}; +#[cfg(feature = "digest-preview")] +use signature::{DigestVerifier, RandomizedDigestSigner}; use signature::{RandomizedSigner, Signature as SignSignature, Verifier}; use subtle::ConstantTimeEq; @@ -373,6 +375,29 @@ where } } +#[cfg(feature = "digest-preview")] +impl RandomizedDigestSigner for SigningKey +where + D: Digest + DynDigest, +{ + fn try_sign_digest_with_rng( + &self, + mut rng: impl CryptoRng + RngCore, + digest: D, + ) -> signature::Result { + sign( + &mut rng, + false, + &self.inner, + &digest.finalize(), + self.salt_len, + &mut D::new(), + ) + .map(|v| v.into()) + .map_err(|e| e.into()) + } +} + pub struct BlindedSigningKey where D: Digest + DynDigest, @@ -429,6 +454,29 @@ where } } +#[cfg(feature = "digest-preview")] +impl RandomizedDigestSigner for BlindedSigningKey +where + D: Digest + DynDigest, +{ + fn try_sign_digest_with_rng( + &self, + mut rng: impl CryptoRng + RngCore, + digest: D, + ) -> signature::Result { + sign( + &mut rng, + true, + &self.inner, + &digest.finalize(), + self.salt_len, + &mut D::new(), + ) + .map(|v| v.into()) + .map_err(|e| e.into()) + } +} + pub struct VerifyingKey where D: Digest + DynDigest, @@ -512,6 +560,22 @@ where } } +#[cfg(feature = "digest-preview")] +impl DigestVerifier for VerifyingKey +where + D: Digest + DynDigest, +{ + fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> { + verify( + &self.inner, + &digest.finalize(), + signature.as_ref(), + &mut D::new(), + ) + .map_err(|e| e.into()) + } +} + #[cfg(test)] mod test { use crate::pss::{BlindedSigningKey, SigningKey, VerifyingKey}; @@ -522,6 +586,8 @@ mod test { use num_traits::{FromPrimitive, Num}; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; use sha1::{Digest, Sha1}; + #[cfg(feature = "digest-preview")] + use signature::{DigestVerifier, RandomizedDigestSigner}; use signature::{RandomizedSigner, Signature, Verifier}; fn get_private_key() -> RsaPrivateKey { @@ -622,6 +688,46 @@ mod test { } } + #[cfg(feature = "digest-preview")] + #[test] + fn test_verify_pss_digest_signer() { + let priv_key = get_private_key(); + + let tests = [ + ( + "test\n", + hex!( + "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae" + "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f" + ), + true, + ), + ( + "test\n", + hex!( + "6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae" + "30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e" + ), + false, + ), + ]; + let pub_key: RsaPublicKey = priv_key.into(); + let verifying_key: VerifyingKey<_> = VerifyingKey::new(pub_key); + + for (text, sig, expected) in &tests { + let mut digest = Sha1::new(); + digest.update(text.as_bytes()); + let result = verifying_key.verify_digest(digest, &Signature::from_bytes(sig).unwrap()); + match expected { + true => result.expect("failed to verify"), + false => { + result.expect_err("expected verifying error"); + () + } + } + } + } + #[test] fn test_sign_and_verify_roundtrip() { let priv_key = get_private_key(); @@ -693,4 +799,50 @@ mod test { .expect("failed to verify"); } } + + #[cfg(feature = "digest-preview")] + #[test] + fn test_sign_and_verify_roundtrip_digest_signer() { + let priv_key = get_private_key(); + + let tests = ["test\n"]; + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let signing_key = SigningKey::new(priv_key); + let verifying_key: VerifyingKey<_> = (&signing_key).into(); + + for test in &tests { + let mut digest = Sha1::new(); + digest.update(test.as_bytes()); + let sig = signing_key.sign_digest_with_rng(&mut rng, digest); + + let mut digest = Sha1::new(); + digest.update(test.as_bytes()); + verifying_key + .verify_digest(digest, &sig) + .expect("failed to verify"); + } + } + + #[cfg(feature = "digest-preview")] + #[test] + fn test_sign_and_verify_roundtrip_blinded_digest_signer() { + let priv_key = get_private_key(); + + let tests = ["test\n"]; + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let signing_key = BlindedSigningKey::::new(priv_key); + let verifying_key: VerifyingKey<_> = (&signing_key).into(); + + for test in &tests { + let mut digest = Sha1::new(); + digest.update(test.as_bytes()); + let sig = signing_key.sign_digest_with_rng(&mut rng, digest); + + let mut digest = Sha1::new(); + digest.update(test.as_bytes()); + verifying_key + .verify_digest(digest, &sig) + .expect("failed to verify"); + } + } }