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.
		
		
		
		
			
				
					106 lines
				
				2.2 KiB
			
		
		
			
		
	
	
					106 lines
				
				2.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								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;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 |