Generating Strong Prime Numbers For RSA Using Probabilistic Rabin-Miller Algorithm
Generating Strong Prime Numbers For RSA Using Probabilistic Rabin-Miller Algorithm
An integer p > 1 is called a prime number in case there is no divisor d of p satisfying 1 < d < p. If
an integer a > 1 is not a prime, it is called a composite number.
Characteristics of primes
Every integer n greater than 1 can be expressed as a product of primes (with perhaps only one
factor).
The number of primes is infinite. That is, there is no end to the sequence of primes.
The factoring of any integer n > 1 into primes is unique apart from the order of the prime
factors.
The RSA cryptographic algorithm uses a lot of prime numbers in generating its keys. These keys
in turn will hold the strength of the encryption. In this paper I will discuss how a large number of
large primes can be generated.
Public-key algorithms need prime numbers. Any reasonably sized network needs lots of them.
Before discussing the mathematics of prime number generation, some of common questions are
answered.
1.If everyone needs a different prime number, wont we run out? No. In fact, there are
approximately 10151 primes 512-bits in length or less. For numbers near n, the probability that a
random number is prime is approximately one in ln n. So the total number of primes less that n is
n/(ln n).
2.What if two people accidentally pick up the same prime number? It wont happen. With over
10151 prime numbers to choose from, the odds of that happening are significantly less than the
odds of your computer spontaneously combusting at the exact moment you win the lottery.
3.If someone creates a database of all primes, wont he be able to use that database to break
public-key algorithms? Yes, but he cant do it. If you could store one gigabyte of information on
a drive weighing one gram, then a list of just the 512-bit primes would weight so much that it
would exceed the Chandrasekhar limit and collapse into a black hole &ldots; so you couldnt
retrieve the data anyway.
There are several probabilistic primality tests; tests that determine whether a number is prime
with a given degree of confidence. Assuming this "degree of confidence" is large enough, these
sorts of tests are good enough.
Various probabilistic primality-testing algorithms include:
Rabin-Miller Test
Lucas-Lehmer Algorithm
Fermats Test
Frobenius-Grantham
The algorithm everyone uses was developed by Michael Rabin, based in part on Gary Millers
ideas. Actually, this is a simplified version of the algorithm recommended in the DSS proposal.
Therefore, we start out with Rabin-Miller algorithm.
Algorithm
Input : an odd integer n >= 3 and number of iterations t >= 1
Output : Prime or Composite
1. Write n 1 = 2sr such that r is odd
2. For i from 1 to t do the following
2.1 Choose a random integer a, 2<= a <= n-2
2.2 Compute y = ar mod n
2.3 If y != 1 and y!= n 1
j=1
While j<= s-1 and y != n 1
Compute y = y2 mod n
If y = 1 then return (Composite)
j=j+1
if y ! = n 1 then return (Composite)
3. Return Prime
Class named RabinMiller with constructor of form MillerRabin(BigInteger n, int t) has been used
for experiment. This class expects arbitrary long precision number and number of iterations t.
We then use method isPrime() to see if this number is a probable prime.
The Rabin-Miller Probabilistic Primality Test Proof
Fermats Little Theorem. Let be prime and suppose a.( does not divide a) Then
a-1 1 (mod )
This is a generalization of the Chinese Hypothesis and a special case of Eulers Theorem
Euclids Lemma. Let be prime and suppose | ab. Then either | a or | b.
Now we can outline a development which leads to Millers Test for compositeness.
By Fermats Little Theorem, if is an odd prime and | b, then
b-1 1 (mod )
Since -1 is even,
| (b(-1)/2 1) (b(-1)/2 + 1)
By Euclids Lemma,
b(-1)/2 1 (mod )
If (-1)/2 is even and b(-1)/2 1 (mod ), then we know that
b(-1)/4 1 (mod )
We can repeat this until (-1)/2k is odd or b(-1)/2^k - 1 (mod ) for some k.
10 Iterations
0.05 sec
0.9 sec
8.8 sec
45 sec
20 Iterations
0.083 sec
1.7 sec
17 sec
90 sec
As we can see, time it takes to test for primality is proportional to the number of iterations. In
addition, as we increase the number of bits, the time it took for the algorithm increased
substantially.
Originally, random number was generated and time was measured to compare the time it took for
different number of iterations. However, test result indicated that the time it took was very close.
As the result was examined, it was noted that most numbers that was generated at random was a
Composite number; therefore, number of iterations didnt matter much(cause it always got
reject in first few iteration). Thus, in this case, we used numbers that we knew were Probable
Prime numbers to compare the time.
Experiment
Size of Number( in bits )
130
512
1024
2048
Lucas Test
0.125 sec
0.6 sec
5 sec
35 sec
When we applied Lucas Test to our test vectors that passed 20 iterations of Miller-Rabin, some of
them were determined to be Composites. Here we show some list of 1024 bit numbers that
passed Miller-Rabin(20 iterations) but didnt pass Lucas Test.
943663967303341733831073530494149595215288153105481870301659362295789602095234
218089124597953290352035102845761871600763866437004412165477329142505789342618
915108271402670435920072251607983489136394725647150554452015124613593594887954
27875530231001298552452230535485049737222714000227878890892901228389026881
138028649176899647846076023812164793645371887571371559091892986639999096471811
910222267538577825033963552683101137782650479906670021895135954212738694784814
783986671046107023185842481502719762055887490765764329237651328922972514308635
045190654896041748716218441926626988737664133219271115413563418353821396401
123301261697053560451930527879636974557474268923771832437126939266601921428796
348203611050423256894847735769138870460373141723679005090549101566289920247264
982095246187318303659027201708559916949810035265951104246512008259674244307851
578647894027803356820480862664695522389066327012330793517771435385653616841
119432521682023078841121052226157857003721669633106050345198988740042219728400
958282159638484144822421840470442893056822510584029066504295892189315912923804
894933736660559950053226576719285711831138657839435060908151231090715952576998
400120335346005544083959311246562842277496260598128781581003807229557518839
132082885240291678440073580124226578272473600569147812319294626601995619845059
779715619475871419551319029519794232989255381829366374647864619189704922722431
776563860747714706040922215308646535910589305924065089149684429555813953571007
126408164577035854428632242206880193165045777949624510896312005014225526731
153410708946188157980279532372610756837706984448408515364579602515073276538040
155990230789600191915021209039203172105094957316552912585741177975853552299222
501069267567888742458519569317286299134843250075228359900070009684517875782331
709619287588451883575354340318132216817231993558066067063143257425853927599
103130593592068072608023213244858971741946977638988649427937324034014356815504
971087381663169829571046157738503075005527471064224791270584831779395959349442
093395294980019731027051356344056416276026592333932610954020105156667883269888
206386119513058400355612571198438511950152690467372712488391425876725831041
It is known that Lucas Test is independent of Miller-Rabin test. Therefore by combining these
two algorithms, we present a powerful algorithm in the next section that utilizes one iteration of
Miller-Rabin with Lucas Test.(we also noticed that if the number passed a single iterations of
Miller-Rabin, its most likely to pass more iterations of Miller-Rabin - > Increasing Miller-Rabin
increases worst case probability of error; however, in practice, Miller-Rabin yields substantially
better probability of error(than worst case error) and each subsequent iteration improves the
algorithm moderately)
Lucas-Lehmer Test
Pomerance, Selfridge and Wagstaff have proposed a test, based on a combination of the Strong
Probable Prime Test and the Lucas Probable Test, that seems very powerful. Indeed, nobody yet
claimed the $620 that they offer for a composite that passes it, even though they have relaxed the
conditions of the offer so that the Probable Prime Test no longer need be Strong. In this
section, we present a test that combines Probable Prime Test(Miller Rabin test) and the Lucas
Probable Test.
MillerRabin test = new MillerRabin(a, 1);
if (test.isPrime() == true) {
lt = new LucasTest(a);
if (lt.isPrime()) System.out.println("prime1");
}
We measure a time taken by applying a single iteration of Miller-Rabin followed by Lucas Test.
Lucas-Lehmer Test
0.125 sec
0.72 sec
6.12 sec
40 sec
Grantham-Frobenius
This is a test based on Frobenius pseudoprimes developed by Grantham which is passed by
Composite Numbers with probability at most 1/7710. Algorithm is presented below.
1. Choose pairs (b,c) at random with 1<= b, c < n until one is found with (b2+4c / n ) = -1and
(-c/n) = 1, or with gcd(b2+4c, n), gcd(b,n) or gcd(c,n) a notrivial divisor of n. If latter case occurs
before the f ormer, declare n to be composite and stop. If after B pairs are tested, none is found
satisfying the above conditions, declare n to be a probable prime and stop(we need to do this
since we cant declare prime as composite at any case)
2. Perform Quadratic Frobenius Test
1) Test n for divisibility by primes less than or equal to min {B, n^0.5}. If it is divisible by one
of these primes, declare n to be composite and stop
2) Test whether n^0.5 . If it is declare n to be composite and stop
3) Compute x^(n+1 / 2) mod (n, x2 bx c). If x^(n+1 /2) /n, declare n to be composite
and stop
4) Compute x^(n+1) mod (n, x2 bx c). If x^(n+1) != - c, declare n to be composite and stop
2^j*s
!= -1 mod (n,x2 bx
5) Let n2 1 = 2rs, where s is odd. If x != 1 mod(n, x2 bx c), and x
c) for all 0 <= j <= r-2, declare n to be composite and stop.
3. If n is not declared composite in Steps 1-5, declare n to be a probable prime.
89
178
355
bit(# of primes)
MillerRabin(20)
Lucas-Lehmer
256
Time
35
43
bit(20)
# Tested
1869
2488
512
Time
73
70
bit(2)
# Tested
742
742
1024
Time
420
850
bit(1)
# Tested
504
1175
}
}
}
x = x.add( two );
}
count ++;
}
System.out.println(i + " number tested to find " + numPrimes + " primes ");
}
Lucas Test
import java.math.*;
class LucasTest {
final int COMPOSITE = 0, PRIME = 1;
final BigInteger _zero = new BigInteger("0");
final BigInteger _one = new BigInteger("1");
final BigInteger _two = new BigInteger("2");
final BigInteger _three = new BigInteger("3");
final BigInteger _four = new BigInteger("4");
final BigInteger _five = new BigInteger("5");
final BigInteger _seven = new BigInteger("7");
final BigInteger _eight = new BigInteger("8");
final BigInteger _negativeOne = new BigInteger("-1");
BigInteger _u, _v, testVector;
boolean _isPrime;
public LucasTest() {
}
/**
* returns number being tested
*/
public BigInteger getNumber() {
return testVector;
}
public LucasTest(BigInteger n) {
BigInteger d, p, q, one, four, temp;
int result;
testVector = n;
d = findValueOfD( n );
System.out.println("d = " + d.toString());
q = new BigInteger("0");
p = new BigInteger("1");
//q = 1-d/4
q = q.subtract(d);
q = q.divide( _four );
d = p.multiply(p);
temp = q.multiply(_four);
d = d.subtract(temp);
result = findUk(p,q,d,n);
if (result == COMPOSITE )
_isPrime = false;
else
_isPrime = true;
}
/**
* isPrime() returns true if it passes Lucas test
* otherwise, returns false
*/
public boolean isPrime() {
return _isPrime;
}
protected BigInteger findValueOfD(BigInteger n) {
int i = 1;
Integer candidate = new Integer(5);
BigInteger d;
BigInteger temp;
//generate candidate d
d = new BigInteger( candidate.toString() );
while ( true ) {
temp = findJacobi3(d, n);
if (temp.intValue() == -1) {
return d;
}
i = i*(-1);
candidate = new Integer( (candidate.intValue()*i*(-1) + 2) * i );
d = new BigInteger( candidate.toString() );
}
}
protected int findUk(BigInteger p, BigInteger q, BigInteger d, BigInteger n) {
BigInteger u, v, temp, k;
int r, i;
k = n.add(_one);
r = k.bitLength();
// u =1, v = p
u = new BigInteger("1");
v = new BigInteger("0");
v = v.add(p);
//System.out.println("u = " + u.toString());
//System.out.println("v = " + v.toString());
_u = u;
_v = v;
for(i=r-2; i >= 0; i--) {
setUV( d, p, n);
if (k.testBit(i)) {
setUV2(d, p, n);
}
}
u = _u;
v = _v;
temp = u.mod(n);
if (temp.intValue() == 0)
return PRIME;
else
return COMPOSITE;
}
x = y.subtract(x);
if (y.mod(_four).intValue() == 3) {
j = j.negate();
}
}
while (true) {
if (x.remainder(_four).intValue() == 0) {
x = x.divide(_four);
}
else
break;
}
if (x.testBit(0) == false) {
x = x.shiftRight(1);
if ( (y.mod(_eight).intValue() == 3) || (y.mod(_eight).intValue()
== 5) ) {
j = j.negate();
}
}
if (x.intValue() == 1)
return j;
if ( (x.mod(_four).intValue() == 3) && (y.mod(_four).intValue() == 3) ) {
j = j.negate();
}
temp = x;
x = y;
y = temp;
}
}