From 5cccb274a7ccbc044ef6e38420e63ea0cecb9d35 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sun, 31 Jul 2022 12:30:57 +0300 Subject: [PATCH] PaddingScheme: remove rng from PSS padding scheme (#172) The passed rng is not necessary for PSS signature verification. Instead of passing artificial unused RNG through the PaddingScheme, add new sign_with_rng() API and pass rng directly. In the sign_blinded() use the passed rng both for salt generation and for the blinding process. Signed-off-by: Dmitry Baryshkov --- src/key.rs | 34 ++++++++++++++++------------------ src/padding.rs | 11 ++--------- src/pss.rs | 39 +++++++++++++++++++++++++-------------- 3 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/key.rs b/src/key.rs index 3b323c0b..13012363 100644 --- a/src/key.rs +++ b/src/key.rs @@ -499,18 +499,24 @@ impl RsaPrivateKey { PaddingScheme::PKCS1v15Sign { ref hash } => { pkcs1v15::sign::(None, self, hash.as_ref(), digest_in) } + _ => Err(Error::InvalidPaddingScheme), + } + } + + /// Sign the given digest using the provided rng + /// + /// Use `rng` for signature process. + pub fn sign_with_rng( + &self, + rng: &mut R, + padding: PaddingScheme, + digest_in: &[u8], + ) -> Result> { + match padding { PaddingScheme::PSS { - mut salt_rng, mut digest, salt_len, - } => pss::sign::<_, DummyRng, _>( - &mut *salt_rng, - None, - self, - digest_in, - salt_len, - &mut *digest, - ), + } => pss::sign::(rng, false, self, digest_in, salt_len, &mut *digest), _ => Err(Error::InvalidPaddingScheme), } } @@ -529,17 +535,9 @@ impl RsaPrivateKey { pkcs1v15::sign(Some(rng), self, hash.as_ref(), digest_in) } PaddingScheme::PSS { - mut salt_rng, mut digest, salt_len, - } => pss::sign::<_, R, _>( - &mut *salt_rng, - Some(rng), - self, - digest_in, - salt_len, - &mut *digest, - ), + } => pss::sign::(rng, true, self, digest_in, salt_len, &mut *digest), _ => Err(Error::InvalidPaddingScheme), } } diff --git a/src/padding.rs b/src/padding.rs index e9c9102e..8655cb63 100644 --- a/src/padding.rs +++ b/src/padding.rs @@ -3,7 +3,6 @@ use alloc::string::{String, ToString}; use core::fmt; use digest::{Digest, DynDigest}; -use rand_core::RngCore; use crate::hash::Hash; @@ -30,7 +29,6 @@ pub enum PaddingScheme { }, /// Sign and Verify using PSS padding. PSS { - salt_rng: Box, digest: Box, salt_len: Option, }, @@ -142,20 +140,15 @@ impl PaddingScheme { } } - pub fn new_pss(rng: S) -> Self { + pub fn new_pss() -> Self { PaddingScheme::PSS { - salt_rng: Box::new(rng), digest: Box::new(T::new()), salt_len: None, } } - pub fn new_pss_with_salt( - rng: S, - len: usize, - ) -> Self { + pub fn new_pss_with_salt(len: usize) -> Self { PaddingScheme::PSS { - salt_rng: Box::new(rng), digest: Box::new(T::new()), salt_len: Some(len), } diff --git a/src/pss.rs b/src/pss.rs index 41d2f144..4222f807 100644 --- a/src/pss.rs +++ b/src/pss.rs @@ -31,9 +31,9 @@ pub fn verify( /// given hash function. The opts argument may be nil, in which case sensible /// defaults are used. // TODO: bind T with the CryptoRng trait -pub fn sign( +pub fn sign( rng: &mut T, - blind_rng: Option<&mut S>, + blind: bool, priv_key: &SK, hashed: &[u8], salt_len: Option, @@ -44,6 +44,7 @@ pub fn sign( let mut salt = vec![0; salt_len]; rng.fill_bytes(&mut salt[..]); + let blind_rng = if blind { Some(rng) } else { None }; sign_pss_with_salt(blind_rng, priv_key, hashed, &salt, digest) } @@ -283,9 +284,8 @@ mod test { for (text, sig) in &tests { let digest = Sha1::digest(text.as_bytes()).to_vec(); - let rng = ChaCha8Rng::from_seed([42; 32]); pub_key - .verify(PaddingScheme::new_pss::(rng), &digest, sig) + .verify(PaddingScheme::new_pss::(), &digest, sig) .expect("failed to verify"); } } @@ -300,19 +300,30 @@ mod test { for test in &tests { let digest = Sha1::digest(test.as_bytes()).to_vec(); let sig = priv_key - .sign_blinded( - &mut rng.clone(), - PaddingScheme::new_pss::(rng.clone()), - &digest, - ) + .sign_with_rng(&mut rng.clone(), PaddingScheme::new_pss::(), &digest) .expect("failed to sign"); priv_key - .verify( - PaddingScheme::new_pss::(rng.clone()), - &digest, - &sig, - ) + .verify(PaddingScheme::new_pss::(), &digest, &sig) + .expect("failed to verify"); + } + } + + #[test] + fn test_sign_blinded_and_verify_roundtrip() { + let priv_key = get_private_key(); + + let tests = ["test\n"]; + let rng = ChaCha8Rng::from_seed([42; 32]); + + for test in &tests { + let digest = Sha1::digest(test.as_bytes()).to_vec(); + let sig = priv_key + .sign_blinded(&mut rng.clone(), PaddingScheme::new_pss::(), &digest) + .expect("failed to sign"); + + priv_key + .verify(PaddingScheme::new_pss::(), &digest, &sig) .expect("failed to verify"); } }