📄 moduli.c
字号:
/* $OpenBSD: moduli.c,v 1.10 2005/01/17 03:25:46 dtucker Exp $ *//* * Copyright 1994 Phil Karn <karn@qualcomm.com> * Copyright 1996-1998, 2003 William Allen Simpson <wsimpson@greendragon.com> * Copyright 2000 Niels Provos <provos@citi.umich.edu> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *//* * Two-step process to generate safe primes for DHGEX * * Sieve candidates for "safe" primes, * suitable for use as Diffie-Hellman moduli; * that is, where q = (p-1)/2 is also prime. * * First step: generate candidate primes (memory intensive) * Second step: test primes' safety (processor intensive) */#include "includes.h"#include "xmalloc.h"#include "log.h"#include <openssl/bn.h>/* * File output defines *//* need line long enough for largest moduli plus headers */#define QLINESIZE (100+8192)/* Type: decimal. * Specifies the internal structure of the prime modulus. */#define QTYPE_UNKNOWN (0)#define QTYPE_UNSTRUCTURED (1)#define QTYPE_SAFE (2)#define QTYPE_SCHNORR (3)#define QTYPE_SOPHIE_GERMAIN (4)#define QTYPE_STRONG (5)/* Tests: decimal (bit field). * Specifies the methods used in checking for primality. * Usually, more than one test is used. */#define QTEST_UNTESTED (0x00)#define QTEST_COMPOSITE (0x01)#define QTEST_SIEVE (0x02)#define QTEST_MILLER_RABIN (0x04)#define QTEST_JACOBI (0x08)#define QTEST_ELLIPTIC (0x10)/* * Size: decimal. * Specifies the number of the most significant bit (0 to M). * WARNING: internally, usually 1 to N. */#define QSIZE_MINIMUM (511)/* * Prime sieving defines *//* Constant: assuming 8 bit bytes and 32 bit words */#define SHIFT_BIT (3)#define SHIFT_BYTE (2)#define SHIFT_WORD (SHIFT_BIT+SHIFT_BYTE)#define SHIFT_MEGABYTE (20)#define SHIFT_MEGAWORD (SHIFT_MEGABYTE-SHIFT_BYTE)/* * Using virtual memory can cause thrashing. This should be the largest * number that is supported without a large amount of disk activity -- * that would increase the run time from hours to days or weeks! */#define LARGE_MINIMUM (8UL) /* megabytes *//* * Do not increase this number beyond the unsigned integer bit size. * Due to a multiple of 4, it must be LESS than 128 (yielding 2**30 bits). */#define LARGE_MAXIMUM (127UL) /* megabytes *//* * Constant: when used with 32-bit integers, the largest sieve prime * has to be less than 2**32. */#define SMALL_MAXIMUM (0xffffffffUL)/* Constant: can sieve all primes less than 2**32, as 65537**2 > 2**32-1. */#define TINY_NUMBER (1UL<<16)/* Ensure enough bit space for testing 2*q. */#define TEST_MAXIMUM (1UL<<16)#define TEST_MINIMUM (QSIZE_MINIMUM + 1)/* real TEST_MINIMUM (1UL << (SHIFT_WORD - TEST_POWER)) */#define TEST_POWER (3) /* 2**n, n < SHIFT_WORD *//* bit operations on 32-bit words */#define BIT_CLEAR(a,n) ((a)[(n)>>SHIFT_WORD] &= ~(1L << ((n) & 31)))#define BIT_SET(a,n) ((a)[(n)>>SHIFT_WORD] |= (1L << ((n) & 31)))#define BIT_TEST(a,n) ((a)[(n)>>SHIFT_WORD] & (1L << ((n) & 31)))/* * Prime testing defines *//* Minimum number of primality tests to perform */#define TRIAL_MINIMUM (4)/* * Sieving data (XXX - move to struct) *//* sieve 2**16 */static u_int32_t *TinySieve, tinybits;/* sieve 2**30 in 2**16 parts */static u_int32_t *SmallSieve, smallbits, smallbase;/* sieve relative to the initial value */static u_int32_t *LargeSieve, largewords, largetries, largenumbers;static u_int32_t largebits, largememory; /* megabytes */static BIGNUM *largebase;int gen_candidates(FILE *, int, int, BIGNUM *);int prime_test(FILE *, FILE *, u_int32_t, u_int32_t);/* * print moduli out in consistent form, */static intqfileout(FILE * ofile, u_int32_t otype, u_int32_t otests, u_int32_t otries, u_int32_t osize, u_int32_t ogenerator, BIGNUM * omodulus){ struct tm *gtm; time_t time_now; int res; time(&time_now); gtm = gmtime(&time_now); res = fprintf(ofile, "%04d%02d%02d%02d%02d%02d %u %u %u %u %x ", gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min, gtm->tm_sec, otype, otests, otries, osize, ogenerator); if (res < 0) return (-1); if (BN_print_fp(ofile, omodulus) < 1) return (-1); res = fprintf(ofile, "\n"); fflush(ofile); return (res > 0 ? 0 : -1);}/* ** Sieve p's and q's with small factors */static voidsieve_large(u_int32_t s){ u_int32_t r, u; debug3("sieve_large %u", s); largetries++; /* r = largebase mod s */ r = BN_mod_word(largebase, s); if (r == 0) u = 0; /* s divides into largebase exactly */ else u = s - r; /* largebase+u is first entry divisible by s */ if (u < largebits * 2) { /* * The sieve omits p's and q's divisible by 2, so ensure that * largebase+u is odd. Then, step through the sieve in * increments of 2*s */ if (u & 0x1) u += s; /* Make largebase+u odd, and u even */ /* Mark all multiples of 2*s */ for (u /= 2; u < largebits; u += s) BIT_SET(LargeSieve, u); } /* r = p mod s */ r = (2 * r + 1) % s; if (r == 0) u = 0; /* s divides p exactly */ else u = s - r; /* p+u is first entry divisible by s */ if (u < largebits * 4) { /* * The sieve omits p's divisible by 4, so ensure that * largebase+u is not. Then, step through the sieve in * increments of 4*s */ while (u & 0x3) { if (SMALL_MAXIMUM - u < s) return; u += s; } /* Mark all multiples of 4*s */ for (u /= 4; u < largebits; u += s) BIT_SET(LargeSieve, u); }}/* * list candidates for Sophie-Germain primes (where q = (p-1)/2) * to standard output. * The list is checked against small known primes (less than 2**30). */intgen_candidates(FILE *out, int memory, int power, BIGNUM *start){ BIGNUM *q; u_int32_t j, r, s, t; u_int32_t smallwords = TINY_NUMBER >> 6; u_int32_t tinywords = TINY_NUMBER >> 6; time_t time_start, time_stop; int i, ret = 0; largememory = memory; if (memory != 0 && (memory < LARGE_MINIMUM || memory > LARGE_MAXIMUM)) { error("Invalid memory amount (min %ld, max %ld)", LARGE_MINIMUM, LARGE_MAXIMUM); return (-1); } /* * Set power to the length in bits of the prime to be generated. * This is changed to 1 less than the desired safe prime moduli p. */ if (power > TEST_MAXIMUM) { error("Too many bits: %u > %lu", power, TEST_MAXIMUM); return (-1); } else if (power < TEST_MINIMUM) { error("Too few bits: %u < %u", power, TEST_MINIMUM); return (-1); } power--; /* decrement before squaring */ /* * The density of ordinary primes is on the order of 1/bits, so the * density of safe primes should be about (1/bits)**2. Set test range * to something well above bits**2 to be reasonably sure (but not * guaranteed) of catching at least one safe prime. */ largewords = ((power * power) >> (SHIFT_WORD - TEST_POWER)); /* * Need idea of how much memory is available. We don't have to use all * of it. */ if (largememory > LARGE_MAXIMUM) { logit("Limited memory: %u MB; limit %lu MB", largememory, LARGE_MAXIMUM); largememory = LARGE_MAXIMUM; } if (largewords <= (largememory << SHIFT_MEGAWORD)) { logit("Increased memory: %u MB; need %u bytes", largememory, (largewords << SHIFT_BYTE)); largewords = (largememory << SHIFT_MEGAWORD); } else if (largememory > 0) { logit("Decreased memory: %u MB; want %u bytes", largememory, (largewords << SHIFT_BYTE)); largewords = (largememory << SHIFT_MEGAWORD); } TinySieve = calloc(tinywords, sizeof(u_int32_t)); if (TinySieve == NULL) { error("Insufficient memory for tiny sieve: need %u bytes", tinywords << SHIFT_BYTE); exit(1); } tinybits = tinywords << SHIFT_WORD; SmallSieve = calloc(smallwords, sizeof(u_int32_t)); if (SmallSieve == NULL) { error("Insufficient memory for small sieve: need %u bytes", smallwords << SHIFT_BYTE); xfree(TinySieve); exit(1); } smallbits = smallwords << SHIFT_WORD; /* * dynamically determine available memory */ while ((LargeSieve = calloc(largewords, sizeof(u_int32_t))) == NULL) largewords -= (1L << (SHIFT_MEGAWORD - 2)); /* 1/4 MB chunks */ largebits = largewords << SHIFT_WORD; largenumbers = largebits * 2; /* even numbers excluded */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -