Skip to content

Commit 93a29ae

Browse files
authored
Revert "Minimum modulus size checks (#526)" (#575)
This reverts commit 77d9996. Seeing test failures after this was merged: https://github.com/RustCrypto/RSA/actions/runs/17422515248/job/49463477362
1 parent 77d9996 commit 93a29ae

15 files changed

+222
-318
lines changed

.github/workflows/workspace.yml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ jobs:
5151
RUSTDOCFLAGS: "-Dwarnings --cfg docsrs"
5252
run: cargo doc --no-deps --features std,serde,hazmat,sha2
5353

54-
# does not understand concat! macro
55-
# typos:
56-
# runs-on: ubuntu-latest
57-
# steps:
58-
# - uses: actions/checkout@v4
59-
# - uses: crate-ci/[email protected]
54+
typos:
55+
runs-on: ubuntu-latest
56+
steps:
57+
- uses: actions/checkout@v4
58+
- uses: crate-ci/[email protected]

src/errors.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,6 @@ pub enum Error {
4040
/// Invalid coefficient.
4141
InvalidCoefficient,
4242

43-
/// Modulus too small.
44-
ModulusTooSmall,
45-
4643
/// Modulus too large.
4744
ModulusTooLarge,
4845

@@ -97,7 +94,6 @@ impl core::fmt::Display for Error {
9794
Error::InvalidModulus => write!(f, "invalid modulus"),
9895
Error::InvalidExponent => write!(f, "invalid exponent"),
9996
Error::InvalidCoefficient => write!(f, "invalid coefficient"),
100-
Error::ModulusTooSmall => write!(f, "modulus too small"),
10197
Error::ModulusTooLarge => write!(f, "modulus too large"),
10298
Error::PublicExponentTooSmall => write!(f, "public exponent too small"),
10399
Error::PublicExponentTooLarge => write!(f, "public exponent too large"),

src/key.rs

Lines changed: 51 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ use alloc::vec::Vec;
22
use core::cmp::Ordering;
33
use core::fmt;
44
use core::hash::{Hash, Hasher};
5-
use core::ops::Range;
65

76
use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams};
87
use crypto_bigint::{BoxedUint, Integer, NonZero, Odd, Resize};
@@ -207,37 +206,29 @@ impl RsaPublicKey {
207206
pub fn verify<S: SignatureScheme>(&self, scheme: S, hashed: &[u8], sig: &[u8]) -> Result<()> {
208207
scheme.verify(self, hashed, sig)
209208
}
209+
}
210210

211+
impl RsaPublicKey {
211212
/// Minimum value of the public exponent `e`.
212213
pub const MIN_PUB_EXPONENT: u64 = 2;
213214

214215
/// Maximum value of the public exponent `e`.
215216
pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
216217

217-
/// Default minimum size of the modulus `n` in bits.
218-
pub const MIN_SIZE: u32 = 1024;
219-
220-
/// Default maximum size of the modulus `n` in bits.
221-
pub const MAX_SIZE: u32 = 4096;
218+
/// Maximum size of the modulus `n` in bits.
219+
pub const MAX_SIZE: usize = 4096;
222220

223221
/// Create a new public key from its components.
224222
///
225223
/// This function accepts public keys with a modulus size up to 4096-bits,
226224
/// i.e. [`RsaPublicKey::MAX_SIZE`].
227225
pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
228-
Self::new_with_size_limits(n, e, Self::MIN_SIZE..Self::MAX_SIZE)
226+
Self::new_with_max_size(n, e, Self::MAX_SIZE)
229227
}
230228

231229
/// Create a new public key from its components.
232-
///
233-
/// Accepts a third argument which specifies a range of allowed sizes from minimum to maximum
234-
/// in bits, which by default is `1024..4096`.
235-
pub fn new_with_size_limits(
236-
n: BoxedUint,
237-
e: BoxedUint,
238-
size_range_bits: Range<u32>,
239-
) -> Result<Self> {
240-
check_public_with_size_limits(&n, &e, size_range_bits)?;
230+
pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
231+
check_public_with_max_size(&n, &e, max_size)?;
241232

242233
let n_odd = Odd::new(n.clone())
243234
.into_option()
@@ -248,30 +239,19 @@ impl RsaPublicKey {
248239
Ok(Self { n, e, n_params })
249240
}
250241

251-
/// Deprecated: this has been replaced with [`RsaPublicKey::new_with_size_limits`].
252-
#[deprecated(since = "0.10.0", note = "please use `new_with_size_limits` instead")]
253-
pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
254-
Self::new_with_size_limits(n, e, Self::MIN_SIZE..(max_size as u32))
255-
}
256-
257242
/// Create a new public key, bypassing checks around the modulus and public
258243
/// exponent size.
259244
///
260245
/// This method is not recommended, and only intended for unusual use cases.
261246
/// Most applications should use [`RsaPublicKey::new`] or
262-
/// [`RsaPublicKey::new_with_size_limits`] instead.
247+
/// [`RsaPublicKey::new_with_max_size`] instead.
263248
pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
264249
let n_odd = Odd::new(n.clone()).expect("n must be odd");
265250
let n_params = BoxedMontyParams::new(n_odd);
266251
let n = NonZero::new(n).expect("odd numbers are non zero");
267252

268253
Self { n, e, n_params }
269254
}
270-
271-
/// Get the size of the modulus `n` in bits.
272-
pub fn bits(&self) -> u32 {
273-
self.n.bits_vartime()
274-
}
275255
}
276256

277257
impl PublicKeyParts for RsaPrivateKey {
@@ -297,25 +277,6 @@ impl RsaPrivateKey {
297277
Self::new_with_exp(rng, bit_size, BoxedUint::from(Self::EXP))
298278
}
299279

300-
/// Generate a new Rsa key pair of the given bit size using the passed in `rng
301-
/// and allowing hazardous insecure or weak constructions of `RsaPrivateKey
302-
///
303-
/// Unless you have specific needs, you should use `RsaPrivateKey::new` instead
304-
#[cfg(feature = "hazmat")]
305-
pub fn new_unchecked<R: CryptoRng + ?Sized>(
306-
rng: &mut R,
307-
bit_size: usize,
308-
) -> Result<RsaPrivateKey> {
309-
let components =
310-
generate_multi_prime_key_with_exp(rng, 2, bit_size, BoxedUint::from(Self::EXP))?;
311-
RsaPrivateKey::from_components_unchecked(
312-
components.n.get(),
313-
components.e,
314-
components.d,
315-
components.primes,
316-
)
317-
}
318-
319280
/// Generate a new RSA key pair of the given bit size and the public exponent
320281
/// using the passed in `rng`.
321282
///
@@ -348,36 +309,6 @@ impl RsaPrivateKey {
348309
///
349310
/// [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
350311
pub fn from_components(
351-
n: BoxedUint,
352-
e: BoxedUint,
353-
d: BoxedUint,
354-
primes: Vec<BoxedUint>,
355-
) -> Result<RsaPrivateKey> {
356-
// The primes may come in padded with zeros too, so we need to shorten them as well.
357-
let primes = primes
358-
.into_iter()
359-
.map(|p| {
360-
let p_bits = p.bits();
361-
p.resize_unchecked(p_bits)
362-
})
363-
.collect();
364-
365-
let mut k = Self::from_components_unchecked(n, e, d, primes)?;
366-
367-
// Always validate the key, to ensure precompute can't fail
368-
k.validate()?;
369-
370-
// Precompute when possible, ignore error otherwise.
371-
k.precompute().ok();
372-
373-
Ok(k)
374-
}
375-
376-
/// Constructs an RSA key pair from individual components. Bypasses checks on the key's
377-
/// validity like the modulus size.
378-
///
379-
/// Please use [`RsaPrivateKey::from_components`] whenever possible.
380-
pub fn from_components_unchecked(
381312
n: BoxedUint,
382313
e: BoxedUint,
383314
d: BoxedUint,
@@ -406,8 +337,8 @@ impl RsaPrivateKey {
406337
1 => return Err(Error::NprimesTooSmall),
407338
_ => {
408339
// Check that the product of primes matches the modulus.
409-
// This also ensures that `bits_precision` of each prime is <= that of the modulus,
410-
// and `bits_precision` of their product is >= that of the modulus.
340+
// This also ensures that `bit_precision` of each prime is <= that of the modulus,
341+
// and `bit_precision` of their product is >= that of the modulus.
411342
if &primes.iter().fold(BoxedUint::one(), |acc, p| acc * p) != n_c.as_ref() {
412343
return Err(Error::InvalidModulus);
413344
}
@@ -423,7 +354,7 @@ impl RsaPrivateKey {
423354
})
424355
.collect();
425356

426-
Ok(RsaPrivateKey {
357+
let mut k = RsaPrivateKey {
427358
pubkey_components: RsaPublicKey {
428359
n: n_c,
429360
e,
@@ -432,7 +363,15 @@ impl RsaPrivateKey {
432363
d,
433364
primes,
434365
precomputed: None,
435-
})
366+
};
367+
368+
// Always validate the key, to ensure precompute can't fail
369+
k.validate()?;
370+
371+
// Precompute when possible, ignore error otherwise.
372+
k.precompute().ok();
373+
374+
Ok(k)
436375
}
437376

438377
/// Constructs an RSA key pair from its two primes p and q.
@@ -645,11 +584,6 @@ impl RsaPrivateKey {
645584
) -> Result<Vec<u8>> {
646585
padding.sign(Some(rng), self, digest_in)
647586
}
648-
649-
/// Get the size of the modulus `n` in bits.
650-
pub fn bits(&self) -> u32 {
651-
self.pubkey_components.bits()
652-
}
653587
}
654588

655589
impl PrivateKeyParts for RsaPrivateKey {
@@ -686,30 +620,16 @@ impl PrivateKeyParts for RsaPrivateKey {
686620
}
687621
}
688622

689-
/// Check that the public key is well-formed and has an exponent within acceptable bounds.
623+
/// Check that the public key is well formed and has an exponent within acceptable bounds.
690624
#[inline]
691625
pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> {
692-
check_public_with_size_limits(
693-
public_key.n(),
694-
public_key.e(),
695-
RsaPublicKey::MIN_SIZE..RsaPublicKey::MAX_SIZE,
696-
)
626+
check_public_with_max_size(public_key.n(), public_key.e(), RsaPublicKey::MAX_SIZE)
697627
}
698628

699-
/// Check that the public key is well-formed and has an exponent within acceptable bounds.
629+
/// Check that the public key is well formed and has an exponent within acceptable bounds.
700630
#[inline]
701-
fn check_public_with_size_limits(
702-
n: &BoxedUint,
703-
e: &BoxedUint,
704-
size_range_bits: Range<u32>,
705-
) -> Result<()> {
706-
let modulus_bits = n.bits_vartime();
707-
708-
if modulus_bits < size_range_bits.start {
709-
return Err(Error::ModulusTooSmall);
710-
}
711-
712-
if modulus_bits > size_range_bits.end {
631+
fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: usize) -> Result<()> {
632+
if n.bits_vartime() as usize > max_size {
713633
return Err(Error::ModulusTooLarge);
714634
}
715635

@@ -812,10 +732,7 @@ mod tests {
812732
}
813733

814734
fn test_key_basics(private_key: &RsaPrivateKey) {
815-
// Some test keys have moduli which are smaller than 1024-bits
816-
if private_key.bits() >= RsaPublicKey::MIN_SIZE {
817-
private_key.validate().expect("invalid private key");
818-
}
735+
private_key.validate().expect("invalid private key");
819736

820737
assert!(
821738
PrivateKeyParts::d(private_key) < PublicKeyParts::n(private_key).as_ref(),
@@ -861,17 +778,29 @@ mod tests {
861778
};
862779
}
863780

781+
key_generation!(key_generation_128, 2, 128);
864782
key_generation!(key_generation_1024, 2, 1024);
783+
784+
key_generation!(key_generation_multi_3_256, 3, 256);
785+
786+
key_generation!(key_generation_multi_4_64, 4, 64);
787+
788+
key_generation!(key_generation_multi_5_64, 5, 64);
789+
key_generation!(key_generation_multi_8_576, 8, 576);
865790
key_generation!(key_generation_multi_16_1024, 16, 1024);
866791

867792
#[test]
868793
fn test_negative_decryption_value() {
869794
let bits = 128;
870-
let private_key = RsaPrivateKey::from_components_unchecked(
871-
BoxedUint::from_le_slice_vartime(&[
872-
99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180,
873-
]),
874-
BoxedUint::from_le_slice_vartime(&[1, 0, 1, 0, 0, 0, 0, 0]),
795+
let private_key = RsaPrivateKey::from_components(
796+
BoxedUint::from_le_slice(
797+
&[
798+
99, 192, 208, 179, 0, 220, 7, 29, 49, 151, 75, 107, 75, 73, 200, 180,
799+
],
800+
bits,
801+
)
802+
.unwrap(),
803+
BoxedUint::from_le_slice(&[1, 0, 1, 0, 0, 0, 0, 0], 64).unwrap(),
875804
BoxedUint::from_le_slice(
876805
&[
877806
81, 163, 254, 144, 171, 159, 144, 42, 244, 133, 51, 249, 28, 12, 63, 65,
@@ -898,44 +827,21 @@ mod tests {
898827
use serde_test::{assert_tokens, Configure, Token};
899828

900829
let mut rng = ChaCha8Rng::from_seed([42; 32]);
901-
let priv_key = RsaPrivateKey::new(&mut rng, 1024).expect("failed to generate key");
830+
let priv_key = RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key");
902831

903832
let priv_tokens = [Token::Str(concat!(
904-
"30820278020100300d06092a864886f70d0101010500048202623082025e0",
905-
"2010002818100cd1419dc3771354bee0955a90489cce0c98aee6577851358",
906-
"afe386a68bc95287862a1157d5aba8847e8e57b6f2f94748ab7efda3f3c74",
907-
"a6702329397ffe0b1d4f76e1b025d87d583e48b3cfce99d6a507d94eb46c5",
908-
"242b3addb54d346ecf43eb0d7343bcb258a31d5fa51f47b9e0d7280623901",
909-
"d1d29af1a986fec92ba5fe2430203010001028181009bb3203326d0c7b31f",
910-
"456d08c6ce4c8379e10640792ecad271afe002406d184096a707c5d50ee00",
911-
"1c00818266970c3233439551f0e2d879a8f7b90bd3d62fdffa3e661f14c8d",
912-
"cce071f081966e25bb351289810c2f8a012f2fa3f001029d7f2e0cf24f6a4",
913-
"b139292f8078fac24e7fc8185bab4f02f539267bd09b615e4e19fe1024100",
914-
"e90ad93c4b19bb40807391b5a9404ce5ea359e7b0556ee25cb2e7455aeb5c",
915-
"af83fc26f34457cdbb173347962c66b6fe0c4686b54dbe0d2c913a7aa924e",
916-
"ff6031024100e148067566a1fa3aabd0672361be62715516c9d62790b03f4",
917-
"326cc00b2f782e6b64a167689e5c9aebe6a4cf594f3083380fe2a0a7edf1f",
918-
"325e58c523b981a0b3024100ab96e85323bd038a3fca588c58ddd681278d6",
919-
"96e8d84ef7ef676f303afcb7d728287e897a55e84e8c8b9e772da447b3115",
920-
"8d0912877fa7d4945b4d15c382f7d102400ddde317e2e36185af01baf7809",
921-
"2b97884664cb233e9421002d0268a7c79a3c313c167b4903466bfacd4da3b",
922-
"db99420df988ab89cdd96a102da2852ff7c134e5024100bafb0dac0fda53f",
923-
"9c755c23483343922727b88a5256a6fb47242e1c99b8f8a2c914f39f7af30",
924-
"1219245786a6bb15336231d6a9b57ee7e0b3dd75129f93f54ecf"
833+
"3056020100300d06092a864886f70d010101050004423040020100020900a",
834+
"b240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf302",
835+
"0500d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
925836
))];
926837
assert_tokens(&priv_key.clone().readable(), &priv_tokens);
927838

928-
let pub_tokens = [Token::Str(concat!(
929-
"30819f300d06092a864886f70d010101050003818d0030818902818100cd1",
930-
"419dc3771354bee0955a90489cce0c98aee6577851358afe386a68bc95287",
931-
"862a1157d5aba8847e8e57b6f2f94748ab7efda3f3c74a6702329397ffe0b",
932-
"1d4f76e1b025d87d583e48b3cfce99d6a507d94eb46c5242b3addb54d346e",
933-
"cf43eb0d7343bcb258a31d5fa51f47b9e0d7280623901d1d29af1a986fec9",
934-
"2ba5fe2430203010001"
935-
))];
839+
let priv_tokens = [Token::Str(
840+
"3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001",
841+
)];
936842
assert_tokens(
937843
&RsaPublicKey::from(priv_key.clone()).readable(),
938-
&pub_tokens,
844+
&priv_tokens,
939845
);
940846
}
941847

src/oaep/decrypting_key.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ mod tests {
107107

108108
let mut rng = ChaCha8Rng::from_seed([42; 32]);
109109
let decrypting_key = DecryptingKey::<Sha256>::new(
110-
RsaPrivateKey::new(&mut rng, 2048).expect("failed to generate key"),
110+
RsaPrivateKey::new(&mut rng, 64).expect("failed to generate key"),
111111
);
112112

113113
let tokens = [
@@ -117,7 +117,9 @@ mod tests {
117117
},
118118
Token::Str("inner"),
119119
Token::Str(concat!(
120-
"308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100cf823bdbad23cda55787e9d1dbd630457e3e8407f3a4da723656a120866a8284ce211ff8464904cf7dab256d0b5544549719f4155d32187ad3eb928ada9cd4152a9e4153e21c68022e654b0d10b065519e9ef5619f431740c2a0f568141c27670485f28d1643fe650af3757f4775af5d01ed3c992a6269c5aa5ff7f52450c30a84783e36931b8855b091559540ec34e0730c511d62e09ea86d66b0f4cb92d1a609e7fb6f34ae8cf08bd791eee85150850e943fb5e4d9b7fd44a5eb474ed7e0bb7faa2e1dca443d5df8f77468fb0905731e421b2e06e864f957f3a517b2b0e3ad09118310b9fd74cb54bb07308d009e3ec6cecc17f06cddf10e0b1b9eff5ff8b90203010001028201000a7071d4765c63bf1aad32bd25031c80927e50a419c4c45c94913d1fe6c33af7b56b0331b94f79177b29fe03035bf1c913a4f19b9589aca3993fb3aa9a9ee32881715eb5fa9d153a6edd17ae7b9574336bf8713dcd065208270273f61d74e122949eac7a1e91a31db0345947e2ef6fb80d1dc33bad5f30150aa2335638d27b4d57f47262b31059351b08c2350d8afe88d1dfbd1b398daf317db8c0cd42859072b8ddadcc2d50c5ad1d6d06a56594bdabb7dd51c77fe2b5d404c64ff99e6500de5da418c5c49c6ebd7ecfc400f18ba26fd4d6e7b31e435d494326585a9efff7bdb3c51ba19399918df4a999453dfed65e84adb15b0a183416b5ec5f221491978102818100e148067566a1fa3aabd0672361be62715516c9d62790b03f4326cc00b2f782e6b64a167689e5c9aebe6a4cf594f3083380fe2a0a7edf1f325e58c523b9819747a90ad93c4b19bb40807391b5a9404ce5ea359e7b0556ee25cb2e7455aeb5caf83fc26f34457cdbb173347962c66b6fe0c4686b54dbe0d2c913a7aa924eff6ec902818100ebcdd03d9b1dfd2ea4f2d6dade79fcb02727d84426f9d756121525f14696434fa594867ca839d1025b823a7576eb6c8b33e6dd4ff4fcb72c6069d1e5e74885e90b76b0bf3994501dd0ef212694e73cbf43855731ba543c771debf979eea8f77fcab8a53d56fc46d5398893f3421ca54b371afb10ecb2137892f5062c506e82710281801c345542ab87c9f9407b85fe23059ff38a70a0f263dfb481271a1b5e5709afe4cc9bb7f63d4b7c9599175bed3f29b234288929a048c40c76d4e30e436bbd32c071047fb011c2f5f39c615bb3bfade232c2c0d5c797228c0c4544daa1c38ed50b8188093e2518fdb458b5102172b00ec0b8364e81c049847a5230a2a550a8a029028180718bebc89e9734416fc057e190dbe0e7da12ffbae1a1d1256b13afef9cf3e279c9dbd95ed18af5b052ec44c6277b7a0b15f50780e711820ae66a4e5e8c9e898d0cae1cb21841e8ca52bfb390e686eae396d9f080cb9ea077237b6be8611a10040354228d85037a0056f2037c51cb8574d096376b90eeb71d8a765e809c427aa102818100886afe7a9610e60cd2da4cf3137ba5f597cd9cdc344f36c4101720363341c42cdfe09f68ee25a3dd63e191b6542bcd97aaa0af776eb68aaab84db4594e5340591b4fe194ea2fe2f7586ac3c3aaf8bc337963c4e05d6556b1a6024ac6e07710cdf01bcd9543e263a35ad13baaa2aa6c3af60880cc56622959916cab038a51fff9",
120+
"3056020100300d06092a864886f70d010101050004423040020100020900ab",
121+
"240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf30205",
122+
"00d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
121123
)),
122124
Token::Str("label"),
123125
Token::None,

0 commit comments

Comments
 (0)