Bootstrap

rsa源码

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 &gt;= small_primes<i>)
        moduli<i> -= small_primes<i>;
      if (moduli<i> + difference == 0)
        break;
    }
    if (i &lt; 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) &lt; 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) &gt;= 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 &lt; 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 &lt; bytes; i++)
    sprintf(str + 2 * i, "%02x", random_get_byte(state));

  /* 转化到内部表示 */
  if (mpz_set_str(ret, str, 16) &lt; 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);
}
_______________________________________________________ 
;