From: Wei Dai <weidai@eskimo.com>
To: Cypherpunks <cypherpunks@toad.com>
Message Hash: 2816606b0d43fb35d372628326496fd5475ff384a06ff50a1e0b0285367c06bc
Message ID: <Pine.SUN.3.91.951123024142.12404A-100000@eskimo.com>
Reply To: N/A
UTC Datetime: 1995-11-23 11:08:12 UTC
Raw Date: Thu, 23 Nov 95 03:08:12 PST
From: Wei Dai <weidai@eskimo.com>
Date: Thu, 23 Nov 95 03:08:12 PST
To: Cypherpunks <cypherpunks@toad.com>
Subject: generating provable primes
Message-ID: <Pine.SUN.3.91.951123024142.12404A-100000@eskimo.com>
MIME-Version: 1.0
Content-Type: text/plain
Several days ago someone (I forgot who he was) asked about code for
primality tests. I just implemented an algorithm to generate random
provable primes that is only about 50% slower than generating probable
primes. It will be in the next version of Crypto++, but I've attached
code for the main function in case anyone is interested in the
algorithm. Full description can be found in "Fast Generation of Prime
Numbers and Secure Public-Key Cryptographic Parameters" by U.M. Maurer in
Journal of Cryptology, Volume 8 Number 3, 1995. The paper also describes
a more complicated algorithm that produces primes with a more uniform
distribution.
There was discussion some days ago about generating strong primes
for DH exchange moduli. Eric Young reported that he spent tens of hours
of CPU time to generate a 4096 bit prime p such that (p-1)/2 is also
prime. However, there is really no reason why DH exchange moduli must be of
the form 2q+1 where q is a prime. It should be sufficient that they are
of the form rq+1, where q is a large enough prime (say more than 256
bits). The following algorithm generates a provable prime p=2rq+1, where q
is a prime with at least half the length of p.
bignum ProvablePrime(RandomNumberGenerator &rng, unsigned int bits)
{
const unsigned smallPrimeBound = 29, c_opt=10;
bignum p;
BuildPrimeTable();
if (bits < smallPrimeBound)
{
do
p.Randomize(rng, bignum::Power2(bits-1),
bignum::Power2(bits)-1, ODD);
while (TrialDivision(p, 1 << ((bits+1)/2)));
}
else
{
const unsigned margin = bits > 50 ? 20 : (bits-10)/2;
double relativeSize;
do
relativeSize = pow(2.0,
double(rng.GetLong())/0xffffffff - 1);
while (bits * relativeSize >= bits - margin);
bignum a,b;
bignum q = ProvablePrime(rng, unsigned(bits*relativeSize));
bignum I = bignum::Power2(bits-2)/q;
bignum I2 = I << 1;
unsigned int trialDivisorBound = (unsigned
int)min((unsigned long)primeTable[primeTableSize-1], (unsigned
long)bits*bits/c_opt);
boolean success = FALSE;
do
{
p.Randomize(rng, I, I2, ANY);
p *= q; p <<= 1; ++p;
if (!TrialDivision(p, trialDivisorBound))
{
a.Randomize(rng, 2, p-1, ANY);
b = a.ExponentiateMod((p-1)/q, p);
success = (Gcd(b-1, p) == 1) &&
(b.ExponentiateMod(q, p) == 1);
}
}
while (!success);
}
return p;
}
Return to November 1995
Return to “Wei Dai <weidai@eskimo.com>”
1995-11-23 (Thu, 23 Nov 95 03:08:12 PST) - generating provable primes - Wei Dai <weidai@eskimo.com>