1
0

probably_prime.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. */
  10. int
  11. probably_prime(mpint *n, int nrep)
  12. {
  13. int j, k, rep, nbits, isprime;
  14. mpint *nm1, *q, *x, *y, *r;
  15. if(n->sign < 0)
  16. sysfatal("negative prime candidate");
  17. if(nrep <= 0)
  18. nrep = 18;
  19. k = mptoi(n);
  20. if(k == 2) /* 2 is prime */
  21. return 1;
  22. if(k < 2) /* 1 is not prime */
  23. return 0;
  24. if((n->p[0] & 1) == 0) /* even is not prime */
  25. return 0;
  26. /* test against small prime numbers */
  27. if(smallprimetest(n) < 0)
  28. return 0;
  29. /* fermat test, 2^n mod n == 2 if p is prime */
  30. x = uitomp(2, nil);
  31. y = mpnew(0);
  32. mpexp(x, n, n, y);
  33. k = mptoi(y);
  34. if(k != 2){
  35. mpfree(x);
  36. mpfree(y);
  37. return 0;
  38. }
  39. nbits = mpsignif(n);
  40. nm1 = mpnew(nbits);
  41. mpsub(n, mpone, nm1); /* nm1 = n - 1 */
  42. k = mplowbits0(nm1);
  43. q = mpnew(0);
  44. mpright(nm1, k, q); /* q = (n-1)/2**k */
  45. for(rep = 0; rep < nrep; rep++){
  46. for(;;){
  47. /* find x = random in [2, n-2] */
  48. r = mprand(nbits, prng, nil);
  49. mpmod(r, nm1, x);
  50. mpfree(r);
  51. if(mpcmp(x, mpone) > 0)
  52. break;
  53. }
  54. /* y = x**q mod n */
  55. mpexp(x, q, n, y);
  56. if(mpcmp(y, mpone) == 0 || mpcmp(y, nm1) == 0)
  57. continue;
  58. for(j = 1;; j++){
  59. if(j >= k) {
  60. isprime = 0;
  61. goto done;
  62. }
  63. mpmul(y, y, x);
  64. mpmod(x, n, y); /* y = y*y mod n */
  65. if(mpcmp(y, nm1) == 0)
  66. break;
  67. if(mpcmp(y, mpone) == 0){
  68. isprime = 0;
  69. goto done;
  70. }
  71. }
  72. }
  73. isprime = 1;
  74. done:
  75. mpfree(y);
  76. mpfree(x);
  77. mpfree(q);
  78. mpfree(nm1);
  79. return isprime;
  80. }