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
4 changes: 4 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ pub enum Error {
/// Invalid coefficient.
InvalidCoefficient,

/// Modulus too small.
ModulusTooSmall,

/// Modulus too large.
ModulusTooLarge,

Expand Down Expand Up @@ -94,6 +97,7 @@ impl core::fmt::Display for Error {
Error::InvalidModulus => write!(f, "invalid modulus"),
Error::InvalidExponent => write!(f, "invalid exponent"),
Error::InvalidCoefficient => write!(f, "invalid coefficient"),
Error::ModulusTooSmall => write!(f, "modulus too small"),
Error::ModulusTooLarge => write!(f, "modulus too large"),
Error::PublicExponentTooSmall => write!(f, "public exponent too small"),
Error::PublicExponentTooLarge => write!(f, "public exponent too large"),
Expand Down
55 changes: 49 additions & 6 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -272,19 +272,62 @@ impl RsaPrivateKey {
/// Default exponent for RSA keys.
const EXP: u64 = 65537;

/// Generate a new Rsa key pair of the given bit size using the passed in `rng`.
pub fn new<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<RsaPrivateKey> {
Self::new_with_exp(rng, bit_size, BoxedUint::from(Self::EXP))
/// 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
/// - If `bit_size` is lower than the minimum 1024-bits.
pub fn new<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
Self::new_with_exp(rng, bit_size, Self::EXP.into())
}

/// Generate a new RSA key pair of the given bit size.
///
/// #⚠️Warning: Hazmat!
/// This version does not apply minimum key size checks, and as such may generate keys
/// which are insecure!
#[cfg(feature = "hazmat")]
pub fn new_unchecked<R: CryptoRng + ?Sized>(rng: &mut R, bit_size: usize) -> Result<Self> {
Self::new_with_exp_unchecked(rng, bit_size, Self::EXP.into())
}

/// Generate a new RSA key pair of the given bit size and the public exponent
/// using the passed in `rng`.
///
/// Unless you have specific needs, you should use `RsaPrivateKey::new` instead.
/// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
pub fn new_with_exp<R: CryptoRng + ?Sized>(
rng: &mut R,
bit_size: usize,
exp: BoxedUint,
) -> Result<RsaPrivateKey> {
if bit_size < Self::MIN_SIZE as usize {
return Err(Error::ModulusTooSmall);
}

let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
RsaPrivateKey::from_components(
components.n.get(),
components.e,
components.d,
components.primes,
)
}

/// Generate a new RSA key pair of the given bit size and the public exponent
/// using the passed in `rng`.
///
/// Unless you have specific needs, you should use [`RsaPrivateKey::new`] instead.
///
/// #⚠️Warning: Hazmat!
/// This version does not apply minimum key size checks, and as such may generate keys
/// which are insecure!
#[cfg(feature = "hazmat")]
pub fn new_with_exp_unchecked<R: CryptoRng + ?Sized>(
rng: &mut R,
bit_size: usize,
exp: BoxedUint,
) -> Result<RsaPrivateKey> {
let components = generate_multi_prime_key_with_exp(rng, 2, bit_size, exp)?;
RsaPrivateKey::from_components(
Expand Down Expand Up @@ -821,13 +864,13 @@ mod tests {
}

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

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");

let priv_tokens = [Token::Str(concat!(
"3056020100300d06092a864886f70d010101050004423040020100020900a",
Expand Down
4 changes: 2 additions & 2 deletions src/oaep/decrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
Expand All @@ -107,7 +107,7 @@ mod tests {

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let decrypting_key = DecryptingKey::<Sha256>::new(
RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"),
RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key"),
);

let tokens = [
Expand Down
5 changes: 3 additions & 2 deletions src/oaep/encrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,15 @@ where
mod tests {

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

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
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 tokens = [
Expand Down
7 changes: 4 additions & 3 deletions src/pkcs1v15/decrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,16 @@ impl ZeroizeOnDrop for DecryptingKey {}
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let decrypting_key =
DecryptingKey::new(RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"));
let decrypting_key = DecryptingKey::new(
RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key"),
);

let tokens = [
Token::Struct {
Expand Down
5 changes: 3 additions & 2 deletions src/pkcs1v15/encrypting_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ impl RandomizedEncryptor for EncryptingKey {
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
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 tokens = [
Expand Down
5 changes: 3 additions & 2 deletions src/pkcs1v15/signing_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,15 +319,16 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let signing_key = SigningKey::<Sha256>::new(priv_key);

let tokens = [Token::Str(concat!(
Expand Down
5 changes: 3 additions & 2 deletions src/pkcs1v15/verifying_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,15 +241,16 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let pub_key = priv_key.to_public_key();
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);

Expand Down
4 changes: 2 additions & 2 deletions src/pss/blinded_signing_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
Expand All @@ -288,7 +288,7 @@ mod tests {

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let signing_key = BlindedSigningKey::<Sha256>::new(
RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"),
RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key"),
);

let tokens = [Token::Str(concat!(
Expand Down
5 changes: 3 additions & 2 deletions src/pss/signing_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,16 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let signing_key = SigningKey::<Sha256>::new(priv_key);

let tokens = [Token::Str(concat!(
Expand Down
5 changes: 3 additions & 2 deletions src/pss/verifying_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,16 @@ where
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "serde")]
#[cfg(all(feature = "hazmat", feature = "serde"))]
fn test_serde() {
use super::*;
use crate::RsaPrivateKey;
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use serde_test::{assert_tokens, Configure, Token};
use sha2::Sha256;

let mut rng = ChaCha8Rng::from_seed([42; 32]);
let priv_key = crate::RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
let priv_key = RsaPrivateKey::new_unchecked(&mut rng, 64).expect("failed to generate key");
let pub_key = priv_key.to_public_key();
let verifying_key = VerifyingKey::<Sha256>::new(pub_key);

Expand Down
4 changes: 3 additions & 1 deletion tests/proptests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! Property-based tests.

#![cfg(feature = "hazmat")]

use proptest::prelude::*;
use rand_chacha::ChaCha8Rng;
use rand_core::SeedableRng;
Expand All @@ -14,7 +16,7 @@ prop_compose! {
// WARNING: do *NOT* copy and paste this code. It's insecure and optimized for test speed.
fn private_key()(seed in any::<[u8; 32]>()) -> RsaPrivateKey {
let mut rng = ChaCha8Rng::from_seed(seed);
RsaPrivateKey::new(&mut rng, 512).unwrap()
RsaPrivateKey::new_unchecked(&mut rng, 512).unwrap()
}
}

Expand Down