mr.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. var bn = require('bn.js');
  2. var brorand = require('brorand');
  3. function MillerRabin(rand) {
  4. this.rand = rand || new brorand.Rand();
  5. }
  6. module.exports = MillerRabin;
  7. MillerRabin.create = function create(rand) {
  8. return new MillerRabin(rand);
  9. };
  10. MillerRabin.prototype._rand = function _rand(n) {
  11. var len = n.bitLength();
  12. var buf = this.rand.generate(Math.ceil(len / 8));
  13. // Set low bits
  14. buf[0] |= 3;
  15. // Mask high bits
  16. var mask = len & 0x7;
  17. if (mask !== 0)
  18. buf[buf.length - 1] >>= 7 - mask;
  19. return new bn(buf);
  20. }
  21. MillerRabin.prototype.test = function test(n, k, cb) {
  22. var len = n.bitLength();
  23. var red = bn.mont(n);
  24. var rone = new bn(1).toRed(red);
  25. if (!k)
  26. k = Math.max(1, (len / 48) | 0);
  27. // Find d and s, (n - 1) = (2 ^ s) * d;
  28. var n1 = n.subn(1);
  29. var n2 = n1.subn(1);
  30. for (var s = 0; !n1.testn(s); s++) {}
  31. var d = n.shrn(s);
  32. var rn1 = n1.toRed(red);
  33. var prime = true;
  34. for (; k > 0; k--) {
  35. var a = this._rand(n2);
  36. if (cb)
  37. cb(a);
  38. var x = a.toRed(red).redPow(d);
  39. if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
  40. continue;
  41. for (var i = 1; i < s; i++) {
  42. x = x.redSqr();
  43. if (x.cmp(rone) === 0)
  44. return false;
  45. if (x.cmp(rn1) === 0)
  46. break;
  47. }
  48. if (i === s)
  49. return false;
  50. }
  51. return prime;
  52. };
  53. MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
  54. var len = n.bitLength();
  55. var red = bn.mont(n);
  56. var rone = new bn(1).toRed(red);
  57. if (!k)
  58. k = Math.max(1, (len / 48) | 0);
  59. // Find d and s, (n - 1) = (2 ^ s) * d;
  60. var n1 = n.subn(1);
  61. var n2 = n1.subn(1);
  62. for (var s = 0; !n1.testn(s); s++) {}
  63. var d = n.shrn(s);
  64. var rn1 = n1.toRed(red);
  65. for (; k > 0; k--) {
  66. var a = this._rand(n2);
  67. var g = n.gcd(a);
  68. if (g.cmpn(1) !== 0)
  69. return g;
  70. var x = a.toRed(red).redPow(d);
  71. if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
  72. continue;
  73. for (var i = 1; i < s; i++) {
  74. x = x.redSqr();
  75. if (x.cmp(rone) === 0)
  76. return x.fromRed().subn(1).gcd(n);
  77. if (x.cmp(rn1) === 0)
  78. break;
  79. }
  80. if (i === s) {
  81. x = x.redSqr();
  82. return x.fromRed().subn(1).gcd(n);
  83. }
  84. }
  85. return false;
  86. };