Skip to content

Commit d7384bc

Browse files
committed
pkcs1v15: use AssociatedOID for getting the RSA prefix
Drop internal implementation of AssociatedHash and use AssociatedOID trait to get the OID corresponding to the Digest and to format the ASN.1 prefix. Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent 9b3858f commit d7384bc

File tree

5 files changed

+113
-161
lines changed

5 files changed

+113
-161
lines changed

Cargo.toml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ num-iter = { version = "0.1.37", default-features = false }
2020
rand_core = { version = "0.6", default-features = false }
2121
byteorder = { version = "1.3.1", default-features = false }
2222
subtle = { version = "2.1.1", default-features = false }
23-
digest = { version = "0.10.0", default-features = false, features = ["alloc"] }
23+
digest = { version = "0.10.0", default-features = false, features = ["alloc", "oid"] }
2424
pkcs1 = { version = "0.4", default-features = false, features = ["pkcs8", "alloc"] }
2525
pkcs8 = { version = "0.9", default-features = false, features = ["alloc"] }
2626
#To keep the rand_core versions properly pinnen, specify exact version
@@ -30,11 +30,6 @@ zeroize = { version = "1", features = ["alloc"] }
3030
# Temporary workaround until https://github.com/dignifiedquire/num-bigint/pull/42 lands
3131
smallvec = { version = "1.6.1", default-features = false }
3232

33-
# Temporary until the link from Digest to OID is moved to corresponding crates
34-
sha1 = { version = "0.10.1", default-features = false, optional = true }
35-
sha2 = { version = "0.10.2", default-features = false, optional = true }
36-
sha3 = { version = "0.10.1", default-features = false, optional = true }
37-
3833
[dependencies.serde_crate]
3934
package = "serde"
4035
optional = true
@@ -50,15 +45,15 @@ rand_xorshift = "0.3"
5045
rand_chacha = "0.3"
5146
rand = "0.8"
5247
rand_core = { version = "0.6", default-features = false }
53-
sha1 = { version = "0.10.1", default-features = false }
54-
sha2 = { version = "0.10.2", default-features = false }
48+
sha1 = { version = "0.10.1", default-features = false, features = ["oid"] }
49+
sha2 = { version = "0.10.2", default-features = false, features = ["oid"] }
5550
sha3 = { version = "0.10.1", default-features = false }
5651

5752
[[bench]]
5853
name = "key"
5954

6055
[features]
61-
default = ["std", "pem", "sha2"]
56+
default = ["std", "pem"]
6257
nightly = ["num-bigint/nightly"]
6358
serde = ["num-bigint/serde", "serde_crate"]
6459
expose-internals = []
@@ -68,7 +63,7 @@ pkcs5 = ["pkcs8/encryption"]
6863
getrandom = ["rand_core/getrandom"]
6964

7065
[package.metadata.docs.rs]
71-
features = ["std", "pem", "serde", "expose-internals", "sha1", "sha2", "sha3"]
66+
features = ["std", "pem", "serde", "expose-internals"]
7267
rustdoc-args = ["--cfg", "docsrs"]
7368

7469
[profile.dev]

src/hash.rs

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -83,55 +83,3 @@ impl Hash {
8383
}
8484
}
8585
}
86-
87-
/* FIXME: This trait should be refactored into per-digest implementations returning OID */
88-
pub trait AssociatedHash {
89-
const HASH: Hash;
90-
}
91-
92-
#[cfg(feature = "sha1")]
93-
impl AssociatedHash for sha1::Sha1 {
94-
const HASH: Hash = Hash::SHA1;
95-
}
96-
97-
#[cfg(feature = "sha2")]
98-
impl AssociatedHash for sha2::Sha224 {
99-
const HASH: Hash = Hash::SHA2_224;
100-
}
101-
102-
#[cfg(feature = "sha2")]
103-
impl AssociatedHash for sha2::Sha256 {
104-
const HASH: Hash = Hash::SHA2_256;
105-
}
106-
107-
#[cfg(feature = "sha2")]
108-
impl AssociatedHash for sha2::Sha384 {
109-
const HASH: Hash = Hash::SHA2_384;
110-
}
111-
112-
#[cfg(feature = "sha2")]
113-
impl AssociatedHash for sha2::Sha512 {
114-
const HASH: Hash = Hash::SHA2_512;
115-
}
116-
117-
/*
118-
#[cfg(feature = "sha3")]
119-
impl AssociatedHash for sha3::Sha3_224 {
120-
const HASH: Hash = Hash::SHA3_224;
121-
}
122-
*/
123-
124-
#[cfg(feature = "sha3")]
125-
impl AssociatedHash for sha3::Sha3_256 {
126-
const HASH: Hash = Hash::SHA3_256;
127-
}
128-
129-
#[cfg(feature = "sha3")]
130-
impl AssociatedHash for sha3::Sha3_384 {
131-
const HASH: Hash = Hash::SHA3_384;
132-
}
133-
134-
#[cfg(feature = "sha3")]
135-
impl AssociatedHash for sha3::Sha3_512 {
136-
const HASH: Hash = Hash::SHA3_512;
137-
}

src/key.rs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use zeroize::Zeroize;
1212
use crate::algorithms::{generate_multi_prime_key, generate_multi_prime_key_with_exp};
1313
use crate::dummy_rng::DummyRng;
1414
use crate::errors::{Error, Result};
15+
use crate::hash::Hash;
1516

1617
use crate::padding::PaddingScheme;
1718
use crate::raw::{DecryptionPrimitive, EncryptionPrimitive};
@@ -217,7 +218,8 @@ impl PublicKey for RsaPublicKey {
217218
fn verify(&self, padding: PaddingScheme, hashed: &[u8], sig: &[u8]) -> Result<()> {
218219
match padding {
219220
PaddingScheme::PKCS1v15Sign { ref hash } => {
220-
pkcs1v15::verify(self, hash.as_ref(), hashed, sig)
221+
let prefix = hash_info(*hash, hashed.len())?;
222+
pkcs1v15::verify(self, prefix, hashed, sig)
221223
}
222224
PaddingScheme::PSS { mut digest, .. } => pss::verify(self, hashed, sig, &mut *digest),
223225
_ => Err(Error::InvalidPaddingScheme),
@@ -510,7 +512,8 @@ impl RsaPrivateKey {
510512
match padding {
511513
// need to pass any Rng as the type arg, so the type checker is happy, it is not actually used for anything
512514
PaddingScheme::PKCS1v15Sign { ref hash } => {
513-
pkcs1v15::sign::<DummyRng, _>(None, self, hash.as_ref(), digest_in)
515+
let prefix = hash_info(*hash, digest_in.len())?;
516+
pkcs1v15::sign::<DummyRng, _>(None, self, prefix, digest_in)
514517
}
515518
_ => Err(Error::InvalidPaddingScheme),
516519
}
@@ -545,7 +548,8 @@ impl RsaPrivateKey {
545548
) -> Result<Vec<u8>> {
546549
match padding {
547550
PaddingScheme::PKCS1v15Sign { ref hash } => {
548-
pkcs1v15::sign(Some(rng), self, hash.as_ref(), digest_in)
551+
let prefix = hash_info(*hash, digest_in.len())?;
552+
pkcs1v15::sign(Some(rng), self, prefix, digest_in)
549553
}
550554
PaddingScheme::PSS {
551555
mut digest,
@@ -556,6 +560,22 @@ impl RsaPrivateKey {
556560
}
557561
}
558562

563+
#[inline]
564+
fn hash_info(hash: Option<Hash>, digest_len: usize) -> Result<&'static [u8]> {
565+
match hash {
566+
Some(hash) => {
567+
let hash_len = hash.size();
568+
if digest_len != hash_len {
569+
return Err(Error::InputNotHashed);
570+
}
571+
572+
Ok(hash.asn1_prefix())
573+
}
574+
// this means the data is signed directly
575+
None => Ok(&[]),
576+
}
577+
}
578+
559579
/// Check that the public key is well formed and has an exponent within acceptable bounds.
560580
#[inline]
561581
pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> {

src/lib.rs

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,32 +47,28 @@
4747
//! assert_eq!(&data[..], &dec_data[..]);
4848
//! ```
4949
//!
50-
#![cfg_attr(
51-
feature = "sha2",
52-
doc = r#"
53-
Using PKCS1v15 signatures
54-
```
55-
use rsa::RsaPrivateKey;
56-
use rsa::pkcs1v15::{SigningKey, VerifyingKey};
57-
use sha2::{Digest, Sha256};
58-
use signature::{RandomizedSigner, Signature, Verifier};
59-
60-
let mut rng = rand::thread_rng();
61-
62-
let bits = 2048;
63-
let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
64-
let signing_key = SigningKey::<Sha256>::new_with_prefix(private_key);
65-
let verifying_key: VerifyingKey<_> = (&signing_key).into();
66-
67-
// Sign
68-
let data = b"hello world";
69-
let signature = signing_key.sign_with_rng(&mut rng, data);
70-
assert_ne!(signature.as_bytes(), data);
71-
72-
// Verify
73-
verifying_key.verify(data, &signature).expect("failed to verify");
74-
```"#
75-
)]
50+
//! Using PKCS1v15 signatures
51+
//! ```
52+
//! use rsa::RsaPrivateKey;
53+
//! use rsa::pkcs1v15::{SigningKey, VerifyingKey};
54+
//! use sha2::{Digest, Sha256};
55+
//! use signature::{RandomizedSigner, Signature, Verifier};
56+
//!
57+
//! let mut rng = rand::thread_rng();
58+
//!
59+
//! let bits = 2048;
60+
//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
61+
//! let signing_key = SigningKey::<Sha256>::new_with_prefix(private_key);
62+
//! let verifying_key: VerifyingKey<_> = (&signing_key).into();
63+
//!
64+
//! // Sign
65+
//! let data = b"hello world";
66+
//! let signature = signing_key.sign_with_rng(&mut rng, data);
67+
//! assert_ne!(signature.as_bytes(), data);
68+
//!
69+
//! // Verify
70+
//! verifying_key.verify(data, &signature).expect("failed to verify");
71+
//! ```
7672
//!
7773
//! Using PSS signatures
7874
//! ```

0 commit comments

Comments
 (0)