Avoid small private exponents during RSA key generation

Attacks against RSA exist for small D. [Wiener] established this for
D < N^0.25. [Boneh] suggests the bound should be N^0.5.

Multiple possible values of D might exist for the same set of E, P, Q. The
attack works when there exists any possible D that is small. To make sure that
the generated key is not susceptible to attack, we need to make sure we have
found the smallest possible D, and then check that D is big enough. The
Carmichael function λ of p*q is lcm(p-1, q-1), so we can apply Carmichael's
theorem to show that D = d mod λ(n) is the smallest.

[Wiener] Michael J. Wiener, "Cryptanalysis of Short RSA Secret Exponents"
[Boneh] Dan Boneh and Glenn Durfee, "Cryptanalysis of RSA with Private Key d Less than N^0.292"
This commit is contained in:
Jethro Beekman 2018-02-13 15:50:36 -08:00
parent 80aa3b8d65
commit 97f95c9ef3

View file

@ -502,7 +502,7 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
unsigned int nbits, int exponent )
{
int ret;
mbedtls_mpi H, G;
mbedtls_mpi H, G, L;
if( f_rng == NULL || nbits < 128 || exponent < 3 )
return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
@ -512,10 +512,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
mbedtls_mpi_init( &H );
mbedtls_mpi_init( &G );
mbedtls_mpi_init( &L );
/*
* find primes P and Q with Q < P so that:
* GCD( E, (P-1)*(Q-1) ) == 1
* 1. GCD( E, (P-1)*(Q-1) ) == 1
* 2. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 )
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) );
@ -541,9 +543,23 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) );
/* check GCD( E, (P-1)*(Q-1) ) == 1 */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) );
if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 )
continue;
/* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) */
MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) );
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) );
if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a))
continue;
break;
}
while( mbedtls_mpi_cmp_int( &G, 1 ) != 0 );
while( 1 );
/* Restore P,Q */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) );
@ -551,16 +567,12 @@ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx,
ctx->len = mbedtls_mpi_size( &ctx->N );
#if !defined(MBEDTLS_RSA_NO_CRT)
/*
* D = E^-1 mod ((P-1)*(Q-1))
* DP = D mod (P - 1)
* DQ = D mod (Q - 1)
* QP = Q^-1 mod P
*/
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &H ) );
#if !defined(MBEDTLS_RSA_NO_CRT)
MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D,
&ctx->DP, &ctx->DQ, &ctx->QP ) );
#endif /* MBEDTLS_RSA_NO_CRT */
@ -572,6 +584,7 @@ cleanup:
mbedtls_mpi_free( &H );
mbedtls_mpi_free( &G );
mbedtls_mpi_free( &L );
if( ret != 0 )
{