116 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var bn = require('bn.js');
 | 
						|
var brorand = require('brorand');
 | 
						|
 | 
						|
function MillerRabin(rand) {
 | 
						|
  this.rand = rand || new brorand.Rand();
 | 
						|
}
 | 
						|
module.exports = MillerRabin;
 | 
						|
 | 
						|
MillerRabin.create = function create(rand) {
 | 
						|
  return new MillerRabin(rand);
 | 
						|
};
 | 
						|
 | 
						|
MillerRabin.prototype._randbelow = function _randbelow(n) {
 | 
						|
  var len = n.bitLength();
 | 
						|
  var min_bytes = Math.ceil(len / 8);
 | 
						|
 | 
						|
  // Generage random bytes until a number less than n is found.
 | 
						|
  // This ensures that 0..n-1 have an equal probability of being selected.
 | 
						|
  do
 | 
						|
    var a = new bn(this.rand.generate(min_bytes));
 | 
						|
  while (a.cmp(n) >= 0);
 | 
						|
 | 
						|
  return a;
 | 
						|
};
 | 
						|
 | 
						|
MillerRabin.prototype._randrange = function _randrange(start, stop) {
 | 
						|
  // Generate a random number greater than or equal to start and less than stop.
 | 
						|
  var size = stop.sub(start);
 | 
						|
  return start.add(this._randbelow(size));
 | 
						|
};
 | 
						|
 | 
						|
MillerRabin.prototype.test = function test(n, k, cb) {
 | 
						|
  var len = n.bitLength();
 | 
						|
  var red = bn.mont(n);
 | 
						|
  var rone = new bn(1).toRed(red);
 | 
						|
 | 
						|
  if (!k)
 | 
						|
    k = Math.max(1, (len / 48) | 0);
 | 
						|
 | 
						|
  // Find d and s, (n - 1) = (2 ^ s) * d;
 | 
						|
  var n1 = n.subn(1);
 | 
						|
  for (var s = 0; !n1.testn(s); s++) {}
 | 
						|
  var d = n.shrn(s);
 | 
						|
 | 
						|
  var rn1 = n1.toRed(red);
 | 
						|
 | 
						|
  var prime = true;
 | 
						|
  for (; k > 0; k--) {
 | 
						|
    var a = this._randrange(new bn(2), n1);
 | 
						|
    if (cb)
 | 
						|
      cb(a);
 | 
						|
 | 
						|
    var x = a.toRed(red).redPow(d);
 | 
						|
    if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
 | 
						|
      continue;
 | 
						|
 | 
						|
    for (var i = 1; i < s; i++) {
 | 
						|
      x = x.redSqr();
 | 
						|
 | 
						|
      if (x.cmp(rone) === 0)
 | 
						|
        return false;
 | 
						|
      if (x.cmp(rn1) === 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (i === s)
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
 | 
						|
  return prime;
 | 
						|
};
 | 
						|
 | 
						|
MillerRabin.prototype.getDivisor = function getDivisor(n, k) {
 | 
						|
  var len = n.bitLength();
 | 
						|
  var red = bn.mont(n);
 | 
						|
  var rone = new bn(1).toRed(red);
 | 
						|
 | 
						|
  if (!k)
 | 
						|
    k = Math.max(1, (len / 48) | 0);
 | 
						|
 | 
						|
  // Find d and s, (n - 1) = (2 ^ s) * d;
 | 
						|
  var n1 = n.subn(1);
 | 
						|
  for (var s = 0; !n1.testn(s); s++) {}
 | 
						|
  var d = n.shrn(s);
 | 
						|
 | 
						|
  var rn1 = n1.toRed(red);
 | 
						|
 | 
						|
  for (; k > 0; k--) {
 | 
						|
    var a = this._randrange(new bn(2), n1);
 | 
						|
 | 
						|
    var g = n.gcd(a);
 | 
						|
    if (g.cmpn(1) !== 0)
 | 
						|
      return g;
 | 
						|
 | 
						|
    var x = a.toRed(red).redPow(d);
 | 
						|
    if (x.cmp(rone) === 0 || x.cmp(rn1) === 0)
 | 
						|
      continue;
 | 
						|
 | 
						|
    for (var i = 1; i < s; i++) {
 | 
						|
      x = x.redSqr();
 | 
						|
 | 
						|
      if (x.cmp(rone) === 0)
 | 
						|
        return x.fromRed().subn(1).gcd(n);
 | 
						|
      if (x.cmp(rn1) === 0)
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    if (i === s) {
 | 
						|
      x = x.redSqr();
 | 
						|
      return x.fromRed().subn(1).gcd(n);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return false;
 | 
						|
};
 |