You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							105 lines
						
					
					
						
							2.2 KiB
						
					
					
				
			
		
		
	
	
							105 lines
						
					
					
						
							2.2 KiB
						
					
					
				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; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
}
 | 
						|
 |