Commit e89a1126 authored by Niels Möller's avatar Niels Möller

New file.

Rev: src/nettle/rsa-keygen.c:1.1
parent c251c1fc
/* rsa-keygen.c
*
* Generation of RSA keypairs
*/
/* nettle, low-level cryptographics library
*
* Copyright (C) 2002 Niels Mller
*
* The nettle library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or (at your
* option) any later version.
*
* The nettle library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the nettle library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#if HAVE_LIBGMP
#include "rsa.h"
#include "bignum.h"
#include <assert.h>
#include <limits.h>
#include <stdlib.h>
#ifndef DEBUG
# define DEBUG 0
#endif
#if DEBUG
# include <stdio.h>
#endif
/* Returns a random number, 0 <= x < 2^bits. */
static void
bignum_random_size(mpz_t x, unsigned bits,
void *random_ctx, nettle_random_func random)
{
unsigned length = (bits + 7) / 8;
uint8_t *data = alloca(length);
random(random_ctx, length, data);
nettle_mpz_set_str_256(x, length, data);
if (bits % 8)
mpz_fdiv_r_2exp(x, x, bits);
}
#define NUMBER_OF_PRIMES 167
static const unsigned long primes[NUMBER_OF_PRIMES] = {
3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139,
149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211,
223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367,
373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443,
449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613,
617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691,
701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787,
797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877,
881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971,
977, 983, 991, 997
};
/* NOTE: The mpz_nextprime in current GMP is unoptimized. */
static void
bignum_next_prime(mpz_t p, mpz_t n, int count,
void *progress_ctx, nettle_progress_func progress)
{
mpz_t tmp;
unsigned long *moduli = NULL;
unsigned long difference;
int prime_limit = NUMBER_OF_PRIMES;
/* First handle tiny numbers */
if (mpz_cmp_ui(n, 2) <= 0)
{
mpz_set_ui(p, 2);
return;
}
mpz_set(p, n);
mpz_setbit(p, 0);
if (mpz_cmp_ui(p, 8) < 0)
return;
mpz_init(tmp);
if (prime_limit && (mpz_cmp_ui(p, primes[prime_limit]) <= 0) )
/* Use unly 3, 5 and 7 */
prime_limit = 3;
if (prime_limit)
{
/* Compute residues modulo small odd primes */
int i;
moduli = alloca(prime_limit * sizeof(*moduli));
for (i = 0; i < prime_limit; i++)
moduli[i] = mpz_fdiv_ui(p, primes[i]);
}
for (difference = 0; ; difference += 2)
{
if (difference >= ULONG_MAX - 10)
{ /* Should not happen, at least not very often... */
mpz_add_ui(p, p, difference);
difference = 0;
}
/* First check residues */
if (prime_limit)
{
int composite = 0;
int i;
for (i = 0; i < prime_limit; i++)
{
if (moduli[i] == 0)
composite = 1;
moduli[i] = (moduli[i] + 2) % primes[i];
}
if (composite)
continue;
}
mpz_add_ui(p, p, difference);
difference = 0;
if (progress)
progress(progress_ctx, '.');
/* Fermat test, with respect to 2 */
mpz_set_ui(tmp, 2);
mpz_powm(tmp, tmp, p, p);
if (mpz_cmp_ui(tmp, 2) != 0)
continue;
if (progress)
progress(progress_ctx, '+');
/* Miller-Rabin test */
if (mpz_probab_prime_p(p, count))
break;
}
mpz_clear(tmp);
}
/* Returns a random prime of size BITS */
static void
bignum_random_prime(mpz_t x, unsigned bits,
void *random_ctx, nettle_random_func random,
void *progress_ctx, nettle_progress_func progress)
{
assert(bits);
for (;;)
{
bignum_random_size(x, bits, random_ctx, random);
mpz_setbit(x, bits - 1);
/* Miller-rabin count of 25 is probably much overkill. */
bignum_next_prime(x, x, 25, progress_ctx, progress);
if (mpz_sizeinbase(x, 2) == bits)
break;
}
}
int
rsa_generate_keypair(struct rsa_public_key *pub,
struct rsa_private_key *key,
void *random_ctx, nettle_random_func random,
void *progress_ctx, nettle_progress_func progress,
unsigned n_size,
unsigned e_size)
{
mpz_t p1;
mpz_t q1;
mpz_t phi;
mpz_t tmp;
if (e_size)
{
/* We should choose e randomly. Is the size reasonable? */
if ((e_size < 16) || (e_size > n_size) )
return 0;
}
else
{
/* We have a fixed e. Check that it makes sense */
/* It must be odd */
if (!mpz_tstbit(pub->e, 0))
return 0;
/* And 3 or larger */
if (mpz_cmp_ui(pub->e, 3) < 0)
return 0;
}
if (n_size < RSA_MINIMUM_N_BITS)
return 0;
mpz_init(p1); mpz_init(q1); mpz_init(phi); mpz_init(tmp);
/* Generate primes */
for (;;)
{
/* Generate p, such that gcd(p-1, e) = 1 */
for (;;)
{
bignum_random_prime(key->p, (n_size+1)/2,
random_ctx, random,
progress_ctx, progress);
mpz_sub_ui(p1, key->p, 1);
/* If e was given, we must chose p such that p-1 has no factors in
* common with e. */
if (e_size)
break;
mpz_gcd(tmp, pub->e, p1);
if (mpz_cmp_ui(tmp, 1) == 0)
break;
else if (progress) progress(progress_ctx, 'c');
}
if (progress)
progress(progress_ctx, '\n');
/* Generate q, such that gcd(q-1, e) = 1 */
for (;;)
{
bignum_random_prime(key->q, n_size/2,
random_ctx, random,
progress_ctx, progress);
mpz_sub_ui(q1, key->q, 1);
/* If e was given, we must chose q such that q-1 has no factors in
* common with e. */
if (e_size)
break;
mpz_gcd(tmp, pub->e, q1);
if (mpz_cmp_ui(tmp, 1) == 0)
break;
else if (progress) progress(progress_ctx, 'c');
}
/* Now we have the primes. Is the product of the right size? */
mpz_mul(pub->n, key->p, key->q);
if (mpz_sizeinbase(pub->n, 2) != n_size)
/* We might get an n of size n_size-1. Then just try again. */
{
#if DEBUG
fprintf(stderr,
"\nWanted size: %d, p-size: %d, q-size: %d, n-size: %d\n",
n_size,
mpz_sizeinbase(key->p,2),
mpz_sizeinbase(key->q,2),
mpz_sizeinbase(pub->n,2));
#endif
if (progress)
{
progress(progress_ctx, 'b');
progress(progress_ctx, '\n');
}
continue;
}
if (progress)
progress(progress_ctx, '\n');
/* c = q^{-1} (mod p) */
if (mpz_invert(key->c, key->q, key->p))
/* This should succeed everytime. But if it doesn't,
* we try again. */
break;
else if (progress) progress(progress_ctx, '?');
}
mpz_mul(phi, p1, q1);
/* If we didn't have a given e, generate one now. */
if (e_size)
for (;;)
{
bignum_random_size(pub->e, e_size,
random_ctx, random);
/* Make sure it's odd and that the most significant bit is
* set */
mpz_setbit(pub->e, 0);
mpz_setbit(pub->e, e_size - 1);
/* Needs gmp-3, or inverse might be negative. */
if (mpz_invert(key->d, pub->e, phi))
break;
else if (progress) progress(progress_ctx, 'e');
}
else
{
/* Must always succeed, as we already that e
* doesn't have any common factor with p-1 or q-1. */
int res = mpz_invert(key->d, pub->e, phi);
assert(res);
}
/* Done! Almost, we must compute the auxillary private values. */
/* a = d % (p-1) */
mpz_fdiv_r(key->a, key->d, p1);
/* b = d % (q-1) */
mpz_fdiv_r(key->b, key->d, q1);
/* c was computed earlier */
pub->size = key->size = (mpz_sizeinbase(pub->n, 2) + 7) / 8;
assert(pub->size >= RSA_MINIMUM_N_OCTETS);
mpz_clear(p1); mpz_clear(q1); mpz_clear(phi); mpz_clear(tmp);
return 1;
}
#endif /* HAVE_LIBGMP */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment