void rsa_generate_key
(
RSAPrivateKey *prv, RSAPublicKey *pub,
RandomState *state, unsigned int bits
)
{
MP_INT test, aux;
unsigned int pbits, qbits;
int ret;
mpz_init(&prv->q);
mpz_init(&prv->p);
mpz_init(&prv->e);
mpz_init(&prv->d);
mpz_init(&prv->u);
mpz_init(&prv->n);
mpz_init(&test);
mpz_init(&aux);
/* 计算质数 p、q 的位数 */
pbits = bits / 2;
qbits = bits - pbits;
retry0:
fprintf(stderr, "Generating p: ");
/* 生 成随机质数 p */
rsa_random_prime(&prv->p, state, pbits);
retry:
fprintf(stderr, "Generating q: ");
/* 生 成随机质数 q */
rsa_random_prime(&prv->q, state, qbits);
/* 判断是否 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;
}
/* 从质数 p、q 导出私钥 */
fprintf(stderr, "Computing the keys.../n");
derive_rsa_keys(&prv->n, &prv->e, &prv->d,
&prv->u, &prv->p, &prv->q, 5);
prv->bits = bits;
/* 从质数 p、q 导出公钥 */
pub->bits = bits;
mpz_init_set(&pub->n, &prv->n);
mpz_init_set(&pub->e, &prv->e);
/* 测试公钥和密钥是否有效 */
fprintf(stderr, "Testing the keys.../n");
rsa_random_integer(&test, state, bits);
mpz_mod(&test, &test, &pub->n); /* must be less than n. */
rsa_private(&aux, &test, prv);
rsa_public(&aux, &aux, pub);
if (mpz_cmp(&aux, &test) != 0)
{
fprintf(stderr,
"**** private+public failed to decrypt./n");
goto retry0;
}
rsa_public(&aux, &test, pub);
rsa_private(&aux, &aux, prv);
if (mpz_cmp(&aux, &test) != 0)
{
fprintf(stderr,
"**** public+private failed to decrypt./n");
goto retry0;
}
mpz_clear(&aux);
mpz_clear(&test);
fprintf(stderr, "Key generation complete./n");
}
_______________________________________________________
在上面的函数 成一对密钥时,首先调用函数
_______________________________________________________
void rsa_random_prime
(
MP_INT *ret, RandomState *state,
unsigned int bits
)
{
MP_INT start, aux;
unsigned int num_primes;
int *moduli;
long difference;
mpz_init(&start);
mpz_init(&aux);
retry:
/* 挑出一个随机的足够大的整数 */
rsa_random_integer(&start, state, bits);
/* 设置最高的两位 */
mpz_set_ui(&aux, 3);
mpz_mul_2exp(&aux, &aux, bits - 2);
mpz_ior(&start, &start, &aux);
/* 设置最低的两位为奇数 */
mpz_set_ui(&aux, 1);
mpz_ior(&start, &start, &aux);
/* 启动小质数的 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);
}
_______________________________________________________
随机产生一对大质数(p,q)。这对随机大质数要符合的条件是p 必须小于 q。然后调用下面的函数来生 成公钥和私钥对的其他组员:
static void derive_rsa_keys
(
MP_INT *n, MP_INT *e, MP_INT *d, MP_INT *u,
MP_INT *p, MP_INT *q,
unsigned int ebits
)
{
MP_INT p_minus_1, q_minus_1, aux, phi, G, F;
assert(mpz_cmp(p, q) < 0);
mpz_init(&p_minus_1);
mpz_init(&q_minus_1);
mpz_init(&aux);
mpz_init(&phi);
mpz_init(&G);
mpz_init(&F);
/* 计算 p-1 和 q-1. */
mpz_sub_ui(&p_minus_1, p, 1);
mpz_sub_ui(&q_minus_1, q, 1);
/* phi = (p - 1) * (q - 1) */
mpz_mul(&phi, &p_minus_1, &q_minus_1);
/* 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);
/* Clear auxiliary variables. */
mpz_clear(&p_minus_1);
mpz_clear(&q_minus_1);
mpz_clear(&aux);
mpz_clear(&phi);
mpz_clear(&G);
mpz_clear(&F);
}
_______________________________________________________
最后为检验所生 成的一对密钥的有效性,它调用下面的函数产生一个随机整数。
_______________________________________________________
void rsa_random_integer(MP_INT *ret, RandomState *state,
unsigned int bits)
{
unsigned int bytes = (bits + 7) / 8;
char *str = xmalloc(bytes * 2 + 1);
unsigned int i;
/* 生 成一个适当大小的16进制随机数, 把它转化 成mp型整数 */
for (i = 0; i < bytes; i++)
sprintf(str + 2 * i, "%02x", random_get_byte(state));
/* 转化到内部表示 */
if (mpz_set_str(ret, str, 16) < 0)
{
fprintf("Intenal error, mpz_set_str returned error");
exit(1);
}
/* Clear extra data. */
memset(str, 0, 2 * bytes);
if (str != NULL)
free(str);
else
exit(1);
/* Reduce it to the desired number of bits. */
mpz_mod_2exp(ret, ret, bits);
}
_______________________________________________________
(
RSAPrivateKey *prv, RSAPublicKey *pub,
RandomState *state, unsigned int bits
)
{
MP_INT test, aux;
unsigned int pbits, qbits;
int ret;
mpz_init(&prv->q);
mpz_init(&prv->p);
mpz_init(&prv->e);
mpz_init(&prv->d);
mpz_init(&prv->u);
mpz_init(&prv->n);
mpz_init(&test);
mpz_init(&aux);
/* 计算质数 p、q 的位数 */
pbits = bits / 2;
qbits = bits - pbits;
retry0:
fprintf(stderr, "Generating p: ");
/* 生 成随机质数 p */
rsa_random_prime(&prv->p, state, pbits);
retry:
fprintf(stderr, "Generating q: ");
/* 生 成随机质数 q */
rsa_random_prime(&prv->q, state, qbits);
/* 判断是否 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;
}
/* 从质数 p、q 导出私钥 */
fprintf(stderr, "Computing the keys.../n");
derive_rsa_keys(&prv->n, &prv->e, &prv->d,
&prv->u, &prv->p, &prv->q, 5);
prv->bits = bits;
/* 从质数 p、q 导出公钥 */
pub->bits = bits;
mpz_init_set(&pub->n, &prv->n);
mpz_init_set(&pub->e, &prv->e);
/* 测试公钥和密钥是否有效 */
fprintf(stderr, "Testing the keys.../n");
rsa_random_integer(&test, state, bits);
mpz_mod(&test, &test, &pub->n); /* must be less than n. */
rsa_private(&aux, &test, prv);
rsa_public(&aux, &aux, pub);
if (mpz_cmp(&aux, &test) != 0)
{
fprintf(stderr,
"**** private+public failed to decrypt./n");
goto retry0;
}
rsa_public(&aux, &test, pub);
rsa_private(&aux, &aux, prv);
if (mpz_cmp(&aux, &test) != 0)
{
fprintf(stderr,
"**** public+private failed to decrypt./n");
goto retry0;
}
mpz_clear(&aux);
mpz_clear(&test);
fprintf(stderr, "Key generation complete./n");
}
_______________________________________________________
在上面的函数 成一对密钥时,首先调用函数
_______________________________________________________
void rsa_random_prime
(
MP_INT *ret, RandomState *state,
unsigned int bits
)
{
MP_INT start, aux;
unsigned int num_primes;
int *moduli;
long difference;
mpz_init(&start);
mpz_init(&aux);
retry:
/* 挑出一个随机的足够大的整数 */
rsa_random_integer(&start, state, bits);
/* 设置最高的两位 */
mpz_set_ui(&aux, 3);
mpz_mul_2exp(&aux, &aux, bits - 2);
mpz_ior(&start, &start, &aux);
/* 设置最低的两位为奇数 */
mpz_set_ui(&aux, 1);
mpz_ior(&start, &start, &aux);
/* 启动小质数的 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);
}
_______________________________________________________
随机产生一对大质数(p,q)。这对随机大质数要符合的条件是p 必须小于 q。然后调用下面的函数来生 成公钥和私钥对的其他组员:
static void derive_rsa_keys
(
MP_INT *n, MP_INT *e, MP_INT *d, MP_INT *u,
MP_INT *p, MP_INT *q,
unsigned int ebits
)
{
MP_INT p_minus_1, q_minus_1, aux, phi, G, F;
assert(mpz_cmp(p, q) < 0);
mpz_init(&p_minus_1);
mpz_init(&q_minus_1);
mpz_init(&aux);
mpz_init(&phi);
mpz_init(&G);
mpz_init(&F);
/* 计算 p-1 和 q-1. */
mpz_sub_ui(&p_minus_1, p, 1);
mpz_sub_ui(&q_minus_1, q, 1);
/* phi = (p - 1) * (q - 1) */
mpz_mul(&phi, &p_minus_1, &q_minus_1);
/* 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);
/* Clear auxiliary variables. */
mpz_clear(&p_minus_1);
mpz_clear(&q_minus_1);
mpz_clear(&aux);
mpz_clear(&phi);
mpz_clear(&G);
mpz_clear(&F);
}
_______________________________________________________
最后为检验所生 成的一对密钥的有效性,它调用下面的函数产生一个随机整数。
_______________________________________________________
void rsa_random_integer(MP_INT *ret, RandomState *state,
unsigned int bits)
{
unsigned int bytes = (bits + 7) / 8;
char *str = xmalloc(bytes * 2 + 1);
unsigned int i;
/* 生 成一个适当大小的16进制随机数, 把它转化 成mp型整数 */
for (i = 0; i < bytes; i++)
sprintf(str + 2 * i, "%02x", random_get_byte(state));
/* 转化到内部表示 */
if (mpz_set_str(ret, str, 16) < 0)
{
fprintf("Intenal error, mpz_set_str returned error");
exit(1);
}
/* Clear extra data. */
memset(str, 0, 2 * bytes);
if (str != NULL)
free(str);
else
exit(1);
/* Reduce it to the desired number of bits. */
mpz_mod_2exp(ret, ret, bits);
}
_______________________________________________________