106 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			106 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var randomBytes = require('randombytes');
 | 
						|
module.exports = findPrime;
 | 
						|
findPrime.simpleSieve = simpleSieve;
 | 
						|
findPrime.fermatTest = fermatTest;
 | 
						|
var BN = require('bn.js');
 | 
						|
var TWENTYFOUR = new BN(24);
 | 
						|
var MillerRabin = require('miller-rabin');
 | 
						|
var millerRabin = new MillerRabin();
 | 
						|
var ONE = new BN(1);
 | 
						|
var TWO = new BN(2);
 | 
						|
var FIVE = new BN(5);
 | 
						|
var SIXTEEN = new BN(16);
 | 
						|
var EIGHT = new BN(8);
 | 
						|
var TEN = new BN(10);
 | 
						|
var THREE = new BN(3);
 | 
						|
var SEVEN = new BN(7);
 | 
						|
var ELEVEN = new BN(11);
 | 
						|
var FOUR = new BN(4);
 | 
						|
var TWELVE = new BN(12);
 | 
						|
var primes = null;
 | 
						|
 | 
						|
function _getPrimes() {
 | 
						|
  if (primes !== null)
 | 
						|
    return primes;
 | 
						|
 | 
						|
  var limit = 0x100000;
 | 
						|
  var res = [];
 | 
						|
  res[0] = 2;
 | 
						|
  for (var i = 1, k = 3; k < limit; k += 2) {
 | 
						|
    var sqrt = Math.ceil(Math.sqrt(k));
 | 
						|
    for (var j = 0; j < i && res[j] <= sqrt; j++)
 | 
						|
      if (k % res[j] === 0)
 | 
						|
        break;
 | 
						|
 | 
						|
    if (i !== j && res[j] <= sqrt)
 | 
						|
      continue;
 | 
						|
 | 
						|
    res[i++] = k;
 | 
						|
  }
 | 
						|
  primes = res;
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
function simpleSieve(p) {
 | 
						|
  var primes = _getPrimes();
 | 
						|
 | 
						|
  for (var i = 0; i < primes.length; i++)
 | 
						|
    if (p.modn(primes[i]) === 0) {
 | 
						|
      if (p.cmpn(primes[i]) === 0) {
 | 
						|
        return true;
 | 
						|
      } else {
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
function fermatTest(p) {
 | 
						|
  var red = BN.mont(p);
 | 
						|
  return TWO.toRed(red).redPow(p.subn(1)).fromRed().cmpn(1) === 0;
 | 
						|
}
 | 
						|
 | 
						|
function findPrime(bits, gen) {
 | 
						|
  if (bits < 16) {
 | 
						|
    // this is what openssl does
 | 
						|
    if (gen === 2 || gen === 5) {
 | 
						|
      return new BN([0x8c, 0x7b]);
 | 
						|
    } else {
 | 
						|
      return new BN([0x8c, 0x27]);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  gen = new BN(gen);
 | 
						|
 | 
						|
  var num, n2;
 | 
						|
 | 
						|
  while (true) {
 | 
						|
    num = new BN(randomBytes(Math.ceil(bits / 8)));
 | 
						|
    while (num.bitLength() > bits) {
 | 
						|
      num.ishrn(1);
 | 
						|
    }
 | 
						|
    if (num.isEven()) {
 | 
						|
      num.iadd(ONE);
 | 
						|
    }
 | 
						|
    if (!num.testn(1)) {
 | 
						|
      num.iadd(TWO);
 | 
						|
    }
 | 
						|
    if (!gen.cmp(TWO)) {
 | 
						|
      while (num.mod(TWENTYFOUR).cmp(ELEVEN)) {
 | 
						|
        num.iadd(FOUR);
 | 
						|
      }
 | 
						|
    } else if (!gen.cmp(FIVE)) {
 | 
						|
      while (num.mod(TEN).cmp(THREE)) {
 | 
						|
        num.iadd(FOUR);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    n2 = num.shrn(1);
 | 
						|
    if (simpleSieve(n2) && simpleSieve(num) &&
 | 
						|
      fermatTest(n2) && fermatTest(num) &&
 | 
						|
      millerRabin.test(n2) && millerRabin.test(num)) {
 | 
						|
      return num;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
}
 |