1 #include "os.h" 2 #include <mp.h> 3 #include <libsec.h> 4 5 /* Miller-Rabin probabilistic primality testing */ 6 /* Knuth (1981) Seminumerical Algorithms, p.379 */ 7 /* Menezes et al () Handbook, p.39 */ 8 /* 0 if composite; 1 if almost surely prime, Pr(err)<1/4**nrep */ 9 int 10 probably_prime(mpint *n, int nrep) 11 { 12 int j, k, rep, nbits, isprime; 13 mpint *nm1, *q, *x, *y, *r; 14 15 if(n->sign < 0) 16 sysfatal("negative prime candidate"); 17 18 if(nrep <= 0) 19 nrep = 18; 20 21 k = mptoi(n); 22 if(k == 2) /* 2 is prime */ 23 return 1; 24 if(k < 2) /* 1 is not prime */ 25 return 0; 26 if((n->p[0] & 1) == 0) /* even is not prime */ 27 return 0; 28 29 /* test against small prime numbers */ 30 if(smallprimetest(n) < 0) 31 return 0; 32 33 /* fermat test, 2^n mod n == 2 if p is prime */ 34 x = uitomp(2, nil); 35 y = mpnew(0); 36 mpexp(x, n, n, y); 37 k = mptoi(y); 38 if(k != 2){ 39 mpfree(x); 40 mpfree(y); 41 return 0; 42 } 43 44 nbits = mpsignif(n); 45 nm1 = mpnew(nbits); 46 mpsub(n, mpone, nm1); /* nm1 = n - 1 */ 47 k = mplowbits0(nm1); 48 q = mpnew(0); 49 mpright(nm1, k, q); /* q = (n-1)/2**k */ 50 51 for(rep = 0; rep < nrep; rep++){ 52 for(;;){ 53 /* find x = random in [2, n-2] */ 54 r = mprand(nbits, prng, nil); 55 mpmod(r, nm1, x); 56 mpfree(r); 57 if(mpcmp(x, mpone) > 0) 58 break; 59 } 60 61 /* y = x**q mod n */ 62 mpexp(x, q, n, y); 63 64 if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0) 65 continue; 66 67 for(j = 1;; j++){ 68 if(j >= k) { 69 isprime = 0; 70 goto done; 71 } 72 mpmul(y, y, x); 73 mpmod(x, n, y); /* y = y*y mod n */ 74 if(mpcmp(y, nm1) == 0) 75 break; 76 if(mpcmp(y, mpone) == 0){ 77 isprime = 0; 78 goto done; 79 } 80 } 81 } 82 isprime = 1; 83 done: 84 mpfree(y); 85 mpfree(x); 86 mpfree(q); 87 mpfree(nm1); 88 return isprime; 89 } 90