Skip to content

Commit 70bb260

Browse files
committed
Implement RandomizedDigestSigner, DigestVerifier for PSS structs
Implement the experimental (preview) RandomizedDigestSigner and DigestVerifier traits for the PSS structs. Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent efb9749 commit 70bb260

File tree

1 file changed

+148
-2
lines changed

1 file changed

+148
-2
lines changed

src/pss.rs

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex};
55
use core::marker::PhantomData;
66
use digest::{Digest, DynDigest};
77
use rand_core::{CryptoRng, RngCore};
8-
use signature::{RandomizedSigner, Signature as SignSignature, Verifier};
8+
use signature::{
9+
DigestVerifier, RandomizedDigestSigner, RandomizedSigner, Signature as SignSignature, Verifier,
10+
};
911
use subtle::ConstantTimeEq;
1012

1113
use crate::algorithms::mgf1_xor;
@@ -373,6 +375,28 @@ where
373375
}
374376
}
375377

378+
impl<D> RandomizedDigestSigner<D, Signature> for SigningKey<D>
379+
where
380+
D: Digest + DynDigest,
381+
{
382+
fn try_sign_digest_with_rng(
383+
&self,
384+
mut rng: impl CryptoRng + RngCore,
385+
digest: D,
386+
) -> signature::Result<Signature> {
387+
sign(
388+
&mut rng,
389+
false,
390+
&self.inner,
391+
&digest.finalize(),
392+
self.salt_len,
393+
&mut D::new(),
394+
)
395+
.map(|v| v.into())
396+
.map_err(|e| e.into())
397+
}
398+
}
399+
376400
pub struct BlindedSigningKey<D>
377401
where
378402
D: Digest + DynDigest,
@@ -429,6 +453,28 @@ where
429453
}
430454
}
431455

456+
impl<D> RandomizedDigestSigner<D, Signature> for BlindedSigningKey<D>
457+
where
458+
D: Digest + DynDigest,
459+
{
460+
fn try_sign_digest_with_rng(
461+
&self,
462+
mut rng: impl CryptoRng + RngCore,
463+
digest: D,
464+
) -> signature::Result<Signature> {
465+
sign(
466+
&mut rng,
467+
true,
468+
&self.inner,
469+
&digest.finalize(),
470+
self.salt_len,
471+
&mut D::new(),
472+
)
473+
.map(|v| v.into())
474+
.map_err(|e| e.into())
475+
}
476+
}
477+
432478
pub struct VerifyingKey<D>
433479
where
434480
D: Digest + DynDigest,
@@ -512,6 +558,21 @@ where
512558
}
513559
}
514560

561+
impl<D> DigestVerifier<D, Signature> for VerifyingKey<D>
562+
where
563+
D: Digest + DynDigest,
564+
{
565+
fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> {
566+
verify(
567+
&self.inner,
568+
&digest.finalize(),
569+
signature.as_ref(),
570+
&mut D::new(),
571+
)
572+
.map_err(|e| e.into())
573+
}
574+
}
575+
515576
#[cfg(test)]
516577
mod test {
517578
use crate::pss::{BlindedSigningKey, SigningKey, VerifyingKey};
@@ -522,7 +583,9 @@ mod test {
522583
use num_traits::{FromPrimitive, Num};
523584
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
524585
use sha1::{Digest, Sha1};
525-
use signature::{RandomizedSigner, Signature, Verifier};
586+
use signature::{
587+
DigestVerifier, RandomizedDigestSigner, RandomizedSigner, Signature, Verifier,
588+
};
526589

527590
fn get_private_key() -> RsaPrivateKey {
528591
// In order to generate new test vectors you'll need the PEM form of this key:
@@ -622,6 +685,45 @@ mod test {
622685
}
623686
}
624687

688+
#[test]
689+
fn test_verify_pss_digest_signer() {
690+
let priv_key = get_private_key();
691+
692+
let tests = [
693+
(
694+
"test\n",
695+
hex!(
696+
"6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
697+
"30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962f"
698+
),
699+
true,
700+
),
701+
(
702+
"test\n",
703+
hex!(
704+
"6f86f26b14372b2279f79fb6807c49889835c204f71e38249b4c5601462da8ae"
705+
"30f26ffdd9c13f1c75eee172bebe7b7c89f2f1526c722833b9737d6c172a962e"
706+
),
707+
false,
708+
),
709+
];
710+
let pub_key: RsaPublicKey = priv_key.into();
711+
let verifying_key = VerifyingKey::new(pub_key);
712+
713+
for (text, sig, expected) in &tests {
714+
let mut digest = Sha1::new();
715+
digest.update(text.as_bytes());
716+
let result = verifying_key.verify_digest(digest, &Signature::from_bytes(sig).unwrap());
717+
match expected {
718+
true => result.expect("failed to verify"),
719+
false => {
720+
result.expect_err("expected verifying error");
721+
()
722+
}
723+
}
724+
}
725+
}
726+
625727
#[test]
626728
fn test_sign_and_verify_roundtrip() {
627729
let priv_key = get_private_key();
@@ -693,4 +795,48 @@ mod test {
693795
.expect("failed to verify");
694796
}
695797
}
798+
799+
#[test]
800+
fn test_sign_and_verify_roundtrip_digest_signer() {
801+
let priv_key = get_private_key();
802+
803+
let tests = ["test\n"];
804+
let mut rng = ChaCha8Rng::from_seed([42; 32]);
805+
let signing_key = SigningKey::new(priv_key);
806+
let verifying_key = VerifyingKey::from(&signing_key);
807+
808+
for test in &tests {
809+
let mut digest = Sha1::new();
810+
digest.update(test.as_bytes());
811+
let sig = signing_key.sign_digest_with_rng(&mut rng, digest);
812+
813+
let mut digest = Sha1::new();
814+
digest.update(test.as_bytes());
815+
verifying_key
816+
.verify_digest(digest, &sig)
817+
.expect("failed to verify");
818+
}
819+
}
820+
821+
#[test]
822+
fn test_sign_and_verify_roundtrip_blinded_digest_signer() {
823+
let priv_key = get_private_key();
824+
825+
let tests = ["test\n"];
826+
let mut rng = ChaCha8Rng::from_seed([42; 32]);
827+
let signing_key = BlindedSigningKey::<Sha1>::new(priv_key);
828+
let verifying_key = VerifyingKey::from(&signing_key);
829+
830+
for test in &tests {
831+
let mut digest = Sha1::new();
832+
digest.update(test.as_bytes());
833+
let sig = signing_key.sign_digest_with_rng(&mut rng, digest);
834+
835+
let mut digest = Sha1::new();
836+
digest.update(test.as_bytes());
837+
verifying_key
838+
.verify_digest(digest, &sig)
839+
.expect("failed to verify");
840+
}
841+
}
696842
}

0 commit comments

Comments
 (0)