RSA密钥生成 您所在的位置:网站首页 rsa密钥对生成在线,指定模数 RSA密钥生成

RSA密钥生成

2023-09-18 13:40| 来源: 网络整理| 查看: 265

本博客以mbedtls crypto库为参考介绍RSA密钥对的生成过程。主要可以分为两部分,第一部分是寻找质数pq,第二部分是根据pq计算公钥和私钥,如下所示生成RSA密钥对的函数。

/* * Generate an RSA keypair * * This generation method follows the RSA key pair generation procedure of * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. */ int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, unsigned int nbits, int exponent ) { int ret; mbedtls_mpi H, G, L; int prime_quality = 0; RSA_VALIDATE_RET( ctx != NULL ); RSA_VALIDATE_RET( f_rng != NULL ); if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); /* * If the modulus is 1024 bit long or shorter, then the security strength of * the RSA algorithm is less than or equal to 80 bits and therefore an error * rate of 2^-80 is sufficient. */ if( nbits > 1024 ) prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; mbedtls_mpi_init( &H ); mbedtls_mpi_init( &G ); mbedtls_mpi_init( &L ); /* * find primes P and Q with Q < P so that: * 1. |P-Q| > 2^( nbits / 2 - 100 ) * 2. GCD( E, (P-1)*(Q-1) ) == 1 * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) */ MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); do { MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, prime_quality, f_rng, p_rng ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, prime_quality, f_rng, p_rng ) ); /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); if( mbedtls_mpi_bitlen( &H ) = 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) continue; /* not required by any standards, but some users rely on the fact that P > Q */ if( H.s < 0 ) mbedtls_mpi_swap( &ctx->P, &ctx->Q ); /* Temporarily replace P,Q by P-1, Q-1 */ 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 (FIPS 186-4 §B.3.1 criterion 2(a)) */ 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) (FIPS 186-4 §B.3.1 criterion 3(b)) */ 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 ) P, &ctx->P, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); ctx->len = mbedtls_mpi_size( &ctx->N ); #if !defined(MBEDTLS_RSA_NO_CRT) /* * DP = D mod (P - 1) * DQ = D mod (Q - 1) * QP = Q^-1 mod P */ MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, &ctx->DP, &ctx->DQ, &ctx->QP ) ); #endif /* MBEDTLS_RSA_NO_CRT */ /* Double-check */ MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); cleanup: mbedtls_mpi_free( &H ); mbedtls_mpi_free( &G ); mbedtls_mpi_free( &L ); if( ret != 0 ) { mbedtls_rsa_free( ctx ); return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); } return( 0 ); } 一、寻找质数pq

质数pq的寻找是通过mbedtls_mpi_gen_prime函数实现的。在寻找大质数是,首先会用随机数发生器生成目标长度的随机数,然后对随机数做素性检测,通常使用米勒-罗宾概率性素性检测方法(通过多次检测的方法将为素数的可能性降低到2^{-100}~2^{-80}),通过检测的随机数我们可以认为它是素数。在进行米勒-罗宾素性检测过程中,会对每一级的数进行小因子测试,以提高素性检测效率。

/* * Prime number generation * * To generate an RSA key in a way recommended by FIPS 186-4, both primes must * be either 1024 bits or 1536 bits long, and flags must contain * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. */ int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { #ifdef MBEDTLS_HAVE_INT64 // ceil(2^63.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL #else // ceil(2^31.5) #define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U #endif int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; size_t k, n; int rounds; mbedtls_mpi_uint r; mbedtls_mpi Y; MPI_VALIDATE_RET( X != NULL ); MPI_VALIDATE_RET( f_rng != NULL ); if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); mbedtls_mpi_init( &Y ); n = BITS_TO_LIMBS( nbits ); if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) { /* * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 */ rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); } else { /* * 2^-100 error probability, number of rounds computed based on HAC, * fact 4.48 */ rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); } while( 1 ) { MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; k = n * biL; if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); X->p[0] |= 1; if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) { ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; } else { /* * An necessary condition for Y and X = 2Y + 1 to be prime * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). * Make sure it is satisfied, while keeping X = 3 mod 4 */ X->p[0] |= 2; MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); if( r == 0 ) MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); else if( r == 1 ) MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); while( 1 ) { /* * First, check small factors for X and Y * before doing Miller-Rabin on any of them */ if( ( ret = mpi_check_small_factors( X ) ) == 0 && ( ret = mpi_check_small_factors( &Y ) ) == 0 && ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) == 0 && ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) == 0 ) goto cleanup; if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) goto cleanup; /* * Next candidates. We want to preserve Y = (X-1) / 2 and * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) * so up Y by 6 and X by 12. */ MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); } } } cleanup: mbedtls_mpi_free( &Y ); return( ret ); } 二、计算秘钥对

如上所列,分别调用mbedtls_mpi_gen_prime函数生成质数pq,这里需要保证pq两个质数是不等的,其中fips的标准要求pq除了满足不想等之外,还需要满足差值不会太小。并且习惯上我们都默认pq,然后,需要保证pq的乘积的bits长度满足公钥长度。

MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); if( mbedtls_mpi_bitlen( &H ) = 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) continue;

在确保了生成正确的质数pq之后,就使用pq来计算加解密用的公钥和私钥。首先计算N的欧拉函数\varphi (N)=\varphi (p)\varphi (q)=(p-1)(q-1)

/* Temporarily replace P,Q by P-1, Q-1 */ 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 ) );

然后确保公钥质数E\varphi (N)的最大公约数是1(这是为了求出E关于\varphi (N)的模反元素,作为私钥)。

/* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ 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) (FIPS 186-4 §B.3.1 criterion 3(b)) */ 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 ) );

这样就计算出来RSA的秘钥对。

现在多数RSA的签名和解密都是用了中国剩余定理进行优化,通常也会计算出RSA密钥对的中国剩余定理因子。这里需要计算出Dp \equiv D(mod p-1)Dq \equiv D(mod q-1)Qp \equiv Q^{-1}(mod p)

/* * Export CRT parameters * This must also be implemented if CRT is not used, for being able to * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt * can be used in this case. */ int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) { int ret; int is_priv; RSA_VALIDATE_RET( ctx != NULL ); /* Check if key is private or public */ is_priv = mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; if( !is_priv ) return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); #if !defined(MBEDTLS_RSA_NO_CRT) /* Export all requested blinding parameters. */ if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) { return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); } #else if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, DP, DQ, QP ) ) != 0 ) { return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); } #endif return( 0 ); }

 



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有