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;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| }
 |