Skip to content

Commit 40242fb

Browse files
authored
Implement Signer/Verifier/Signature interfaces for the RSA signatures (#174)
Refactor the `rsa` crate to use the API defined by the signature crate. This adds `pss` and `pkcs1v15` modules, each of them providing `Signature`, `Verifier` and `Signer`/`RandomizedSigner` implementations. Add tests for pkcs1v15 and pss signature verification functions to check that verifying invalid signatures returns an error. Signed-off-by: Dmitry Baryshkov <[email protected]>
1 parent e7f4810 commit 40242fb

File tree

7 files changed

+731
-56
lines changed

7 files changed

+731
-56
lines changed

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ subtle = { version = "2.1.1", default-features = false }
2323
digest = { version = "0.10.0", default-features = false, features = ["alloc"] }
2424
pkcs1 = { version = "0.4", default-features = false, features = ["pkcs8", "alloc"] }
2525
pkcs8 = { version = "0.9", default-features = false, features = ["alloc"] }
26+
#To keep the rand_core versions properly pinnen, specify exact version
27+
signature = { version = ">=1.5, <1.7", default-features = false , features = ["rand-preview"] }
2628
zeroize = { version = "1", features = ["alloc"] }
2729

2830
# Temporary workaround until https://github.com/dignifiedquire/num-bigint/pull/42 lands
@@ -55,7 +57,7 @@ default = ["std", "pem"]
5557
nightly = ["num-bigint/nightly"]
5658
serde = ["num-bigint/serde", "serde_crate"]
5759
expose-internals = []
58-
std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std"]
60+
std = ["digest/std", "pkcs1/std", "pkcs8/std", "rand_core/std", "signature/std"]
5961
pem = ["pkcs1/pem", "pkcs8/pem"]
6062
pkcs5 = ["pkcs8/encryption"]
6163
getrandom = ["rand_core/getrandom"]

src/dummy_rng.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use rand_core::{CryptoRng, RngCore};
2+
3+
/// This is a dummy RNG for cases when we need a concrete RNG type
4+
/// which does not get used.
5+
#[derive(Copy, Clone)]
6+
pub(crate) struct DummyRng;
7+
8+
impl RngCore for DummyRng {
9+
fn next_u32(&mut self) -> u32 {
10+
unimplemented!();
11+
}
12+
13+
fn next_u64(&mut self) -> u64 {
14+
unimplemented!();
15+
}
16+
17+
fn fill_bytes(&mut self, _: &mut [u8]) {
18+
unimplemented!();
19+
}
20+
21+
fn try_fill_bytes(&mut self, _: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
22+
unimplemented!();
23+
}
24+
}
25+
26+
impl CryptoRng for DummyRng {}

src/errors.rs

+14
Original file line numberDiff line numberDiff line change
@@ -64,3 +64,17 @@ impl From<pkcs8::Error> for Error {
6464
Error::Pkcs8(err)
6565
}
6666
}
67+
68+
#[cfg(feature = "std")]
69+
impl From<Error> for signature::Error {
70+
fn from(err: Error) -> Self {
71+
Self::from_source(err)
72+
}
73+
}
74+
75+
#[cfg(not(feature = "std"))]
76+
impl From<Error> for signature::Error {
77+
fn from(_err: Error) -> Self {
78+
Self::new()
79+
}
80+
}

src/key.rs

+1-25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use serde_crate::{Deserialize, Serialize};
1010
use zeroize::Zeroize;
1111

1212
use crate::algorithms::{generate_multi_prime_key, generate_multi_prime_key_with_exp};
13+
use crate::dummy_rng::DummyRng;
1314
use crate::errors::{Error, Result};
1415

1516
use crate::padding::PaddingScheme;
@@ -586,31 +587,6 @@ fn check_public_with_max_size(public_key: &impl PublicKeyParts, max_size: usize)
586587
Ok(())
587588
}
588589

589-
/// This is a dummy RNG for cases when we need a concrete RNG type
590-
/// which does not get used.
591-
#[derive(Copy, Clone)]
592-
struct DummyRng;
593-
594-
impl RngCore for DummyRng {
595-
fn next_u32(&mut self) -> u32 {
596-
unimplemented!();
597-
}
598-
599-
fn next_u64(&mut self) -> u64 {
600-
unimplemented!();
601-
}
602-
603-
fn fill_bytes(&mut self, _: &mut [u8]) {
604-
unimplemented!();
605-
}
606-
607-
fn try_fill_bytes(&mut self, _: &mut [u8]) -> core::result::Result<(), rand_core::Error> {
608-
unimplemented!();
609-
}
610-
}
611-
612-
impl CryptoRng for DummyRng {}
613-
614590
#[cfg(test)]
615591
mod tests {
616592
use super::*;

src/lib.rs

+53-2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,54 @@
4747
//! assert_eq!(&data[..], &dec_data[..]);
4848
//! ```
4949
//!
50+
//! Using PKCS1v15 signatures
51+
//! ```
52+
//! use rsa::{Hash, 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::new_with_hash(private_key, Hash::SHA2_256);
62+
//! let verifying_key: VerifyingKey = (&signing_key).into();
63+
//!
64+
//! // Sign
65+
//! let data = b"hello world";
66+
//! let digest = Sha256::digest(data).to_vec();
67+
//! let signature = signing_key.sign_with_rng(&mut rng, &digest);
68+
//! assert_ne!(signature.as_bytes(), data);
69+
//!
70+
//! // Verify
71+
//! verifying_key.verify(&digest, &signature).expect("failed to verify");
72+
//! ```
73+
//!
74+
//! Using PSS signatures
75+
//! ```
76+
//! use rsa::{Hash, RsaPrivateKey};
77+
//! use rsa::pss::{BlindedSigningKey, VerifyingKey};
78+
//! use sha2::{Digest, Sha256};
79+
//! use signature::{RandomizedSigner, Signature, Verifier};
80+
//!
81+
//! let mut rng = rand::thread_rng();
82+
//!
83+
//! let bits = 2048;
84+
//! let private_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key");
85+
//! let signing_key = BlindedSigningKey::new(private_key, Box::new(Sha256::new()));
86+
//! let verifying_key: VerifyingKey = (&signing_key).into();
87+
//!
88+
//! // Sign
89+
//! let data = b"hello world";
90+
//! let digest = Sha256::digest(data).to_vec();
91+
//! let signature = signing_key.sign_with_rng(&mut rng, &digest);
92+
//! assert_ne!(signature.as_bytes(), data);
93+
//!
94+
//! // Verify
95+
//! verifying_key.verify(&digest, &signature).expect("failed to verify");
96+
//! ```
97+
//!
5098
//! ## PKCS#1 RSA Key Encoding
5199
//!
52100
//! PKCS#1 is a legacy format for encoding RSA keys as binary (DER) or text
@@ -158,12 +206,15 @@ pub mod errors;
158206
pub mod hash;
159207
/// Supported padding schemes.
160208
pub mod padding;
209+
/// RSASSA-PKCS1-v1_5 Signature support
210+
pub mod pkcs1v15;
211+
/// RSASSA-PSS Signature support
212+
pub mod pss;
161213

214+
mod dummy_rng;
162215
mod encoding;
163216
mod key;
164217
mod oaep;
165-
mod pkcs1v15;
166-
mod pss;
167218
mod raw;
168219

169220
pub use pkcs1;

0 commit comments

Comments
 (0)