void test_main(void) { struct knuth_lfib_ctx lfib; mpz_t p; unsigned bits; knuth_lfib_init(&lfib, 17); mpz_init(p); for (bits = 6; bits < 1000; bits = bits + 1 + bits/20) { if (verbose) fprintf(stderr, "bits = %d\n", bits); nettle_random_prime(p, bits, 0, &lfib, (nettle_random_func *) knuth_lfib_random, NULL, NULL); ASSERT (mpz_sizeinbase (p, 2) == bits); ASSERT (mpz_probab_prime_p(p, 25)); } mpz_clear(p); }
int main(int argc, char **argv) { long bits; mpz_t p; struct yarrow256_ctx yarrow; int verbose = 0; const char *random_file = NULL; int c; char *arg_end; clock_t start; clock_t end; enum { OPT_HELP = 300 }; static const struct option options[] = { /* Name, args, flag, val */ { "help", no_argument, NULL, OPT_HELP }, { "verbose", no_argument, NULL, 'v' }, { "random", required_argument, NULL, 'r' }, { NULL, 0, NULL, 0} }; while ( (c = getopt_long(argc, argv, "vr:", options, NULL)) != -1) switch (c) { case 'v': verbose = 1; break; case 'r': random_file = optarg; break; case OPT_HELP: usage(); return EXIT_SUCCESS; case '?': return EXIT_FAILURE; default: abort(); } argc -= optind; argv += optind; if (argc != 1) { usage(); return EXIT_FAILURE; } bits = strtol(argv[0], &arg_end, 0); if (*arg_end || bits < 0) { fprintf(stderr, "Invalid number.\n"); return EXIT_FAILURE; } if (bits < 3) { fprintf(stderr, "Bitsize must be at least 3.\n"); return EXIT_FAILURE; } /* NOTE: No sources */ yarrow256_init(&yarrow, 0, NULL); /* Read some data to seed the generator */ if (!simple_random(&yarrow, random_file)) { werror("Initialization of randomness generator failed.\n"); return EXIT_FAILURE; } mpz_init(p); start = clock(); nettle_random_prime(p, bits, 0, &yarrow, (nettle_random_func *) yarrow256_random, NULL, NULL); end = clock(); mpz_out_str(stdout, 10, p); printf("\n"); if (verbose) fprintf(stderr, "time: %.3g s\n", (double)(end - start) / CLOCKS_PER_SEC); return EXIT_SUCCESS; }
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; /* And size less than n */ if (mpz_sizeinbase(pub->e, 2) >= n_size) 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 (;;) { nettle_random_prime(key->p, (n_size+1)/2, 1, 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 (;;) { nettle_random_prime(key->q, n_size/2, 1, random_ctx, random, progress_ctx, progress); /* Very unlikely. */ if (mpz_cmp (key->q, key->p) == 0) continue; 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); assert (mpz_sizeinbase(pub->n, 2) == n_size); 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) { int retried = 0; for (;;) { nettle_mpz_random_size(pub->e, random_ctx, random, e_size); /* 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; if (progress) progress(progress_ctx, 'e'); retried = 1; } if (retried && progress) progress(progress_ctx, '\n'); } 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 = (n_size + 7) / 8; assert(pub->size >= RSA_MINIMUM_N_OCTETS); mpz_clear(p1); mpz_clear(q1); mpz_clear(phi); mpz_clear(tmp); return 1; }
/* Valid sizes, according to FIPS 186-3 are (1024, 160), (2048. 224), (2048, 256), (3072, 256). Currenty, we use only q_bits of 160 or 256. */ int dsa_generate_keypair(struct dsa_public_key *pub, struct dsa_private_key *key, void *random_ctx, nettle_random_func *random, void *progress_ctx, nettle_progress_func *progress, unsigned p_bits, unsigned q_bits) { mpz_t p0, p0q, r; unsigned p0_bits; unsigned a; switch (q_bits) { case 160: if (p_bits < DSA_SHA1_MIN_P_BITS) return 0; break; case 256: if (p_bits < DSA_SHA256_MIN_P_BITS) return 0; break; default: return 0; } mpz_init (p0); mpz_init (p0q); mpz_init (r); nettle_random_prime (pub->q, q_bits, 0, random_ctx, random, progress_ctx, progress); p0_bits = (p_bits + 3)/2; nettle_random_prime (p0, p0_bits, 0, random_ctx, random, progress_ctx, progress); if (progress) progress (progress_ctx, 'q'); /* Generate p = 2 r q p0 + 1, such that 2^{n-1} < p < 2^n. * * We select r in the range i + 1 < r <= 2i, with i = floor (2^{n-2} / (p0 q). */ mpz_mul (p0q, p0, pub->q); _nettle_generate_pocklington_prime (pub->p, r, p_bits, 0, random_ctx, random, p0, pub->q, p0q); if (progress) progress (progress_ctx, 'p'); mpz_mul (r, r, p0); for (a = 2; ; a++) { mpz_set_ui (pub->g, a); mpz_powm (pub->g, pub->g, r, pub->p); if (mpz_cmp_ui (pub->g, 1) != 0) break; } if (progress) progress (progress_ctx, 'g'); mpz_set(r, pub->q); mpz_sub_ui(r, r, 2); nettle_mpz_random(key->x, random_ctx, random, r); mpz_add_ui(key->x, key->x, 1); mpz_powm(pub->y, pub->g, key->x, pub->p); if (progress) progress (progress_ctx, '\n'); mpz_clear (p0); mpz_clear (p0q); mpz_clear (r); return 1; }