[Edu-sig] Miller-Rabin (first draft, slow)

Kirby Urner pdx4d@teleport.com
Thu, 14 Dec 2000 10:51:26 -0800


>not) -- I don't have the tests for that written.  A Fermat test 
>seems impractical.  Has anyone done Miller-Rabin in pure Python, 
>for pedagogic purposes?  Still looking into it.  Yes, I know, 
>I know, I need to join the Python cryptography SIG.
>
>Kirby

I haven't chatted with the Python crypto heads yet, but using
http://www.middlebury.edu/~pemerson/thesis/node5.html and the
related source code, I was able to come up with a first draft
of Miller-Rabin's primality test in pure Python.

Although I believe it implements the algorithm "by the book",
it's quite slow -- no way I'd want to sic this on some randomly
generated 100-digit possible-prime.  Like, it took a minute and 
a half just to verify that 399173 was very likey prime -- 
something lowly trial-by-division can handle (with certainty)
in the blink of an eye.

The paper's author, Paul Emerson, was getting his program to 
verify 57*2**502 +1 in under 3 minutes, checking against 20 bases.  
There's gotta be some drastic difference in our hardware and/or 
software in that case.  His is written in C and uses mpz utilities.  
I hypothesize that I should likewise be using Python's optional 
mpz module -- but that one doesn't come with the default binary 
for Windows.  Maybe in my Linux RPM?

Note, in the code below, some of the functions are actually defined 
in primes.py, which is at my website:  basically gcd(a,b) and 
get2nb(n) -- find the greatest common divisor (Euclid's Algorithm) 
and get n successive primes from 2 (trial-by-division).

See: http://www.python.org/pipermail/edu-sig/2000-August/000599.html
for more on Euclid's Algorithm (includes Python and DrScheme source), 
plus a discussion of precision issues.  I think GCD, LCM and 
Euclid's Algorithm in particular belong at the grade 6-8 level.

Miller-Rabin, along with other primality tests, should be mentioned
in high school, but possibly only in a story-telling context (along
with some play with the Euler-Fermat test -- see related reading
below), i.e. the point might be to give the flavor of number theory 
applied to cryptography -- a topic with many historical ramifications.

import primes, time 
 
def ppt(n,i=6):
    """
    Probable Primality Test (Miller-Rabin)
    """
    start = time.clock()
    # get i successive primes from 2 to < n
    bases  = filter(lambda x,n=n: x<n, primes.get2nb(i))
    isprob = 0
    # if any of the primes is a factor, we're done
    if 0 in map(lambda i,n=n,b=bases:
                primes.gcd(n,b[i])==1, range(len(bases))):
       print "Definitely not prime"
       return
    tests  = 0
    m = n-1
    r=0
    # turning (n-1) into form (2**r) * m
    while m%2==0:
        m = m/2
        r += 1
    print "(n-1,r,m) = (%s,%s,%s)" % (2L**r*m,r,m)        
    for b in bases:
        tests += 1
        print "Testing base %s" % b
        isprob = miller(m,r,b,n)
        if not isprob: break
            
    if not isprob:  print "Definitely not prime"
    else: print "%s chance of being prime" % (1-(1./(4**tests)))
    print "Elapsed time: %s seconds" % (time.clock()-start)

def miller(m,r,b,n):
    result = 0    
    bignum = b**m
    # Miller test: if b**m mod n = -1 or 1, pass, or...
    if bignum%n ==1 or bignum%n == n-1:
       result = 1
    else: # if b**(m*(2**k)) mod n = -1 for some 1<k<r, pass
       for k in range(1,r+1):
          expo = 2L**k
          if (bignum**expo)%n==n-1:
              result = 1
              break
    if result:  print "Passed for base %s" % b
    else: print "Failed for base %s" % b
    return result


Usage:

 >>> rsa.ppt(399173L)
 (n-1,r,m) = (399172,2,99793)
 Testing base 2
 Passed for base 2
 Testing base 3
 Passed for base 3
 Testing base 5
 Passed for base 5
 Testing base 7
 Passed for base 7
 Testing base 11
 Passed for base 11
 Testing base 13
 Passed for base 13
 0.999755859375 chance of being prime
 Elapsed time: 89.9671910357 seconds

Kirby

Related reading:

On using big numbers to open new horizons in K-12
http://www.mathforum.org/epigone/math-teach/zhahcrafah

Cryptography w/ Python (a.k.a. Clubhouse Crypto)
http://www.inetarena.com/~pdx4d/ocn/clubhouse.html