diff --git a/Cargo.toml b/Cargo.toml index a9397ab6..0558bfac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ num-iter = { version = "0.1.37", default-features = false } rand_core = { version = "0.6", default-features = false } byteorder = { version = "1.3.1", default-features = false } subtle = { version = "2.1.1", default-features = false } -digest = { version = "0.10.0", default-features = false, features = ["alloc"] } +digest = { version = "0.10.5", default-features = false, features = ["alloc", "oid"] } pkcs1 = { version = "0.4", default-features = false, features = ["pkcs8", "alloc"] } pkcs8 = { version = "0.9", default-features = false, features = ["alloc"] } #To keep the rand_core versions properly pinnen, specify exact version @@ -30,11 +30,6 @@ zeroize = { version = "1", features = ["alloc"] } # Temporary workaround until https://github.com/dignifiedquire/num-bigint/pull/42 lands smallvec = { version = "1.6.1", default-features = false } -# Temporary until the link from Digest to OID is moved to corresponding crates -sha1 = { version = "0.10.1", default-features = false, optional = true } -sha2 = { version = "0.10.2", default-features = false, optional = true } -sha3 = { version = "0.10.1", default-features = false, optional = true } - [dependencies.serde_crate] package = "serde" optional = true @@ -50,15 +45,15 @@ rand_xorshift = "0.3" rand_chacha = "0.3" rand = "0.8" rand_core = { version = "0.6", default-features = false } -sha1 = { version = "0.10.1", default-features = false } -sha2 = { version = "0.10.2", default-features = false } -sha3 = { version = "0.10.1", default-features = false } +sha1 = { version = "0.10.5", default-features = false, features = ["oid"] } +sha2 = { version = "0.10.6", default-features = false, features = ["oid"] } +sha3 = { version = "0.10.5", default-features = false, features = ["oid"] } [[bench]] name = "key" [features] -default = ["std", "pem", "sha2"] +default = ["std", "pem"] nightly = ["num-bigint/nightly"] serde = ["num-bigint/serde", "serde_crate"] expose-internals = [] @@ -68,7 +63,7 @@ pkcs5 = ["pkcs8/encryption"] getrandom = ["rand_core/getrandom"] [package.metadata.docs.rs] -features = ["std", "pem", "serde", "expose-internals", "sha1", "sha2", "sha3"] +features = ["std", "pem", "serde", "expose-internals"] rustdoc-args = ["--cfg", "docsrs"] [profile.dev] diff --git a/src/hash.rs b/src/hash.rs deleted file mode 100644 index ffa8433f..00000000 --- a/src/hash.rs +++ /dev/null @@ -1,137 +0,0 @@ -/// A list of provided hashes, implementing `Hash`. -#[derive(Debug, Clone, Copy)] -pub enum Hash { - MD5, - SHA1, - SHA2_224, - SHA2_256, - SHA2_384, - SHA2_512, - SHA3_256, - SHA3_384, - SHA3_512, - MD5SHA1, - RIPEMD160, -} - -impl Hash { - /// Returns the length in bytes of a digest. - pub fn size(&self) -> usize { - match *self { - Hash::MD5 => 16, - Hash::SHA1 => 20, - Hash::SHA2_224 => 28, - Hash::SHA2_256 => 32, - Hash::SHA2_384 => 48, - Hash::SHA2_512 => 64, - Hash::SHA3_256 => 32, - Hash::SHA3_384 => 48, - Hash::SHA3_512 => 64, - Hash::MD5SHA1 => 36, - Hash::RIPEMD160 => 20, - } - } - - /// Returns the ASN1 DER prefix for the the hash function. - pub fn asn1_prefix(&self) -> &'static [u8] { - match *self { - Hash::MD5 => &[ - 0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, - 0x05, 0x00, 0x04, 0x10, - ], - Hash::SHA1 => &[ - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, - 0x14, - ], - Hash::SHA2_224 => &[ - 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x04, 0x05, 0x00, 0x04, 0x1c, - ], - Hash::SHA2_256 => &[ - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x01, 0x05, 0x00, 0x04, 0x20, - ], - Hash::SHA2_384 => &[ - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x02, 0x05, 0x00, 0x04, 0x30, - ], - - Hash::SHA2_512 => &[ - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x03, 0x05, 0x00, 0x04, 0x40, - ], - - // A special TLS case which doesn't use an ASN1 prefix - Hash::MD5SHA1 => &[], - Hash::RIPEMD160 => &[ - 0x30, 0x20, 0x30, 0x08, 0x06, 0x06, 0x28, 0xcf, 0x06, 0x03, 0x00, 0x31, 0x04, 0x14, - ], - - Hash::SHA3_256 => &[ - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x08, 0x05, 0x00, 0x04, 0x20, - ], - Hash::SHA3_384 => &[ - 30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x08, 0x05, 0x00, 0x04, 0x20, - ], - - Hash::SHA3_512 => &[ - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, - 0x0a, 0x05, 0x00, 0x04, 0x40, - ], - } - } -} - -/* FIXME: This trait should be refactored into per-digest implementations returning OID */ -pub trait AssociatedHash { - const HASH: Hash; -} - -#[cfg(feature = "sha1")] -impl AssociatedHash for sha1::Sha1 { - const HASH: Hash = Hash::SHA1; -} - -#[cfg(feature = "sha2")] -impl AssociatedHash for sha2::Sha224 { - const HASH: Hash = Hash::SHA2_224; -} - -#[cfg(feature = "sha2")] -impl AssociatedHash for sha2::Sha256 { - const HASH: Hash = Hash::SHA2_256; -} - -#[cfg(feature = "sha2")] -impl AssociatedHash for sha2::Sha384 { - const HASH: Hash = Hash::SHA2_384; -} - -#[cfg(feature = "sha2")] -impl AssociatedHash for sha2::Sha512 { - const HASH: Hash = Hash::SHA2_512; -} - -/* -#[cfg(feature = "sha3")] -impl AssociatedHash for sha3::Sha3_224 { - const HASH: Hash = Hash::SHA3_224; -} -*/ - -#[cfg(feature = "sha3")] -impl AssociatedHash for sha3::Sha3_256 { - const HASH: Hash = Hash::SHA3_256; -} - -#[cfg(feature = "sha3")] -impl AssociatedHash for sha3::Sha3_384 { - const HASH: Hash = Hash::SHA3_384; -} - -#[cfg(feature = "sha3")] -impl AssociatedHash for sha3::Sha3_512 { - const HASH: Hash = Hash::SHA3_512; -} diff --git a/src/key.rs b/src/key.rs index 3d65d5c3..02c88791 100644 --- a/src/key.rs +++ b/src/key.rs @@ -216,8 +216,13 @@ impl PublicKey for RsaPublicKey { fn verify(&self, padding: PaddingScheme, hashed: &[u8], sig: &[u8]) -> Result<()> { match padding { - PaddingScheme::PKCS1v15Sign { ref hash } => { - pkcs1v15::verify(self, hash.as_ref(), hashed, sig) + PaddingScheme::PKCS1v15Sign { hash_len, prefix } => { + if let Some(hash_len) = hash_len { + if hashed.len() != hash_len { + return Err(Error::InputNotHashed); + } + } + pkcs1v15::verify(self, prefix.as_ref(), hashed, sig) } PaddingScheme::PSS { mut digest, .. } => pss::verify(self, hashed, sig, &mut *digest), _ => Err(Error::InvalidPaddingScheme), @@ -509,8 +514,13 @@ impl RsaPrivateKey { pub fn sign(&self, padding: PaddingScheme, digest_in: &[u8]) -> Result> { match padding { // need to pass any Rng as the type arg, so the type checker is happy, it is not actually used for anything - PaddingScheme::PKCS1v15Sign { ref hash } => { - pkcs1v15::sign::(None, self, hash.as_ref(), digest_in) + PaddingScheme::PKCS1v15Sign { hash_len, prefix } => { + if let Some(hash_len) = hash_len { + if digest_in.len() != hash_len { + return Err(Error::InputNotHashed); + } + } + pkcs1v15::sign::(None, self, prefix.as_ref(), digest_in) } _ => Err(Error::InvalidPaddingScheme), } @@ -544,8 +554,13 @@ impl RsaPrivateKey { digest_in: &[u8], ) -> Result> { match padding { - PaddingScheme::PKCS1v15Sign { ref hash } => { - pkcs1v15::sign(Some(rng), self, hash.as_ref(), digest_in) + PaddingScheme::PKCS1v15Sign { hash_len, prefix } => { + if let Some(hash_len) = hash_len { + if digest_in.len() != hash_len { + return Err(Error::InputNotHashed); + } + } + pkcs1v15::sign(Some(rng), self, prefix.as_ref(), digest_in) } PaddingScheme::PSS { mut digest, diff --git a/src/lib.rs b/src/lib.rs index 4d2c7768..14f33e92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,32 +47,28 @@ //! assert_eq!(&data[..], &dec_data[..]); //! ``` //! -#![cfg_attr( - feature = "sha2", - doc = r#" -Using PKCS1v15 signatures -``` -use rsa::RsaPrivateKey; -use rsa::pkcs1v15::{SigningKey, VerifyingKey}; -use sha2::{Digest, Sha256}; -use signature::{RandomizedSigner, Signature, Verifier}; - -let mut rng = rand::thread_rng(); - -let bits = 2048; -let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); -let signing_key = SigningKey::::new_with_prefix(private_key); -let verifying_key: VerifyingKey<_> = (&signing_key).into(); - -// Sign -let data = b"hello world"; -let signature = signing_key.sign_with_rng(&mut rng, data); -assert_ne!(signature.as_bytes(), data); - -// Verify -verifying_key.verify(data, &signature).expect("failed to verify"); -```"# -)] +//! Using PKCS1v15 signatures +//! ``` +//! use rsa::RsaPrivateKey; +//! use rsa::pkcs1v15::{SigningKey, VerifyingKey}; +//! use sha2::{Digest, Sha256}; +//! use signature::{RandomizedSigner, Signature, Verifier}; +//! +//! let mut rng = rand::thread_rng(); +//! +//! let bits = 2048; +//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); +//! let signing_key = SigningKey::::new_with_prefix(private_key); +//! let verifying_key: VerifyingKey<_> = (&signing_key).into(); +//! +//! // Sign +//! let data = b"hello world"; +//! let signature = signing_key.sign_with_rng(&mut rng, data); +//! assert_ne!(signature.as_bytes(), data); +//! +//! // Verify +//! verifying_key.verify(data, &signature).expect("failed to verify"); +//! ``` //! //! Using PSS signatures //! ``` @@ -204,8 +200,6 @@ pub use rand_core; pub mod algorithms; /// Error types. pub mod errors; -/// Supported hash functions. -pub mod hash; /// Supported padding schemes. pub mod padding; /// RSASSA-PKCS1-v1_5 Signature support @@ -222,7 +216,6 @@ mod raw; pub use pkcs1; pub use pkcs8; -pub use self::hash::Hash; pub use self::key::{PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; pub use self::padding::PaddingScheme; diff --git a/src/padding.rs b/src/padding.rs index 8655cb63..49d3a41c 100644 --- a/src/padding.rs +++ b/src/padding.rs @@ -3,15 +3,19 @@ use alloc::string::{String, ToString}; use core::fmt; use digest::{Digest, DynDigest}; +use pkcs8::AssociatedOid; -use crate::hash::Hash; +use crate::pkcs1v15; /// Available padding schemes. pub enum PaddingScheme { /// Encryption and Decryption using PKCS1v15 padding. PKCS1v15Encrypt, /// Sign and Verify using PKCS1v15 padding. - PKCS1v15Sign { hash: Option }, + PKCS1v15Sign { + hash_len: Option, + prefix: Box<[u8]>, + }, /// Encryption and Decryption using [OAEP padding](https://datatracker.ietf.org/doc/html/rfc3447#section-7.1.1). /// /// - `digest` is used to hash the label. The maximum possible plaintext length is `m = k - 2 * h_len - 2`, @@ -38,8 +42,8 @@ impl fmt::Debug for PaddingScheme { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { PaddingScheme::PKCS1v15Encrypt => write!(f, "PaddingScheme::PKCS1v15Encrypt"), - PaddingScheme::PKCS1v15Sign { ref hash } => { - write!(f, "PaddingScheme::PKCS1v15Sign({:?})", hash) + PaddingScheme::PKCS1v15Sign { prefix, .. } => { + write!(f, "PaddingScheme::PKCS1v15Sign({:?})", prefix) } PaddingScheme::OAEP { ref label, .. } => { // TODO: How to print the digest name? @@ -58,8 +62,21 @@ impl PaddingScheme { PaddingScheme::PKCS1v15Encrypt } - pub fn new_pkcs1v15_sign(hash: Option) -> Self { - PaddingScheme::PKCS1v15Sign { hash } + pub fn new_pkcs1v15_sign_raw() -> Self { + PaddingScheme::PKCS1v15Sign { + hash_len: None, + prefix: Box::new([]), + } + } + + pub fn new_pkcs1v15_sign() -> Self + where + D: Digest + AssociatedOid, + { + PaddingScheme::PKCS1v15Sign { + hash_len: Some(::output_size()), + prefix: pkcs1v15::generate_prefix::().into_boxed_slice(), + } } /// Create a new OAEP `PaddingScheme`, using `T` as the hash function for the default (empty) label, and `U` as the hash function for MGF1. diff --git a/src/pkcs1v15.rs b/src/pkcs1v15.rs index fb60aac3..b5ec29dc 100644 --- a/src/pkcs1v15.rs +++ b/src/pkcs1v15.rs @@ -4,6 +4,7 @@ use core::fmt::{Debug, Display, Formatter, LowerHex, UpperHex}; use core::marker::PhantomData; use core::ops::Deref; use digest::Digest; +use pkcs8::AssociatedOid; use rand_core::{CryptoRng, RngCore}; use signature::{ DigestSigner, DigestVerifier, RandomizedDigestSigner, RandomizedSigner, @@ -14,7 +15,6 @@ use zeroize::Zeroizing; use crate::dummy_rng::DummyRng; use crate::errors::{Error, Result}; -use crate::hash::{AssociatedHash, Hash}; use crate::key::{self, PrivateKey, PublicKey}; use crate::{RsaPrivateKey, RsaPublicKey}; @@ -160,12 +160,11 @@ pub(crate) fn decrypt( pub(crate) fn sign( rng: Option<&mut R>, priv_key: &SK, - hash: Option<&Hash>, + prefix: &[u8], hashed: &[u8], ) -> Result> { - let (hash_len, prefix) = hash_info(hash, hashed.len())?; - - let t_len = prefix.len() + hash_len; + let hash_len = hashed.len(); + let t_len = prefix.len() + hashed.len(); let k = priv_key.size(); if k < t_len + 11 { return Err(Error::MessageTooLong); @@ -186,13 +185,12 @@ pub(crate) fn sign( #[inline] pub(crate) fn verify( pub_key: &PK, - hash: Option<&Hash>, + prefix: &[u8], hashed: &[u8], sig: &[u8], ) -> Result<()> { - let (hash_len, prefix) = hash_info(hash, hashed.len())?; - - let t_len = prefix.len() + hash_len; + let hash_len = hashed.len(); + let t_len = prefix.len() + hashed.len(); let k = pub_key.size(); if k < t_len + 11 { return Err(Error::Verification); @@ -218,20 +216,26 @@ pub(crate) fn verify( Ok(()) } +// prefix = 0x30 0x30 0x06 oid 0x05 0x00 0x04 #[inline] -fn hash_info(hash: Option<&Hash>, digest_len: usize) -> Result<(usize, &'static [u8])> { - match hash { - Some(hash) => { - let hash_len = hash.size(); - if digest_len != hash_len { - return Err(Error::InputNotHashed); - } - - Ok((hash_len, hash.asn1_prefix())) - } - // this means the data is signed directly - None => Ok((digest_len, &[])), - } +pub(crate) fn generate_prefix() -> Vec +where + D: Digest + AssociatedOid, +{ + let oid = D::OID.as_bytes(); + let oid_len = oid.len() as u8; + let digest_len = ::output_size() as u8; + let mut v = vec![ + 0x30, + oid_len + 8 + digest_len, + 0x30, + oid_len + 4, + 0x6, + oid_len, + ]; + v.extend_from_slice(oid); + v.extend_from_slice(&[0x05, 0x00, 0x04, digest_len]); + v } /// Decrypts ciphertext using `priv_key` and blinds the operation if @@ -304,7 +308,7 @@ where D: Digest, { inner: RsaPrivateKey, - hash: Option, + prefix: Vec, phantom: PhantomData, } @@ -316,14 +320,14 @@ where &self.inner } - pub(crate) fn hash(&self) -> Option { - self.hash + pub(crate) fn prefix(&self) -> Vec { + self.prefix.clone() } pub fn new(key: RsaPrivateKey) -> Self { Self { inner: key, - hash: None, + prefix: Vec::new(), phantom: Default::default(), } } @@ -331,12 +335,12 @@ where impl SigningKey where - D: Digest + AssociatedHash, + D: Digest + AssociatedOid, { pub fn new_with_prefix(key: RsaPrivateKey) -> Self { Self { inner: key, - hash: Some(D::HASH), + prefix: generate_prefix::(), phantom: Default::default(), } } @@ -347,7 +351,7 @@ where D: Digest, { fn try_sign(&self, msg: &[u8]) -> signature::Result { - sign::(None, &self.inner, self.hash.as_ref(), &D::digest(msg)) + sign::(None, &self.inner, &self.prefix, &D::digest(msg)) .map(|v| v.into()) .map_err(|e| e.into()) } @@ -362,14 +366,9 @@ where mut rng: impl CryptoRng + RngCore, msg: &[u8], ) -> signature::Result { - sign( - Some(&mut rng), - &self.inner, - self.hash.as_ref(), - &D::digest(msg), - ) - .map(|v| v.into()) - .map_err(|e| e.into()) + sign(Some(&mut rng), &self.inner, &self.prefix, &D::digest(msg)) + .map(|v| v.into()) + .map_err(|e| e.into()) } } @@ -378,7 +377,7 @@ where D: Digest, { fn try_sign_digest(&self, digest: D) -> signature::Result { - sign::(None, &self.inner, self.hash.as_ref(), &digest.finalize()) + sign::(None, &self.inner, &self.prefix, &digest.finalize()) .map(|v| v.into()) .map_err(|e| e.into()) } @@ -396,7 +395,7 @@ where sign( Some(&mut rng), &self.inner, - self.hash.as_ref(), + &self.prefix, &digest.finalize(), ) .map(|v| v.into()) @@ -409,7 +408,7 @@ where D: Digest, { inner: RsaPublicKey, - hash: Option, + prefix: Vec, phantom: PhantomData, } @@ -420,7 +419,7 @@ where pub fn new(key: RsaPublicKey) -> Self { Self { inner: key, - hash: None, + prefix: Vec::new(), phantom: Default::default(), } } @@ -428,12 +427,12 @@ where impl VerifyingKey where - D: Digest + AssociatedHash, + D: Digest + AssociatedOid, { pub fn new_with_prefix(key: RsaPublicKey) -> Self { Self { inner: key, - hash: Some(D::HASH), + prefix: generate_prefix::(), phantom: Default::default(), } } @@ -446,7 +445,7 @@ where fn from(key: SigningKey) -> Self { Self { inner: key.key().into(), - hash: key.hash(), + prefix: key.prefix(), phantom: Default::default(), } } @@ -459,7 +458,7 @@ where fn from(key: &SigningKey) -> Self { Self { inner: key.key().into(), - hash: key.hash(), + prefix: key.prefix(), phantom: Default::default(), } } @@ -472,7 +471,7 @@ where fn verify(&self, msg: &[u8], signature: &Signature) -> signature::Result<()> { verify( &self.inner, - self.hash.as_ref(), + &self.prefix, &D::digest(msg), signature.as_ref(), ) @@ -487,7 +486,7 @@ where fn verify_digest(&self, digest: D, signature: &Signature) -> signature::Result<()> { verify( &self.inner, - self.hash.as_ref(), + &self.prefix, &digest.finalize(), signature.as_ref(), ) @@ -505,11 +504,11 @@ mod tests { use num_traits::Num; use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng}; use sha1::{Digest, Sha1}; - #[cfg(feature = "sha2")] use sha2::Sha256; + use sha3::Sha3_256; use signature::{RandomizedSigner, Signature, Signer, Verifier}; - use crate::{Hash, PaddingScheme, PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; + use crate::{PaddingScheme, PublicKey, PublicKeyParts, RsaPrivateKey, RsaPublicKey}; #[test] fn test_non_zero_bytes() { @@ -615,7 +614,7 @@ mod tests { let digest = Sha1::digest(text.as_bytes()).to_vec(); let out = priv_key - .sign(PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1)), &digest) + .sign(PaddingScheme::new_pkcs1v15_sign::(), &digest) .unwrap(); assert_ne!(out, digest); assert_eq!(out, expected); @@ -624,7 +623,7 @@ mod tests { let out2 = priv_key .sign_blinded( &mut rng, - PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1)), + PaddingScheme::new_pkcs1v15_sign::(), &digest, ) .unwrap(); @@ -632,11 +631,36 @@ mod tests { } } - #[cfg(feature = "sha2")] #[test] fn test_sign_pkcs1v15_signer() { let priv_key = get_private_key(); + let tests = [( + "Test.\n", + hex!( + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae" + ), + )]; + + let signing_key = SigningKey::::new_with_prefix(priv_key); + + for (text, expected) in &tests { + let out = signing_key.sign(text.as_bytes()); + assert_ne!(out.as_ref(), text.as_bytes()); + assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec()); + assert_eq!(out.as_ref(), expected); + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let out2 = signing_key.sign_with_rng(&mut rng, text.as_bytes()); + assert_eq!(out2.as_ref(), expected); + } + } + + #[test] + fn test_sign_pkcs1v15_signer_sha2_256() { + let priv_key = get_private_key(); + let tests = [( "Test.\n", hex!( @@ -650,7 +674,6 @@ mod tests { for (text, expected) in &tests { let out = signing_key.sign(text.as_bytes()); assert_ne!(out.as_ref(), text.as_bytes()); - assert_ne!(out.as_ref(), &Sha1::digest(text.as_bytes()).to_vec()); assert_eq!(out.as_ref(), expected); let mut rng = ChaCha8Rng::from_seed([42; 32]); @@ -659,7 +682,31 @@ mod tests { } } - #[cfg(feature = "sha2")] + #[test] + fn test_sign_pkcs1v15_signer_sha3_256() { + let priv_key = get_private_key(); + + let tests = [( + "Test.\n", + hex!( + "55e9fba3354dfb51d2c8111794ea552c86afc2cab154652c03324df8c2c51ba7" + "2ff7c14de59a6f9ba50d90c13a7537cc3011948369f1f0ec4a49d21eb7e723f9" + ), + )]; + + let signing_key = SigningKey::::new_with_prefix(priv_key); + + for (text, expected) in &tests { + let out = signing_key.sign(text.as_bytes()); + assert_ne!(out.as_ref(), text.as_bytes()); + assert_eq!(out.as_ref(), expected); + + let mut rng = ChaCha8Rng::from_seed([42; 32]); + let out2 = signing_key.sign_with_rng(&mut rng, text.as_bytes()); + assert_eq!(out2.as_ref(), expected); + } + } + #[test] fn test_sign_pkcs1v15_digest_signer() { let priv_key = get_private_key(); @@ -667,15 +714,15 @@ mod tests { let tests = [( "Test.\n", hex!( - "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea" - "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b" + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae" ), )]; let signing_key = SigningKey::new_with_prefix(priv_key); for (text, expected) in &tests { - let mut digest = Sha256::new(); + let mut digest = Sha1::new(); digest.update(text.as_bytes()); let out = signing_key.sign_digest(digest); assert_ne!(out.as_ref(), text.as_bytes()); @@ -683,7 +730,7 @@ mod tests { assert_eq!(out.as_ref(), expected); let mut rng = ChaCha8Rng::from_seed([42; 32]); - let mut digest = Sha256::new(); + let mut digest = Sha1::new(); digest.update(text.as_bytes()); let out2 = signing_key.sign_digest_with_rng(&mut rng, digest); assert_eq!(out2.as_ref(), expected); @@ -717,11 +764,7 @@ mod tests { for (text, sig, expected) in &tests { let digest = Sha1::digest(text.as_bytes()).to_vec(); - let result = pub_key.verify( - PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA1)), - &digest, - sig, - ); + let result = pub_key.verify(PaddingScheme::new_pkcs1v15_sign::(), &digest, sig); match expected { true => result.expect("failed to verify"), false => { @@ -732,7 +775,6 @@ mod tests { } } - #[cfg(feature = "sha2")] #[test] fn test_verify_pkcs1v15_signer() { let priv_key = get_private_key(); @@ -741,22 +783,22 @@ mod tests { ( "Test.\n", hex!( - "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea" - "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b" + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae" ), true, ), ( "Test.\n", hex!( - "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea" - "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451c" + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af" ), false, ), ]; let pub_key: RsaPublicKey = priv_key.into(); - let verifying_key = VerifyingKey::::new_with_prefix(pub_key); + let verifying_key = VerifyingKey::::new_with_prefix(pub_key); for (text, sig, expected) in &tests { let result = @@ -771,7 +813,6 @@ mod tests { } } - #[cfg(feature = "sha2")] #[test] fn test_verify_pkcs1v15_digest_signer() { let priv_key = get_private_key(); @@ -780,16 +821,16 @@ mod tests { ( "Test.\n", hex!( - "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea" - "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451b" + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362ae" ), true, ), ( "Test.\n", hex!( - "2ffae3f3e130287b3a1dcb320e46f52e8f3f7969b646932273a7e3a6f2a182ea" - "02d42875a7ffa4a148aa311f9e4b562e4e13a2223fb15f4e5bf5f2b206d9451c" + "a4f3fa6ea93bcdd0c57be020c1193ecbfd6f200a3d95c409769b029578fa0e33" + "6ad9a347600e40d3ae823b8c7e6bad88cc07c1d54c3a1523cbbb6d58efc362af" ), false, ), @@ -798,7 +839,7 @@ mod tests { let verifying_key = VerifyingKey::new_with_prefix(pub_key); for (text, sig, expected) in &tests { - let mut digest = Sha256::new(); + let mut digest = Sha1::new(); digest.update(text.as_bytes()); let result = verifying_key.verify_digest(digest, &Signature::from_bytes(sig).unwrap()); match expected { @@ -817,13 +858,13 @@ mod tests { let priv_key = get_private_key(); let sig = priv_key - .sign(PaddingScheme::new_pkcs1v15_sign(None), msg) + .sign(PaddingScheme::new_pkcs1v15_sign_raw(), msg) .unwrap(); assert_eq!(expected_sig, sig); let pub_key: RsaPublicKey = priv_key.into(); pub_key - .verify(PaddingScheme::new_pkcs1v15_sign(None), msg, &sig) + .verify(PaddingScheme::new_pkcs1v15_sign_raw(), msg, &sig) .expect("failed to verify"); }