@@ -2,6 +2,7 @@ use alloc::vec::Vec;
2
2
use core:: cmp:: Ordering ;
3
3
use core:: fmt;
4
4
use core:: hash:: { Hash , Hasher } ;
5
+ use core:: ops:: Range ;
5
6
6
7
use crypto_bigint:: modular:: { BoxedMontyForm , BoxedMontyParams } ;
7
8
use crypto_bigint:: { BoxedUint , Integer , NonZero , Odd , Resize } ;
@@ -206,29 +207,37 @@ impl RsaPublicKey {
206
207
pub fn verify < S : SignatureScheme > ( & self , scheme : S , hashed : & [ u8 ] , sig : & [ u8 ] ) -> Result < ( ) > {
207
208
scheme. verify ( self , hashed, sig)
208
209
}
209
- }
210
210
211
- impl RsaPublicKey {
212
211
/// Minimum value of the public exponent `e`.
213
212
pub const MIN_PUB_EXPONENT : u64 = 2 ;
214
213
215
214
/// Maximum value of the public exponent `e`.
216
215
pub const MAX_PUB_EXPONENT : u64 = ( 1 << 33 ) - 1 ;
217
216
218
- /// Maximum size of the modulus `n` in bits.
219
- pub const MAX_SIZE : usize = 4096 ;
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 ;
220
222
221
223
/// Create a new public key from its components.
222
224
///
223
225
/// This function accepts public keys with a modulus size up to 4096-bits,
224
226
/// i.e. [`RsaPublicKey::MAX_SIZE`].
225
227
pub fn new ( n : BoxedUint , e : BoxedUint ) -> Result < Self > {
226
- Self :: new_with_max_size ( n, e, Self :: MAX_SIZE )
228
+ Self :: new_with_size_limits ( n, e, Self :: MIN_SIZE .. Self :: MAX_SIZE )
227
229
}
228
230
229
231
/// Create a new public key from its components.
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) ?;
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) ?;
232
241
233
242
let n_odd = Odd :: new ( n. clone ( ) )
234
243
. into_option ( )
@@ -239,19 +248,30 @@ impl RsaPublicKey {
239
248
Ok ( Self { n, e, n_params } )
240
249
}
241
250
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
+
242
257
/// Create a new public key, bypassing checks around the modulus and public
243
258
/// exponent size.
244
259
///
245
260
/// This method is not recommended, and only intended for unusual use cases.
246
261
/// Most applications should use [`RsaPublicKey::new`] or
247
- /// [`RsaPublicKey::new_with_max_size `] instead.
262
+ /// [`RsaPublicKey::new_with_size_limits `] instead.
248
263
pub fn new_unchecked ( n : BoxedUint , e : BoxedUint ) -> Self {
249
264
let n_odd = Odd :: new ( n. clone ( ) ) . expect ( "n must be odd" ) ;
250
265
let n_params = BoxedMontyParams :: new ( n_odd) ;
251
266
let n = NonZero :: new ( n) . expect ( "odd numbers are non zero" ) ;
252
267
253
268
Self { n, e, n_params }
254
269
}
270
+
271
+ /// Get the size of the modulus `n` in bits.
272
+ pub fn bits ( & self ) -> u32 {
273
+ self . n . bits_vartime ( )
274
+ }
255
275
}
256
276
257
277
impl PublicKeyParts for RsaPrivateKey {
@@ -304,6 +324,36 @@ impl RsaPrivateKey {
304
324
///
305
325
/// [NIST SP 800-56B Revision 2]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
306
326
pub fn from_components (
327
+ n : Odd < BoxedUint > ,
328
+ e : BoxedUint ,
329
+ d : BoxedUint ,
330
+ primes : Vec < BoxedUint > ,
331
+ ) -> Result < RsaPrivateKey > {
332
+ // The primes may come in padded with zeros too, so we need to shorten them as well.
333
+ let primes = primes
334
+ . into_iter ( )
335
+ . map ( |p| {
336
+ let p_bits = p. bits ( ) ;
337
+ p. resize_unchecked ( p_bits)
338
+ } )
339
+ . collect ( ) ;
340
+
341
+ let mut k = Self :: from_components_unchecked ( n, e, d, primes) ?;
342
+
343
+ // Always validate the key, to ensure precompute can't fail
344
+ k. validate ( ) ?;
345
+
346
+ // Precompute when possible, ignore error otherwise.
347
+ k. precompute ( ) . ok ( ) ;
348
+
349
+ Ok ( k)
350
+ }
351
+
352
+ /// Constructs an RSA key pair from individual components. Bypasses checks on the key's
353
+ /// validity like the modulus size.
354
+ ///
355
+ /// Please use [`RsaPrivateKey::from_components`] whenever possible.
356
+ pub fn from_components_unchecked (
307
357
n : Odd < BoxedUint > ,
308
358
e : BoxedUint ,
309
359
d : BoxedUint ,
@@ -330,8 +380,8 @@ impl RsaPrivateKey {
330
380
1 => return Err ( Error :: NprimesTooSmall ) ,
331
381
_ => {
332
382
// Check that the product of primes matches the modulus.
333
- // This also ensures that `bit_precision ` of each prime is <= that of the modulus,
334
- // and `bit_precision ` of their product is >= that of the modulus.
383
+ // This also ensures that `bits_precision ` of each prime is <= that of the modulus,
384
+ // and `bits_precision ` of their product is >= that of the modulus.
335
385
if & primes. iter ( ) . fold ( BoxedUint :: one ( ) , |acc, p| acc * p) != n_c. as_ref ( ) {
336
386
return Err ( Error :: InvalidModulus ) ;
337
387
}
@@ -347,7 +397,7 @@ impl RsaPrivateKey {
347
397
} )
348
398
. collect ( ) ;
349
399
350
- let mut k = RsaPrivateKey {
400
+ Ok ( RsaPrivateKey {
351
401
pubkey_components : RsaPublicKey {
352
402
n : n_c,
353
403
e,
@@ -356,15 +406,7 @@ impl RsaPrivateKey {
356
406
d,
357
407
primes,
358
408
precomputed : None ,
359
- } ;
360
-
361
- // Alaways validate the key, to ensure precompute can't fail
362
- k. validate ( ) ?;
363
-
364
- // Precompute when possible, ignore error otherwise.
365
- k. precompute ( ) . ok ( ) ;
366
-
367
- Ok ( k)
409
+ } )
368
410
}
369
411
370
412
/// Constructs an RSA key pair from its two primes p and q.
@@ -577,6 +619,11 @@ impl RsaPrivateKey {
577
619
) -> Result < Vec < u8 > > {
578
620
padding. sign ( Some ( rng) , self , digest_in)
579
621
}
622
+
623
+ /// Get the size of the modulus `n` in bits.
624
+ pub fn bits ( & self ) -> u32 {
625
+ self . pubkey_components . bits ( )
626
+ }
580
627
}
581
628
582
629
impl PrivateKeyParts for RsaPrivateKey {
@@ -613,16 +660,30 @@ impl PrivateKeyParts for RsaPrivateKey {
613
660
}
614
661
}
615
662
616
- /// Check that the public key is well formed and has an exponent within acceptable bounds.
663
+ /// Check that the public key is well- formed and has an exponent within acceptable bounds.
617
664
#[ inline]
618
665
pub fn check_public ( public_key : & impl PublicKeyParts ) -> Result < ( ) > {
619
- check_public_with_max_size ( public_key. n ( ) , public_key. e ( ) , RsaPublicKey :: MAX_SIZE )
666
+ check_public_with_size_limits (
667
+ public_key. n ( ) ,
668
+ public_key. e ( ) ,
669
+ RsaPublicKey :: MIN_SIZE ..RsaPublicKey :: MAX_SIZE ,
670
+ )
620
671
}
621
672
622
- /// Check that the public key is well formed and has an exponent within acceptable bounds.
673
+ /// Check that the public key is well- formed and has an exponent within acceptable bounds.
623
674
#[ inline]
624
- fn check_public_with_max_size ( n : & BoxedUint , e : & BoxedUint , max_size : usize ) -> Result < ( ) > {
625
- if n. bits_precision ( ) as usize > max_size {
675
+ fn check_public_with_size_limits (
676
+ n : & BoxedUint ,
677
+ e : & BoxedUint ,
678
+ size_range_bits : Range < u32 > ,
679
+ ) -> Result < ( ) > {
680
+ let modulus_bits = n. bits_vartime ( ) ;
681
+
682
+ if modulus_bits < size_range_bits. start {
683
+ return Err ( Error :: ModulusTooSmall ) ;
684
+ }
685
+
686
+ if modulus_bits > size_range_bits. end {
626
687
return Err ( Error :: ModulusTooLarge ) ;
627
688
}
628
689
@@ -723,7 +784,10 @@ mod tests {
723
784
}
724
785
725
786
fn test_key_basics ( private_key : & RsaPrivateKey ) {
726
- private_key. validate ( ) . expect ( "invalid private key" ) ;
787
+ // Some test keys have moduli which are smaller than 1024-bits
788
+ if private_key. bits ( ) >= RsaPublicKey :: MIN_SIZE {
789
+ private_key. validate ( ) . expect ( "invalid private key" ) ;
790
+ }
727
791
728
792
assert ! (
729
793
PrivateKeyParts :: d( private_key) < PublicKeyParts :: n( private_key) . as_ref( ) ,
@@ -769,21 +833,13 @@ mod tests {
769
833
} ;
770
834
}
771
835
772
- key_generation ! ( key_generation_128, 2 , 128 ) ;
773
836
key_generation ! ( key_generation_1024, 2 , 1024 ) ;
774
-
775
- key_generation ! ( key_generation_multi_3_256, 3 , 256 ) ;
776
-
777
- key_generation ! ( key_generation_multi_4_64, 4 , 64 ) ;
778
-
779
- key_generation ! ( key_generation_multi_5_64, 5 , 64 ) ;
780
- key_generation ! ( key_generation_multi_8_576, 8 , 576 ) ;
781
837
key_generation ! ( key_generation_multi_16_1024, 16 , 1024 ) ;
782
838
783
839
#[ test]
784
840
fn test_negative_decryption_value ( ) {
785
841
let bits = 128 ;
786
- let private_key = RsaPrivateKey :: from_components (
842
+ let private_key = RsaPrivateKey :: from_components_unchecked (
787
843
Odd :: new (
788
844
BoxedUint :: from_le_slice (
789
845
& [
@@ -821,21 +877,43 @@ mod tests {
821
877
use serde_test:: { assert_tokens, Configure , Token } ;
822
878
823
879
let mut rng = ChaCha8Rng :: from_seed ( [ 42 ; 32 ] ) ;
824
- let priv_key = RsaPrivateKey :: new ( & mut rng, 64 ) . expect ( "failed to generate key" ) ;
880
+ let priv_key = RsaPrivateKey :: new ( & mut rng, 1024 ) . expect ( "failed to generate key" ) ;
825
881
826
882
let priv_tokens = [ Token :: Str ( concat ! (
827
- "3056020100300d06092a864886f70d010101050004423040020100020900a" ,
828
- "b240c3361d02e370203010001020811e54a15259d22f9020500ceff5cf302" ,
829
- "0500d3a7aaad020500ccaddf17020500cb529d3d020500bb526d6f"
883
+ "30820278020100300d06092a864886f70d0101010500048202623082025e0" ,
884
+ "2010002818100cd1419dc3771354bee0955a90489cce0c98aee6577851358" ,
885
+ "afe386a68bc95287862a1157d5aba8847e8e57b6f2f94748ab7efda3f3c74" ,
886
+ "a6702329397ffe0a8f83e2ef5297aa3d9d883cbeb94ee018fd68e986e08d5" ,
887
+ "b044c15e8170217cd57501d42dd72ef691b2a95bcc090d9bca735bba3ecb8" ,
888
+ "38650f13b1aa36d0f454e37ff020301000102818100935c4248cf3df5c21d" ,
889
+ "c56f5c07faccd129813f5481d189d94c69fdb366f6beeacb2927552a2032f" ,
890
+ "321cd3e92237da40f3fcbfc8df6f9d928b3978c1ec8aab23e857a3ba2db26" ,
891
+ "941ace6ecda8dcb290866a80820b3aa9138179ca867d37825ebcdb48adbe7" ,
892
+ "c397f1e77c4160f0fbf87cc0cd5dff195ac96fd333c0b38384c74c1024100" ,
893
+ "e90ad93c4b19bb40807391b5a9404ce5ea359e7b0556ee25cb2e7455aeb5c" ,
894
+ "af83fc26f34457cdbb173347962c66b6fe0c4686b54dbe0d2c913a7aa924e" ,
895
+ "ff5d67024100e148067566a1fa3aabd0672361be62715516c9d62790b03f4" ,
896
+ "326cc00b2f782e6b64a167689e5c9aebe6a4cf594f3083380fe2a0a7edf1f" ,
897
+ "325e58c523b98199a9024100df15fc8924577892b1a4707b178faf4d751c6" ,
898
+ "91ed928b387486eaafd0ee7866a8916c73fa1b979d1f037ee6fa904563033" ,
899
+ "b4c5f2911e328a3c9f87c0d190d1c7024057461ce26c7141cc6af5608f6f7" ,
900
+ "55f13c2c0024f49a29ef4d321fb9425c1076033ac7e094c20ce4239185b5a" ,
901
+ "246b06795576a178d16fc4d9317db859bfaafa8902410084b2d64651b471b" ,
902
+ "f805af14018db693cdab6059063a6aa4eb8f9ca99b319074b79d7dead3d05" ,
903
+ "68c364978be262d3395aa60541d670f94367babebe7616dbc260"
830
904
) ) ] ;
831
905
assert_tokens ( & priv_key. clone ( ) . readable ( ) , & priv_tokens) ;
832
906
833
- let priv_tokens = [ Token :: Str (
834
- "3024300d06092a864886f70d01010105000313003010020900ab240c3361d02e370203010001" ,
835
- ) ] ;
907
+ let pub_tokens = [ Token :: Str ( concat ! (
908
+ "30819f300d06092a864886f70d010101050003818d0030818902818100cd1419dc3771354bee" ,
909
+ "0955a90489cce0c98aee6577851358afe386a68bc95287862a1157d5aba8847e8e57b6f2f947" ,
910
+ "48ab7efda3f3c74a6702329397ffe0a8f83e2ef5297aa3d9d883cbeb94ee018fd68e986e08d5" ,
911
+ "b044c15e8170217cd57501d42dd72ef691b2a95bcc090d9bca735bba3ecb838650f13b1aa36d" ,
912
+ "0f454e37ff0203010001" ,
913
+ ) ) ] ;
836
914
assert_tokens (
837
915
& RsaPublicKey :: from ( priv_key. clone ( ) ) . readable ( ) ,
838
- & priv_tokens ,
916
+ & pub_tokens ,
839
917
) ;
840
918
}
841
919
0 commit comments