Skip to content

ashtonmendes/Generating-Primes

Repository files navigation

<TITLE>Homework #7 - CSCI 531, Spring 2015</TITLE>

The purpose of this assignment is to get familiar with generating prime numbers, the multiple precision math library (called BIGNUM) of openssl, and modular arithematics with BIGNUM.

To use openssl on nunki.usc.edu, please see the additional notes on openssl.

Compiling:
    make hw7
an executable named hw7 is created.


Commandline Syntax & Program Output

    <TR><TD COLSPAN=3 ALIGN=LEFT BGCOLOR="#000000" WIDTH=100%>
            <FONT COLOR="#ffffff"><A NAME="rndsearch">
            <B>Random-Search</B></A></FONT>
        </TD>
    </TR>
  
    <TR><TD COLSPAN=3 ALIGN=LEFT>

For this assignment, you are required to implement the Random-Search algorithm outlined here.
It's slightly different from the lecture slides to make grading more manageable.

Random-Search(k,maxitr):
1) n = RndOddNum(k)
2) if (TrialDivision(n) == "fail") goto step (1)
3) if (Miller-Rabin(n,maxitr) == "prime") return(n)
goto step (1)
Letx = ceil(k/8). RndOddNum(k) first reads x bytes from rndfile and converts the data into a BIGNUM representation using BN_bin2bn() (first byte read is the most significant byte in BIGNUM). RndOddNum(k) then sets both bit zero (the least significant bit) and bit k-1 to one, sets all bits from k and above to zero in the BIGNUM, and returns the resulting BIGNUM. Please make sure that exactly x bytes of rndfile are consumed. If k=5, and the byte you read is 0xca (which is 1100 1010 in binary), RndOddNum(k) should return a 5-bit integer 0x1b (which is 0001 1011 in binary and 27 in decimal).

TrialDivision(n) tries all prime numbers that are less than or equal to sqrt(n) in primesfile in increasing order to see if it is a divisor of n. It returns "fail" if a prime divisor is found. Otherwise, it returns "pass". (It should return "error" if there are not enough prime numbers in primesfile.)

Finally, Miller-Rabin(n,maxitr) is specified above.

    <TR><TD COLSPAN=3 ALIGN=LEFT BGCOLOR="#000000" WIDTH=100%>
            <FONT COLOR="#ffffff"><A NAME="maurer">
            <B>Maurer's Algorithm</B></A></FONT>
        </TD>
    </TR>
  
    <TR><TD COLSPAN=3 ALIGN=LEFT>

For this assignment, you are required to implement Maurer's Algorithm outlined here.
It's slightly different from the lecture slides to make grading more manageable.

Maurer(k):
1) if (k <= 20) do forever {
1.1) n = RndOddNum(k)
1.2) if (TrialDivision(n) == "pass") return n
}
2) c = 0.1, m = 20
3) B = c * k^2 (not used)
4) (generate a fraction r, the size of q relative to n)
4.1) if (k <= 2m) r = 0.5
4.2) if (k > 2m) do forever {
4.2.1) r = RndByte() / 255.0
4.2.2) r = 0.5 + r / 2.0
4.2.3) if (k*(1-r) > m) break;
}
5) (recursion) q = Maurer(floor(r*k)+1)
6) num_bits_in_q = BN_num_bits(q)
I = floor(2^(k-2) / q)
7) do forever {
7.1) R = RndOddNum(k+1-num_bits_in_q)
R = (R mod I) + I + 1
n = 2Rq+1
7.2) if (TrialDivision(n) != "fail") {
num_bits_in_n = BN_num_bits(n)
7.2.1) do {
a = RndOddNum(num_bits_in_n)
} while (a <= 1 or a >= n-1))
7.2.2) b = a^{n-1} mod n
if (b == 1) {
b = a^{2R} mod n
d = gcd(b-1,n)
if (d == 1) return(n)
}
}
}
RndOddNum() and TrialDivision() are defined above.

RndByte() simply reads exactly one byte from rndfile and returns the data as an octet (or unsigned char).

    <TR><TD COLSPAN=3 ALIGN=LEFT BGCOLOR="#000000" WIDTH=100%>
            <FONT COLOR="#ffffff"><A
            NAME="testdata"><B>Test Data &amp; Sample Output</B></A>
                </FONT>
        </TD>
    </TR>

    <TR><TD COLSPAN=3 ALIGN=LEFT>

primes

Running the "hw7 primes -n=7" command should generate 4 prime numbers, i.e., 2, 3, 5, and 7. The output file is provided here as primes.n7.

Running the "hw7 primes -n=1048576" (1048576 = 220) command should generate 82025 prime numbers. The output file is provided here as primes.n220.

trialdiv

Running the "hw7 trialdiv -n=13 -p=primes.n220" or the "hw7 trialdiv -n=532212456847 -p=primes.n220" command should produce the "n passes trial division test" message.

Running the "hw7 trialdiv -n=667 -p=primes.n220" command should produce the "n is composite by trial division (mod 23 = 0)" message.

millerrabin

Running the "hw7 millerrabin -n=13 -t=20 -p=primes.n220" command should get an error message saying that either maxitr is too large or that there is not enough primes in primes.n220.

Running the "hw7 millerrabin -n=532212456847 -t=20 -p=primes.n220" command result in Miller-Rabin declaring n to be a prime number. The output file is provided here as mrprime.k40.

Running the "hw7 millerrabin -n=667 -t=20 -p=primes.n220" command result in Miller-Rabin declaring n to be a composite number since a strong witness of 2 is found.

Running the "hw7 millerrabin -n=532212456849 -t=20 -p=primes.n220" command result in Miller-Rabin declaring n to be a composite number since a strong witness of 2 is found. The output file is provided here as mrcomp.k40.

rndsearch

A sample 220 bytes long rndfile is provided here as rnd.220.

Please click on the links below to see sample output of the corresponding commands:

  hw7 rndsearch -k=10 -t=10 -p=primes.n220 -r=rnd.220 > rs.10
  hw7 rndsearch -k=11 -t=10 -p=primes.n220 -r=rnd.220 > rs.11
  hw7 rndsearch -k=12 -t=10 -p=primes.n220 -r=rnd.220 > rs.12
  hw7 rndsearch -k=13 -t=10 -p=primes.n220 -r=rnd.220 > rs.13
  hw7 rndsearch -k=14 -t=10 -p=primes.n220 -r=rnd.220 > rs.14
  hw7 rndsearch -k=128 -t=10 -p=primes.n220 -r=rnd.220 > rs.128

maurer

Please click on the links below to see sample output of the corresponding commands:
  hw7 maurer -k=10 -p=primes.n220 -r=rnd.220 > ma.10
  hw7 maurer -k=24 -p=primes.n220 -r=rnd.220 > ma.24
  hw7 maurer -k=32 -p=primes.n220 -r=rnd.220 > ma.32
  hw7 maurer -k=64 -p=primes.n220 -r=rnd.220 > ma.64
  hw7 maurer -k=96 -p=primes.n220 -r=rnd.220 > ma.96
  hw7 maurer -k=128 -p=primes.n220 -r=rnd.220 > ma.128
The commandline syntax for hw7 is as follows:
    hw7 primes -n=maxval
    hw7 trialdiv -n=number -p=primesfile
    hw7 millerrabin -n=number -t=maxitr -p=primesfile
    hw7 rndsearch -k=numbits -t=maxitr -p=primesfile -r=rndfile
    hw7 maurer -k=numbits -p=primesfile -r=rndfile

Square bracketed items are optional. Follows the UNIX convention that commandline options can come in any order. (Note: a commandline option is a commandline argument that begins with a - character in a commandline syntax specification.) If an input file is not specified, the program reads from stdin. Unless otherwise specified, output of the program goes to stdout and error messages go to stderr. number is in decimal and all output numeric values are in decimal.

The meaning of the commands are:

primes   :   Generate all prime numbers less than or equal to maxval. maxval must be between 2 and 224, inclusive. You can use the sieve of Eratosthenes to generate the needed prime numbers.

Since the sieve of Eratosthenes uses an array of maxval integers whose values can only be 0 or 1, please be memory efficient and use only maxval bits (i.e., ceil(maxval/8) bytes) for the array.

 
trialdiv   :   Test the primality of number using trial division by trying sequentially all small prime numbers from 2 to floor(sqrt(number)), inclusive. primesfile conforms to the primesfile format and must be used as the source of small prime numbers.
 
millerrabin   :   Test the primality of number using Miller-Rabin specified here with security parameter maxitr.
 
rndsearch   :   Generate a numbits-bit probable prime using the Random-Search(numbits,maxitr) algorithm specified here with security parameter maxitr.
 
maurer   :   Generate a numbits-bit provable prime using the Maurer(numbits) algorithm specified here.

The output for various commands are as follows.

primes   :   The output of this command is a file in the primesfile format.
 
trialdiv   :   If number passes the trial division test, your program should output the following string (please do not replace "n" with number):
  n passes trial division test
If the maxval in primesfile is strictly less than floor(sqrt(number)) and all prime numbers in primesfile are not divisors of number, your program should output the following string (please do not replace "n" with number):
  n passes trial division test (not enough primes)
If number fails the trial division test because it was divisible by prime number m, your program should output the following string (please replace "m" with the numeric value of m):
  n is composite by trial division (mod m = 0)
 
millerrabin   :   As your program progresses through various stages of the Miller-Rabin algorithm, please print out the following information.
  • Before you start, print the value of number.
  • After step (1), print the value of n-1, s, and r.
  • After step (2.2), print the value of a and y.
  • After step (2.3.1.1), print the value of j and y.
  • After Miller-Rabin returns, print the result.
Please use the specific format illustrated here. Below is an example if no strong witness is found (i.e., Miller-Rabin returns "prime") and maxitr=10:
  n = 1066283
    n-1 = 1066282
    s = 1
    r = 533141
    Itr 1 of 10, a = 2, y = 1066282 (which is n-1)
    Itr 2 of 10, a = 3, y = 1
    Itr 3 of 10, a = 5, y = 1066282 (which is n-1)
    Itr 4 of 10, a = 7, y = 1066282 (which is n-1)
    Itr 5 of 10, a = 11, y = 1066282 (which is n-1)
    Itr 6 of 10, a = 13, y = 1
    Itr 7 of 10, a = 17, y = 1
    Itr 8 of 10, a = 19, y = 1
    Itr 9 of 10, a = 23, y = 1066282 (which is n-1)
    Itr 10 of 10, a = 29, y = 1066282 (which is n-1)
  Miller-Rabin declares n to be a prime number
Please note that there is no leading space characters for the first and last lines and there are two space characters for the other lines above.

Below is an example if a strong witness is found (i.e., Miller-Rabin returns "composite"):

  n = 1066281
    n-1 = 1066280
    s = 3
    r = 133285
    Itr 1 of 10, a = 2, y = 728675
      j = 1 of 2, y = 902584
      j = 2 of 2, y = 1066279
  Miller-Rabin found a strong witness 2
In the above example, the "2" in "j = 1 of 2" is just s-1 (please see step 2.3.1 of Miller-Rabin). Please note that there are four leading space characters for the lines that begins with "j =".
 
rndsearch   :   As your program progresses through various stages of the Random-Seearch algorithm, please print out the following information.
  • At the beginning of step (1), print the iteration number.
  • After step (1), print the value of n.
  • If TrialDivision() returns "fail", print which small prime number is a divisor of n; otherwise, print a message that says that n passed trial division.
  • In step (3), during Miller-Rabin, please print the same information as in Miller-Rabin, except that every line of output is indented by 2 space characters to the right.
Please use the specific format illustrated here. Below is an example if trial division failed during the first few iterations:
  RANDOM-SEARCH: iteration 1
    n = 259
    n is composite by trial division (mod 7 = 0)
  RANDOM-SEARCH: iteration 2
    n = 447
    n is composite by trial division (mod 3 = 0)
  RANDOM-SEARCH: iteration 3
    n = 413
    n is composite by trial division (mod 7 = 0)
  RANDOM-SEARCH: iteration 4
    ...
Please note that there is no leading space characters for lines that starts with "RANDOM-SEARCH:" and there are two space characters for the other lines above.

Below is an example if finally Miller-Rabin returns "prime":

  RANDOM-SEARCH: iteration 6
    n = 367
    n passes trial division test
      n-1 = 366
      s = 1
      r = 183
      Itr 1 of 20, a = 2, y = 1
      Itr 2 of 20, a = 3, y = 366 (which is n-1)
      Itr 3 of 20, a = 5, y = 366 (which is n-1)
      Itr 4 of 20, a = 7, y = 1
      Itr 5 of 20, a = 11, y = 366 (which is n-1)
      ...
      Itr 19 of 20, a = 67, y = 1
      Itr 20 of 20, a = 71, y = 366 (which is n-1)
    Miller-Rabin declares n to be a prime number
Please note that there are additional two leading space characters for the output from Miller-Rabin above. You might want your Miller-Rabin routine to use an exact argument to be the base leading characters.
 
maurer   :   As your program progresses through various stages of the Maurer algorithm, please print out the following information.
  • Since Maurer(k) is a recursive routine, please assign level 0 to be the top level. At each recursive call to Maurer(), print the level and k.
  • If k <= 20, print the value of n after step (1.1). If TrialDivision() returns "fail" in step (1.2), print the reason why TrialDivision() failed. Otherwise, print that n passed TrialDivision().
  • In step (4), print the value of r in percent. Please round to the nearest integer value of percent. If the (4.2) path is taken, also print the last return value of RndByte() when it broke out of the loop at (4.2.3).
  • After step (5) returns, print the current level, k, and q.
  • After step (7.1), print the iteration number in (7) and the value of R and n.
  • If TrialDivision() returns "fail" in step (7.2), print the reason why TrialDivision() failed. Otherwise, print that n passed TrialDivision().
  • After step (7.2.1), print the value of a.
  • After level 0 of Maurer's algorithm returns, print the returned prime number.
Please use the specific format illustrated here. Below is an example for generating a 40-bit prime number:
Maurer: level 0, k=40
  step 4, r = 50%
Maurer: level 1, k=21
  step 4, r = 50%
Maurer: level 2, k=11
  step 1.1, n = 1027
    n is composite by trial division (mod 13 = 0)
  step 1.1, n = 1471
    n passes trial division test
Maurer: back to level 1, k=21, q=1471
  step 7, itr 1: R = 413, n = 1215047
    n passes trial division test
  step 7.2.1, itr 1: a = 1141677
Maurer: back to level 0, k=40, q=1215047
  step 7, itr 1: R = 202779, n = 492772031227
    n is composite by trial division (mod 7 = 0)
  step 7, itr 2: R = 142539, n = 346383168667
    n is composite by trial division (mod 148693 = 0)
  step 7, itr 3: R = 220807, n = 536581765859
    n is composite by trial division (mod 59 = 0)
  step 7, itr 4: R = 160387, n = 389755486379
    n is composite by trial division (mod 7 = 0)
  step 7, itr 5: R = 174443, n = 423912887643
    n is composite by trial division (mod 3 = 0)
  step 7, itr 6: R = 219009, n = 532212456847
    n passes trial division test
  step 7.2.1, itr 6: a = 335622790399

Maurer's Algorithm found an 40-bit prime: n = 532212456847

Please note that there is no leading space characters for lines that starts with "Maurer:".

When Maurer's Algorithm terminates, please use BN_num_bits() to report the actual number of bits in the generated prime number n.

 
primesfile Format
If there are m primes between 2 and maxval, inclusive, the output file must contain exactly m+1 words (a word is 4-bytes long and in big endian representation).

The first word you must output is maxval. It is followed by all the prime numbers, in increasing order, between 2 and maxval, inclusive.

 
Miller-Rabin
For this assignment, you are required to implement the Miller-Rabin test outlined here. It's slightly different from the lecture slides to make grading more manageable. Specifically, step (2.1) below has been changed to use a specified sequence of prime numbers from primesfile.
    Miller-Rabin(n,maxitr):
    1) write n-1 = 2sr such that r is odd
    2) for (i=1; i <= maxitr; i++) {
       2.1) a = the ith smallest prime number
            2.1.1) if (a > n-1) return("failure")
       2.2) compute y = ar mod n
       2.3) if (y != 1 and y != n-1) {
            2.3.1) for (j=1; j <= s-1 and y != n-1; j++) {
                   2.3.1.1) y = y2 mod n
                   2.3.1.2) if (y == 1) return("composite")
                   }
            2.3.2) if (y != n-1) return("composite")
            }
       }
    3) return("prime")
 
 
 
 
Grading Guidelines

About

Generating large prime numbers for cryptographic purposes, primality tests, etc.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors