@@ -200,11 +200,13 @@ impl RsaPublicKey {
200200
201201 /// Create a new public key from its components.
202202 pub fn new_with_max_size ( n : BigUint , e : BigUint , max_size : usize ) -> Result < Self > {
203- let k = Self {
204- n : NonZero :: new ( to_uint ( n) ) . unwrap ( ) ,
205- e : to_uint ( e) ,
206- } ;
207- check_public_with_max_size ( & k, max_size) ?;
203+ check_public_with_max_size ( & n, & e, max_size) ?;
204+
205+ let n = NonZero :: new ( to_uint ( n) ) . unwrap ( ) ;
206+ // widen to 64bit
207+ let e = to_uint_exact ( e, 64 ) ;
208+ let k = Self { n, e } ;
209+
208210 Ok ( k)
209211 }
210212
@@ -215,10 +217,30 @@ impl RsaPublicKey {
215217 /// Most applications should use [`RsaPublicKey::new`] or
216218 /// [`RsaPublicKey::new_with_max_size`] instead.
217219 pub fn new_unchecked ( n : BigUint , e : BigUint ) -> Self {
218- Self {
219- n : NonZero :: new ( to_uint ( n) ) . unwrap ( ) ,
220- e : to_uint ( e) ,
221- }
220+ // TODO: widen?
221+ let n = NonZero :: new ( to_uint ( n) ) . unwrap ( ) ;
222+ let e = to_uint_exact ( e, 64 ) ;
223+ Self { n, e }
224+ }
225+ }
226+
227+ fn needed_bits ( n : & BigUint ) -> usize {
228+ // widen to the max size bits
229+ let n_bits = n. bits ( ) ;
230+
231+ // TODO: better algorithm/more sizes
232+ if n_bits <= 512 {
233+ 512
234+ } else if n_bits <= 1024 {
235+ 1024
236+ } else if n_bits <= 2048 {
237+ 2048
238+ } else if n_bits <= 4096 {
239+ 4096
240+ } else if n_bits <= 8192 {
241+ 8192
242+ } else {
243+ 16384
222244 }
223245}
224246
@@ -274,8 +296,16 @@ impl RsaPrivateKey {
274296 d : BigUint ,
275297 primes : Vec < BigUint > ,
276298 ) -> Result < RsaPrivateKey > {
299+ let n_c = NonZero :: new ( to_uint ( n. clone ( ) ) ) . unwrap ( ) ;
300+ let nbits = n_c. bits_precision ( ) ;
301+
302+ std:: dbg!( nbits) ;
303+
277304 let mut should_validate = false ;
278- let mut primes: Vec < _ > = primes. into_iter ( ) . map ( to_uint) . collect ( ) ;
305+ let mut primes: Vec < _ > = primes
306+ . into_iter ( )
307+ . map ( |p| to_uint_exact ( p, nbits) )
308+ . collect ( ) ;
279309
280310 if primes. len ( ) < 2 {
281311 if !primes. is_empty ( ) {
@@ -284,17 +314,15 @@ impl RsaPrivateKey {
284314 // Recover `p` and `q` from `d`.
285315 // See method in Appendix C.2: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br2.pdf
286316 let ( p, q) = recover_primes ( & n, & e, & d) ?;
287- primes. push ( to_uint ( p ) ) ;
288- primes. push ( to_uint ( q ) ) ;
317+ primes. push ( to_uint_exact ( p , nbits ) ) ;
318+ primes. push ( to_uint_exact ( q , nbits ) ) ;
289319 should_validate = true ;
290320 }
291321
322+ let e = to_uint_exact ( e, 64 ) ;
292323 let mut k = RsaPrivateKey {
293- pubkey_components : RsaPublicKey {
294- n : NonZero :: new ( to_uint ( n) ) . unwrap ( ) ,
295- e : to_uint ( e) ,
296- } ,
297- d : to_uint ( d) ,
324+ pubkey_components : RsaPublicKey { n : n_c, e } ,
325+ d : to_uint_exact ( d, nbits) ,
298326 primes,
299327 precomputed : None ,
300328 } ;
@@ -363,6 +391,10 @@ impl RsaPrivateKey {
363391 if self . precomputed . is_some ( ) {
364392 return Ok ( ( ) ) ;
365393 }
394+
395+ // already widened to what we need
396+ let nbits = self . pubkey_components . n . bits_precision ( ) ;
397+
366398 let d = to_biguint ( & self . d ) ;
367399 let dp = & d % ( & to_biguint ( & self . primes [ 0 ] ) - BigUint :: one ( ) ) ;
368400 let dq = & d % ( & to_biguint ( & self . primes [ 1 ] ) - BigUint :: one ( ) ) ;
@@ -378,14 +410,15 @@ impl RsaPrivateKey {
378410 for prime in & self . primes [ 2 ..] {
379411 let prime = to_biguint ( prime) ;
380412 let res = CrtValueNew {
381- exp : to_uint ( & d % ( & prime - BigUint :: one ( ) ) ) ,
382- r : to_uint ( r. clone ( ) ) ,
383- coeff : to_uint (
413+ exp : to_uint_exact ( & d % ( & prime - BigUint :: one ( ) ) , nbits ) ,
414+ r : to_uint_exact ( r. clone ( ) , nbits ) ,
415+ coeff : to_uint_exact (
384416 r. clone ( )
385417 . mod_inverse ( & prime)
386418 . ok_or ( Error :: InvalidCoefficient ) ?
387419 . to_biguint ( )
388420 . unwrap ( ) ,
421+ nbits,
389422 ) ,
390423 } ;
391424 r *= prime;
@@ -400,8 +433,8 @@ impl RsaPrivateKey {
400433 BoxedResidueParams :: new ( self . pubkey_components . n . clone ( ) . get ( ) ) . unwrap ( ) ;
401434
402435 self . precomputed = Some ( PrecomputedValues {
403- dp : to_uint ( dp) ,
404- dq : to_uint ( dq) ,
436+ dp : to_uint_exact ( dp, nbits ) ,
437+ dq : to_uint_exact ( dq, nbits ) ,
405438 qinv,
406439 crt_values,
407440 residue_params,
@@ -539,34 +572,31 @@ impl PrivateKeyPartsNew for RsaPrivateKey {
539572/// Check that the public key is well formed and has an exponent within acceptable bounds.
540573#[ inline]
541574pub fn check_public ( public_key : & impl PublicKeyParts ) -> Result < ( ) > {
542- check_public_with_max_size ( public_key, RsaPublicKey :: MAX_SIZE )
575+ check_public_with_max_size ( & public_key. n ( ) , & public_key . e ( ) , RsaPublicKey :: MAX_SIZE )
543576}
544577
545578/// Check that the public key is well formed and has an exponent within acceptable bounds.
546579#[ inline]
547- fn check_public_with_max_size ( public_key : & impl PublicKeyParts , max_size : usize ) -> Result < ( ) > {
548- if public_key . n ( ) . bits ( ) > max_size {
580+ fn check_public_with_max_size ( n : & BigUint , e : & BigUint , max_size : usize ) -> Result < ( ) > {
581+ if n . bits ( ) > max_size {
549582 return Err ( Error :: ModulusTooLarge ) ;
550583 }
551584
552- let e = public_key
553- . e ( )
554- . to_u64 ( )
555- . ok_or ( Error :: PublicExponentTooLarge ) ?;
585+ let eu64 = e. to_u64 ( ) . ok_or ( Error :: PublicExponentTooLarge ) ?;
556586
557- if public_key . e ( ) >= public_key . n ( ) || public_key . n ( ) . is_even ( ) {
587+ if e >= n || n . is_even ( ) {
558588 return Err ( Error :: InvalidModulus ) ;
559589 }
560590
561- if public_key . e ( ) . is_even ( ) {
591+ if e . is_even ( ) {
562592 return Err ( Error :: InvalidExponent ) ;
563593 }
564594
565- if e < RsaPublicKey :: MIN_PUB_EXPONENT {
595+ if eu64 < RsaPublicKey :: MIN_PUB_EXPONENT {
566596 return Err ( Error :: PublicExponentTooSmall ) ;
567597 }
568598
569- if e > RsaPublicKey :: MAX_PUB_EXPONENT {
599+ if eu64 > RsaPublicKey :: MAX_PUB_EXPONENT {
570600 return Err ( Error :: PublicExponentTooLarge ) ;
571601 }
572602
@@ -577,12 +607,35 @@ pub(crate) fn to_biguint(uint: &BoxedUint) -> BigUint {
577607 BigUint :: from_bytes_be ( & uint. to_be_bytes ( ) )
578608}
579609
610+ pub ( crate ) fn to_uint_exact ( big_uint : BigUint , nbits : usize ) -> BoxedUint {
611+ let bytes = big_uint. to_bytes_be ( ) ;
612+ let pad_count = Limb :: BYTES - ( bytes. len ( ) % Limb :: BYTES ) ;
613+ let mut padded_bytes = vec ! [ 0u8 ; pad_count] ;
614+ padded_bytes. extend_from_slice ( & bytes) ;
615+
616+ let res = BoxedUint :: from_be_slice ( & padded_bytes, padded_bytes. len ( ) * 8 ) . unwrap ( ) ;
617+
618+ match res. bits_precision ( ) . cmp ( & nbits) {
619+ Ordering :: Equal => res,
620+ Ordering :: Greater => panic ! ( "too large: {} > {}" , res. bits_precision( ) , nbits) ,
621+ Ordering :: Less => res. widen ( nbits) ,
622+ }
623+ }
624+
580625pub ( crate ) fn to_uint ( big_uint : BigUint ) -> BoxedUint {
626+ let nbits = needed_bits ( & big_uint) ;
627+
581628 let bytes = big_uint. to_bytes_be ( ) ;
582629 let pad_count = Limb :: BYTES - ( bytes. len ( ) % Limb :: BYTES ) ;
583630 let mut padded_bytes = vec ! [ 0u8 ; pad_count] ;
584631 padded_bytes. extend_from_slice ( & bytes) ;
585- BoxedUint :: from_be_slice ( & padded_bytes, padded_bytes. len ( ) * 8 ) . unwrap ( )
632+
633+ let res = BoxedUint :: from_be_slice ( & padded_bytes, padded_bytes. len ( ) * 8 ) . unwrap ( ) ;
634+
635+ if res. bits ( ) < nbits {
636+ return res. widen ( nbits) ;
637+ }
638+ res
586639}
587640
588641pub ( crate ) fn reduce ( n : & BoxedUint , p : BoxedResidueParams ) -> BoxedResidue {
@@ -614,10 +667,10 @@ mod tests {
614667 fn test_from_into ( ) {
615668 let private_key = RsaPrivateKey {
616669 pubkey_components : RsaPublicKey {
617- n : NonZero :: new ( to_uint ( BigUint :: from_u64 ( 100 ) . unwrap ( ) ) ) . unwrap ( ) ,
618- e : to_uint ( BigUint :: from_u64 ( 200 ) . unwrap ( ) ) ,
670+ n : NonZero :: new ( to_uint ( BigUint :: from_u64 ( 100 ) . unwrap ( ) ) . widen ( 64 ) ) . unwrap ( ) ,
671+ e : to_uint ( BigUint :: from_u64 ( 200 ) . unwrap ( ) ) . widen ( 64 ) ,
619672 } ,
620- d : to_uint ( BigUint :: from_u64 ( 123 ) . unwrap ( ) ) ,
673+ d : to_uint ( BigUint :: from_u64 ( 123 ) . unwrap ( ) ) . widen ( 64 ) ,
621674 primes : vec ! [ ] ,
622675 precomputed : None ,
623676 } ;
@@ -654,7 +707,8 @@ mod tests {
654707 let mut rng = ChaCha8Rng :: from_seed( [ 42 ; 32 ] ) ;
655708 let exp = BigUint :: from_u64( RsaPrivateKey :: EXP ) . expect( "invalid static exponent" ) ;
656709
657- for _ in 0 ..10 {
710+ for i in 0 ..10 {
711+ std:: dbg!( i, $size) ;
658712 let components =
659713 generate_multi_prime_key_with_exp( & mut rng, $multi, $size, & exp) . unwrap( ) ;
660714 let private_key = RsaPrivateKey :: from_components(
0 commit comments