Skip to content
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
6 changes: 4 additions & 2 deletions checkct/driver/src/raw_rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ pub fn rsa_decrypt_unblinded_non_crt_128() {

// Public modulus (2^64 - 59) * (2^64 - 83), with fixed 128-bit precision.
let n = BoxedUint::from_be_hex("FFFFFFFFFFFFFF720000000000001321", 128).unwrap();
let public = RsaPublicKey::new(n, BoxedUint::from(65537u64)).unwrap();
let public =
RsaPublicKey::new_with_size_limits(n, BoxedUint::from(65537u64), 128..=128).unwrap();

let mut bytes = [0u8; 16];
PrivateRng.fill_bytes(&mut bytes);
Expand Down Expand Up @@ -107,7 +108,8 @@ pub fn rsa_decrypt_unblinded_crt_128() {
unsafe { crate::allocator::reset() };

let n = BoxedUint::from_be_hex("FFFFFFFFFFFFFF720000000000001321", 128).unwrap();
let public = RsaPublicKey::new(n, BoxedUint::from(65537u64)).unwrap();
let public =
RsaPublicKey::new_with_size_limits(n, BoxedUint::from(65537u64), 128..=128).unwrap();
let p = secret_modulus_64();
let q = secret_modulus_64();
let primes = vec![p.modulus().clone(), q.modulus().clone()];
Expand Down
67 changes: 49 additions & 18 deletions src/key.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use alloc::vec::Vec;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::ops::RangeInclusive;

use crypto_bigint::{
BoxedUint, ConcatenatingMul, Integer, NonZero, Odd, Resize,
Expand Down Expand Up @@ -232,26 +233,51 @@ impl RsaPublicKey {
/// If for some reason you have a legitimate reason to use keys with public exponents larger
/// than this value, use the special APIs:
///
/// - [`RsaPublicKey::new_with_max_size`]
/// - [`RsaPublicKey::new_unchecked`]
/// - [`RsaPrivateKey::from_components_with_large_exponent`]
pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;

/// Maximum size of the modulus `n` in bits.
/// Default minimum size of the modulus `n` in bits.
pub const MIN_SIZE: usize = 1024;

/// Default maximum size of the modulus `n` in bits.
pub const MAX_SIZE: usize = 8192;

/// Create a new public key from its components.
///
/// This function accepts public keys with a modulus size up to 8192-bits,
/// i.e. [`RsaPublicKey::MAX_SIZE`].
/// Accepts modulus sizes from [`Self::MIN_SIZE`] to [`Self::MAX_SIZE`], inclusive.
/// Use [`Self::new_with_size_limits`] to explicitly allow other sizes.
#[allow(clippy::missing_errors_doc, reason = "TODO")]
pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
Self::new_with_max_size(n, e, Self::MAX_SIZE)
Self::new_with_size_limits(n, e, Self::MIN_SIZE..=Self::MAX_SIZE)
}

/// Create a new public key from its components.
#[allow(clippy::missing_errors_doc, reason = "TODO")]
pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
check_public_with_max_size(&n, &e, Some(max_size))?;
/// Create a new public key with explicit, inclusive modulus size limits in bits.
///
/// All other public-key checks still apply. Allowing a smaller minimum can admit insecure
/// keys and is intended for testing or compatibility with legacy systems.
///
/// For encoded keys outside the default limits, decode the components with the `pkcs1`
/// crate and pass them to this constructor explicitly.
///
/// # Errors
/// Returns [`Error::InvalidArguments`] for an empty range, [`Error::ModulusTooSmall`] or
/// [`Error::ModulusTooLarge`] for a modulus outside the range, or an error if the modulus
/// or public exponent is invalid.
pub fn new_with_size_limits(
n: BoxedUint,
e: BoxedUint,
size_range_bits: RangeInclusive<usize>,
) -> Result<Self> {
if size_range_bits.is_empty() {
return Err(Error::InvalidArguments);
}

if (n.bits_vartime() as usize) < *size_range_bits.start() {
return Err(Error::ModulusTooSmall);
}

check_public_with_max_size(&n, &e, Some(*size_range_bits.end()))?;

let n_odd = Odd::new(n.clone())
.into_option()
Expand All @@ -262,12 +288,19 @@ impl RsaPublicKey {
Ok(Self { n, e, n_params })
}

/// Create a new public key with the default minimum modulus size and a custom maximum.
#[deprecated(since = "0.10.0", note = "please use `new_with_size_limits` instead")]
#[allow(clippy::missing_errors_doc, reason = "TODO")]
pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
Self::new_with_size_limits(n, e, Self::MIN_SIZE..=max_size)
}

/// Create a new public key, bypassing checks around the modulus and public
/// exponent size.
///
/// This method is not recommended, and only intended for unusual use cases.
/// Most applications should use [`RsaPublicKey::new`] or
/// [`RsaPublicKey::new_with_max_size`] instead.
/// [`RsaPublicKey::new_with_size_limits`] instead.
#[must_use]
pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
let n_odd = Odd::new(n.clone()).expect("n must be odd");
Expand Down Expand Up @@ -296,9 +329,6 @@ impl RsaPrivateKey {
/// Default exponent for RSA keys.
const EXP: u64 = 65537;

/// Minimum size of the modulus `n` in bits. Currently only applies to keygen.
const MIN_SIZE: u32 = 1024;

/// Generate a new RSA key pair with a modulus of the given bit size using the passed in `rng`.
///
/// # Errors
Expand Down Expand Up @@ -330,7 +360,7 @@ impl RsaPrivateKey {
bit_size: usize,
exp: BoxedUint,
) -> Result<RsaPrivateKey> {
if bit_size < Self::MIN_SIZE as usize {
if bit_size < RsaPublicKey::MIN_SIZE {
return Err(Error::ModulusTooSmall);
}

Expand Down Expand Up @@ -1178,7 +1208,7 @@ mod tests {
fn test_serde() {
use rand::rngs::ChaCha8Rng;
use rand_core::SeedableRng;
use serde_test::{Configure, Token, assert_tokens};
use serde_test::{Configure, Token, assert_ser_tokens, assert_tokens};

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
Expand All @@ -1190,12 +1220,13 @@ mod tests {
))];
assert_tokens(&priv_key.clone().readable(), &priv_tokens);

let priv_tokens = [Token::Str(
let pub_tokens = [Token::Str(
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
)];
assert_tokens(
// Small public keys can still be serialized, but default decoding rejects them.
assert_ser_tokens(
&RsaPublicKey::from(priv_key.clone()).readable(),
&priv_tokens,
&pub_tokens,
);
}

Expand Down
17 changes: 7 additions & 10 deletions src/oaep/encrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,27 +74,24 @@ where
mod tests {

#[test]
#[cfg(all(feature = "hazmat", feature = "serde"))]
#[cfg(feature = "serde")]
fn test_serde() {
use super::*;
use rand::rngs::ChaCha8Rng;
use rand_core::SeedableRng;
use pkcs8::DecodePublicKey;
use serde_test::{Configure, Token, assert_tokens};

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key =
crate::RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let encrypting_key = EncryptingKey::<sha2::Sha256>::new(priv_key.to_public_key());
let der = include_bytes!("../../tests/examples/pkcs8/rsa2048-pub.der");
let pub_key = RsaPublicKey::from_public_key_der(der).unwrap();
let encoded = include_str!("../../tests/examples/pkcs8/rsa2048-pub.hex").trim();
let encrypting_key = EncryptingKey::<sha2::Sha256>::new(pub_key);

let tokens = [
Token::Struct {
name: "EncryptingKey",
len: 4,
},
Token::Str("inner"),
Token::Str(
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
),
Token::Str(encoded),
Token::Str("label"),
Token::None,
Token::Str("phantom"),
Expand Down
17 changes: 7 additions & 10 deletions src/pkcs1v15/encrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,24 @@ impl RandomizedEncryptor for EncryptingKey {
#[cfg(test)]
mod tests {
#[test]
#[cfg(all(feature = "hazmat", feature = "serde"))]
#[cfg(feature = "serde")]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand::rngs::ChaCha8Rng;
use rand_core::SeedableRng;
use pkcs8::DecodePublicKey;
use serde_test::{Configure, Token, assert_tokens};

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let encrypting_key = EncryptingKey::new(priv_key.to_public_key());
let der = include_bytes!("../../tests/examples/pkcs8/rsa2048-pub.der");
let pub_key = RsaPublicKey::from_public_key_der(der).unwrap();
let encoded = include_str!("../../tests/examples/pkcs8/rsa2048-pub.hex").trim();
let encrypting_key = EncryptingKey::new(pub_key);

let tokens = [
Token::Struct {
name: "EncryptingKey",
len: 1,
},
Token::Str("inner"),
Token::Str(
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
),
Token::Str(encoded),
Token::StructEnd,
];
assert_tokens(&encrypting_key.clone().readable(), &tokens);
Expand Down
16 changes: 6 additions & 10 deletions src/pkcs1v15/verifying_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -249,23 +249,19 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(all(feature = "hazmat", feature = "serde"))]
#[cfg(feature = "serde")]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand::rngs::ChaCha8Rng;
use rand_core::SeedableRng;
use pkcs8::DecodePublicKey;
use serde_test::{Configure, Token, assert_tokens};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let pub_key = priv_key.to_public_key();
let der = include_bytes!("../../tests/examples/pkcs8/rsa2048-pub.der");
let pub_key = RsaPublicKey::from_public_key_der(der).unwrap();
let encoded = include_str!("../../tests/examples/pkcs8/rsa2048-pub.hex").trim();
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);

let tokens = [Token::Str(
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
)];
let tokens = [Token::Str(encoded)];

assert_tokens(&verifying_key.readable(), &tokens);
}
Expand Down
16 changes: 6 additions & 10 deletions src/pss/verifying_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,23 +246,19 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(all(feature = "hazmat", feature = "serde"))]
#[cfg(feature = "serde")]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand::rngs::ChaCha8Rng;
use rand_core::SeedableRng;
use pkcs8::DecodePublicKey;
use serde_test::{Configure, Token, assert_tokens};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let pub_key = priv_key.to_public_key();
let der = include_bytes!("../../tests/examples/pkcs8/rsa2048-pub.der");
let pub_key = RsaPublicKey::from_public_key_der(der).unwrap();
let encoded = include_str!("../../tests/examples/pkcs8/rsa2048-pub.hex").trim();
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);

let tokens = [Token::Str(
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
)];
let tokens = [Token::Str(encoded)];

assert_tokens(&verifying_key.readable(), &tokens);
}
Expand Down
1 change: 1 addition & 0 deletions tests/examples/pkcs8/rsa2048-pub.hex
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
30820122300d06092a864886f70d01010105000382010f003082010a0282010100b6c42c515f10a6aaf282c63edbe24243a170f3fa2633bd4833637f47ca4f6f36e03a5d29efc3191ac80f390d874b39e30f414fcec1fca0ed81e547edc2cd382c76f61c9018973db9fa537972a7c701f6b77e0982dfc15fc01927ee5e7cd94b4f599ff07013a7c8281bdf22dcbc9ad7cabb7c4311c982f58edb7213ad4558b332266d743aed8192d1884cadb8b14739a8dada66dc970806d9c7ac450cb13d0d7c575fb198534fc61bc41bc0f0574e0e0130c7bbbfbdfdc9f6a6e2e3e2aff1cbeac89ba57884528d55cfb08327a1e8c89f4e003cf2888e933241d9d695bcbbacdc90b44e3e095fa37058ea25b13f5e295cbeac6de838ab8c50af61e298975b872f0203010001
Loading
Loading