/* 判断是否 p == q,如果是返回重新生
成 */
ret = mpz_cmp(&prv->p, &prv->q);
if (ret == 0)
{
fprintf(stderr,
"Generated the same prime twice!/n");
goto retry;
}
if (ret > 0)
{
mpz_set(&aux, &prv->p);
mpz_set(&prv->p, &prv->q);
mpz_set(&prv->q, &aux);
}
/* 确定 p、q 是否很接近 */
mpz_sub(&aux, &prv->q, &prv->p);
mpz_div_2exp(&test, &prv->q, 10);
if (mpz_cmp(&aux, &test) < 0)
{
fprintf(stderr,
"The primes are too close together./n");
goto retry;
}
/* Make certain p and q are relatively prime (in case
one or both were false positives... Though this is
quite impossible). */
mpz_gcd(&aux, &prv->p, &prv->q);
if (mpz_cmp_ui(&aux, 1) != 0)
{
fprintf(stderr,
"The primes are not relatively prime!/n");
goto retry;
}
/* 启动小质数的 moduli 数 */
moduli = malloc(MAX_PRIMES_IN_TABLE * sizeof(moduli[0]));
if (moduli == NULL)
{
printf(stderr, "Cann't get memory for moduli/n");
exit(1);
}
if (bits < 16)
num_primes = 0;
/* Don/'t use the table for very small numbers. */
else
{
for (num_primes = 0;
small_primes[num_primes] != 0; num_primes++)
{
mpz_mod_ui(&aux, &start, small_primes[num_primes]);
moduli[num_primes] = mpz_get_ui(&aux);
}
}
/* 寻找一个数,它不能被小质数整除 */
for (difference = 0; ; difference += 2)
{
unsigned int i;
if (difference > 0x70000000)
{
fprintf(stderr, "rsa_random_prime: "
"failed to find a prime, retrying./n");
if (moduli != NULL)
free(moduli);
else
exit(1);
goto retry;
}
/* 检查它是否是小质数的乘积 */
for (i = 0; i < num_primes; i++)
{
while (moduli<i> + difference >= small_primes<i>)
moduli<i> -= small_primes<i>;
if (moduli<i> + difference == 0)
break;
}
if (i < num_primes)
continue; /* Multiple of a known prime. */
/* 检查通过 */
fprintf(stderr, ".");
/* Compute the number in question. */
mpz_add_ui(ret, &start, difference);
/* Perform the fermat test for witness 2.
This means: it is not prime if 2^n mod n != 2. */
mpz_set_ui(&aux, 2);
mpz_powm(&aux, &aux, ret, ret);
if (mpz_cmp_ui(&aux, 2) == 0)
{
/* Passed the fermat test for witness 2. */
fprintf(stderr, "+");
/* Perform a more tests. These are probably unnecessary. */
if (mpz_probab_prime_p(ret, 20))
break; /* It is a prime with probability 1 - 2^-40. */
}
}
/* Found a (probable) prime. It is in ret. */
fprintf(stderr, "+ (distance %ld)/n", difference);
/* Free the small prime moduli; they are no longer needed. */
if (moduli != NULL)
free(moduli);
else
exit(1);
/* Sanity check: does it still have the high bit set (we might have
wrapped around)? */
mpz_div_2exp(&aux, ret, bits - 1);
if (mpz_get_ui(&aux) != 1)
{
fprintf(stderr,
"rsa_random_prime: high bit not set, retrying./n");
goto retry;
}
mpz_clear(&start);
mpz_clear(&aux);
}
_______________________________________________________
/* G is the number of "spare key sets" for a given
modulus n. The smaller G is, the better. The
smallest G can get is 2. */
mpz_gcd(&G, &p_minus_1, &q_minus_1);
if (mpz_cmp_ui(&G, 100) >= 0)
{
fprintf(stderr, "Warning: G=");
mpz_out_str(stdout, 10, &G);
fprintf(stderr,
" is large (many spare key sets); key may be bad!/n");
}
/* F = phi / G; the number of relative prime
numbers per spare key set. */
mpz_div(&F, &phi, &G);
/* Find a suitable e (the public exponent). */
mpz_set_ui(e, 1);
mpz_mul_2exp(e, e, ebits);
mpz_sub_ui(e, e, 1); /*make lowest bit 1, and substract 2.*/
/* Keep adding 2 until it is relatively prime
to (p-1)(q-1). */
do
{
mpz_add_ui(e, e, 2);
mpz_gcd(&aux, e, &phi);
}
while (mpz_cmp_ui(&aux, 1) != 0);
/* d is the multiplicative inverse of e, mod F.
Could also be mod (p-1)(q-1); however, we try to
choose the smallest possible d. */
mpz_mod_inverse(d, e, &F);
/* u is the multiplicative inverse of p, mod q,
if p < q. It is used when doing private key
RSA operations using the chinese remainder
theorem method. */
mpz_mod_inverse(u, p, q);
/* n = p * q (the public modulus). */
mpz_mul(n, p, q);