|  | #include "os.h" | 
|  | #include <mp.h> | 
|  | #include <libsec.h> | 
|  |  | 
|  | /* Miller-Rabin probabilistic primality testing */ | 
|  | /*	Knuth (1981) Seminumerical Algorithms, p.379 */ | 
|  | /*	Menezes et al () Handbook, p.39 */ | 
|  | /* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep */ | 
|  | int | 
|  | probably_prime(mpint *n, int nrep) | 
|  | { | 
|  | int j, k, rep, nbits, isprime; | 
|  | mpint *nm1, *q, *x, *y, *r; | 
|  |  | 
|  | if(n->sign < 0) | 
|  | sysfatal("negative prime candidate"); | 
|  |  | 
|  | if(nrep <= 0) | 
|  | nrep = 18; | 
|  |  | 
|  | k = mptoi(n); | 
|  | if(k == 2)		/* 2 is prime */ | 
|  | return 1; | 
|  | if(k < 2)		/* 1 is not prime */ | 
|  | return 0; | 
|  | if((n->p[0] & 1) == 0)	/* even is not prime */ | 
|  | return 0; | 
|  |  | 
|  | /* test against small prime numbers */ | 
|  | if(smallprimetest(n) < 0) | 
|  | return 0; | 
|  |  | 
|  | /* fermat test, 2^n mod n == 2 if p is prime */ | 
|  | x = uitomp(2, nil); | 
|  | y = mpnew(0); | 
|  | mpexp(x, n, n, y); | 
|  | k = mptoi(y); | 
|  | if(k != 2){ | 
|  | mpfree(x); | 
|  | mpfree(y); | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | nbits = mpsignif(n); | 
|  | nm1 = mpnew(nbits); | 
|  | mpsub(n, mpone, nm1);	/* nm1 = n - 1 */ | 
|  | k = mplowbits0(nm1); | 
|  | q = mpnew(0); | 
|  | mpright(nm1, k, q);	/* q = (n-1)/2**k */ | 
|  |  | 
|  | for(rep = 0; rep < nrep; rep++){ | 
|  | for(;;){ | 
|  | /* find x = random in [2, n-2] */ | 
|  | r = mprand(nbits, prng, nil); | 
|  | mpmod(r, nm1, x); | 
|  | mpfree(r); | 
|  | if(mpcmp(x, mpone) > 0) | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* y = x**q mod n */ | 
|  | mpexp(x, q, n, y); | 
|  |  | 
|  | if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0) | 
|  | continue; | 
|  |  | 
|  | for(j = 1;; j++){ | 
|  | if(j >= k) { | 
|  | isprime = 0; | 
|  | goto done; | 
|  | } | 
|  | mpmul(y, y, x); | 
|  | mpmod(x, n, y);	/* y = y*y mod n */ | 
|  | if(mpcmp(y, nm1) == 0) | 
|  | break; | 
|  | if(mpcmp(y, mpone) == 0){ | 
|  | isprime = 0; | 
|  | goto done; | 
|  | } | 
|  | } | 
|  | } | 
|  | isprime = 1; | 
|  | done: | 
|  | mpfree(y); | 
|  | mpfree(x); | 
|  | mpfree(q); | 
|  | mpfree(nm1); | 
|  | return isprime; | 
|  | } |