Skip to content

pkcs1v15: use AssociatedOID for getting the RSA prefix #183

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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 = []
Expand All @@ -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]
Expand Down
137 changes: 0 additions & 137 deletions src/hash.rs

This file was deleted.

27 changes: 21 additions & 6 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -509,8 +514,13 @@ impl RsaPrivateKey {
pub fn sign(&self, padding: PaddingScheme, digest_in: &[u8]) -> Result<Vec<u8>> {
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::<DummyRng, _>(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::<DummyRng, _>(None, self, prefix.as_ref(), digest_in)
}
_ => Err(Error::InvalidPaddingScheme),
}
Expand Down Expand Up @@ -544,8 +554,13 @@ impl RsaPrivateKey {
digest_in: &[u8],
) -> Result<Vec<u8>> {
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,
Expand Down
51 changes: 22 additions & 29 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Sha256>::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::<Sha256>::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
//! ```
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down
29 changes: 23 additions & 6 deletions src/padding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Hash> },
PKCS1v15Sign {
hash_len: Option<usize>,
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`,
Expand All @@ -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?
Expand All @@ -58,8 +62,21 @@ impl PaddingScheme {
PaddingScheme::PKCS1v15Encrypt
}

pub fn new_pkcs1v15_sign(hash: Option<Hash>) -> Self {
PaddingScheme::PKCS1v15Sign { hash }
pub fn new_pkcs1v15_sign_raw() -> Self {
PaddingScheme::PKCS1v15Sign {
hash_len: None,
prefix: Box::new([]),
}
}

pub fn new_pkcs1v15_sign<D>() -> Self
where
D: Digest + AssociatedOid,
{
PaddingScheme::PKCS1v15Sign {
hash_len: Some(<D as Digest>::output_size()),
prefix: pkcs1v15::generate_prefix::<D>().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.
Expand Down
Loading