123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- var forge = require('./forge');
- require('./util');
- require('./jsbn');
- require('./random');
- (function() {
- if(forge.prime) {
- module.exports = forge.prime;
- return;
- }
- var prime = module.exports = forge.prime = forge.prime || {};
- var BigInteger = forge.jsbn.BigInteger;
- var GCD_30_DELTA = [6, 4, 2, 4, 2, 4, 6, 2];
- var THIRTY = new BigInteger(null);
- THIRTY.fromInt(30);
- var op_or = function(x, y) {return x|y;};
- prime.generateProbablePrime = function(bits, options, callback) {
- if(typeof options === 'function') {
- callback = options;
- options = {};
- }
- options = options || {};
-
- var algorithm = options.algorithm || 'PRIMEINC';
- if(typeof algorithm === 'string') {
- algorithm = {name: algorithm};
- }
- algorithm.options = algorithm.options || {};
-
- var prng = options.prng || forge.random;
- var rng = {
-
- nextBytes: function(x) {
- var b = prng.getBytesSync(x.length);
- for(var i = 0; i < x.length; ++i) {
- x[i] = b.charCodeAt(i);
- }
- }
- };
- if(algorithm.name === 'PRIMEINC') {
- return primeincFindPrime(bits, rng, algorithm.options, callback);
- }
- throw new Error('Invalid prime generation algorithm: ' + algorithm.name);
- };
- function primeincFindPrime(bits, rng, options, callback) {
- if('workers' in options) {
- return primeincFindPrimeWithWorkers(bits, rng, options, callback);
- }
- return primeincFindPrimeWithoutWorkers(bits, rng, options, callback);
- }
- function primeincFindPrimeWithoutWorkers(bits, rng, options, callback) {
-
- var num = generateRandom(bits, rng);
-
- var deltaIdx = 0;
-
- var mrTests = getMillerRabinTests(num.bitLength());
- if('millerRabinTests' in options) {
- mrTests = options.millerRabinTests;
- }
-
-
-
-
- var maxBlockTime = 10;
- if('maxBlockTime' in options) {
- maxBlockTime = options.maxBlockTime;
- }
- _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback);
- }
- function _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback) {
- var start = +new Date();
- do {
-
- if(num.bitLength() > bits) {
- num = generateRandom(bits, rng);
- }
-
- if(num.isProbablePrime(mrTests)) {
- return callback(null, num);
- }
-
- num.dAddOffset(GCD_30_DELTA[deltaIdx++ % 8], 0);
- } while(maxBlockTime < 0 || (+new Date() - start < maxBlockTime));
-
- forge.util.setImmediate(function() {
- _primeinc(num, bits, rng, deltaIdx, mrTests, maxBlockTime, callback);
- });
- }
- function primeincFindPrimeWithWorkers(bits, rng, options, callback) {
-
- if(typeof Worker === 'undefined') {
- return primeincFindPrimeWithoutWorkers(bits, rng, options, callback);
- }
-
- var num = generateRandom(bits, rng);
-
- var numWorkers = options.workers;
- var workLoad = options.workLoad || 100;
- var range = workLoad * 30 / 8;
- var workerScript = options.workerScript || 'forge/prime.worker.js';
- if(numWorkers === -1) {
- return forge.util.estimateCores(function(err, cores) {
- if(err) {
-
- cores = 2;
- }
- numWorkers = cores - 1;
- generate();
- });
- }
- generate();
- function generate() {
-
- numWorkers = Math.max(1, numWorkers);
-
-
-
-
- var workers = [];
- for(var i = 0; i < numWorkers; ++i) {
-
- workers[i] = new Worker(workerScript);
- }
- var running = numWorkers;
-
- for(var i = 0; i < numWorkers; ++i) {
- workers[i].addEventListener('message', workerMessage);
- }
-
- var found = false;
- function workerMessage(e) {
-
- if(found) {
- return;
- }
- --running;
- var data = e.data;
- if(data.found) {
-
- for(var i = 0; i < workers.length; ++i) {
- workers[i].terminate();
- }
- found = true;
- return callback(null, new BigInteger(data.prime, 16));
- }
-
- if(num.bitLength() > bits) {
- num = generateRandom(bits, rng);
- }
-
- var hex = num.toString(16);
-
- e.target.postMessage({
- hex: hex,
- workLoad: workLoad
- });
- num.dAddOffset(range, 0);
- }
- }
- }
- function generateRandom(bits, rng) {
- var num = new BigInteger(bits, rng);
-
- var bits1 = bits - 1;
- if(!num.testBit(bits1)) {
- num.bitwiseTo(BigInteger.ONE.shiftLeft(bits1), op_or, num);
- }
-
- num.dAddOffset(31 - num.mod(THIRTY).byteValue(), 0);
- return num;
- }
- function getMillerRabinTests(bits) {
- if(bits <= 100) return 27;
- if(bits <= 150) return 18;
- if(bits <= 200) return 15;
- if(bits <= 250) return 12;
- if(bits <= 300) return 9;
- if(bits <= 350) return 8;
- if(bits <= 400) return 7;
- if(bits <= 500) return 6;
- if(bits <= 600) return 5;
- if(bits <= 800) return 4;
- if(bits <= 1250) return 3;
- return 2;
- }
- })();
|