2019-04-19 10:05:37 +00:00
var bigintCryptoUtils = ( function ( exports ) {
2019-04-19 07:42:28 +00:00
'use strict' ;
2019-04-29 11:23:15 +00:00
const _ZERO = BigInt ( 0 ) ;
const _ONE = BigInt ( 1 ) ;
const _TWO = BigInt ( 2 ) ;
2019-04-19 07:42:28 +00:00
/ * *
* Absolute value . abs ( a ) == a if a >= 0. abs ( a ) == - a if a < 0
*
* @ param { number | bigint } a
*
* @ returns { bigint } the absolute value of a
* /
2019-04-19 14:40:11 +00:00
function abs ( a ) {
2019-04-19 07:42:28 +00:00
a = BigInt ( a ) ;
2019-04-23 14:57:06 +00:00
return ( a >= _ZERO ) ? a : - a ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
2019-04-29 10:34:20 +00:00
/ * *
* Returns the bitlength of a number
*
2019-05-04 16:29:09 +00:00
* @ param { number | bigint } a
2019-04-29 10:34:20 +00:00
* @ returns { number } - the bit length
* /
function bitLength ( a ) {
2019-05-04 16:29:09 +00:00
a = BigInt ( a ) ;
2019-05-09 07:39:12 +00:00
if ( a === _ONE )
2019-05-04 16:08:30 +00:00
return 1 ;
2019-04-29 10:34:20 +00:00
let bits = 1 ;
do {
bits ++ ;
} while ( ( a >>= _ONE ) > _ONE ) ;
return bits ;
}
2019-04-19 10:05:37 +00:00
/ * *
* @ typedef { Object } egcdReturn A triple ( g , x , y ) , such that ax + by = g = gcd ( a , b ) .
* @ property { bigint } g
* @ property { bigint } x
* @ property { bigint } y
* /
/ * *
* An iterative implementation of the extended euclidean algorithm or extended greatest common divisor algorithm .
* Take positive integers a , b as input , and return a triple ( g , x , y ) , such that ax + by = g = gcd ( a , b ) .
*
* @ param { number | bigint } a
* @ param { number | bigint } b
*
2019-05-09 07:39:12 +00:00
* @ returns { egcdReturn } A triple ( g , x , y ) , such that ax + by = g = gcd ( a , b ) .
2019-04-19 10:05:37 +00:00
* /
2019-04-19 14:40:11 +00:00
function eGcd ( a , b ) {
2019-04-19 10:05:37 +00:00
a = BigInt ( a ) ;
b = BigInt ( b ) ;
2019-05-09 07:39:12 +00:00
if ( a <= _ZERO | b <= _ZERO )
return NaN ; // a and b MUST be positive
2019-04-23 14:57:06 +00:00
let x = _ZERO ;
let y = _ONE ;
let u = _ONE ;
let v = _ZERO ;
2019-04-19 10:05:37 +00:00
2019-04-23 14:57:06 +00:00
while ( a !== _ZERO ) {
2019-04-19 10:05:37 +00:00
let q = b / a ;
let r = b % a ;
let m = x - ( u * q ) ;
let n = y - ( v * q ) ;
b = a ;
a = r ;
x = u ;
y = v ;
u = m ;
v = n ;
}
return {
b : b ,
x : x ,
y : y
} ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 10:05:37 +00:00
2019-04-19 07:42:28 +00:00
/ * *
* Greatest - common divisor of two integers based on the iterative binary algorithm .
*
* @ param { number | bigint } a
* @ param { number | bigint } b
*
* @ returns { bigint } The greatest common divisor of a and b
* /
2019-04-19 14:40:11 +00:00
function gcd ( a , b ) {
2019-04-19 07:42:28 +00:00
a = abs ( a ) ;
b = abs ( b ) ;
2019-05-09 07:39:12 +00:00
if ( a === _ZERO )
return b ;
else if ( b === _ZERO )
return a ;
2019-04-23 14:57:06 +00:00
let shift = _ZERO ;
while ( ! ( ( a | b ) & _ONE ) ) {
a >>= _ONE ;
b >>= _ONE ;
2019-04-19 07:42:28 +00:00
shift ++ ;
}
2019-04-23 14:57:06 +00:00
while ( ! ( a & _ONE ) ) a >>= _ONE ;
2019-04-19 07:42:28 +00:00
do {
2019-04-23 14:57:06 +00:00
while ( ! ( b & _ONE ) ) b >>= _ONE ;
2019-04-19 07:42:28 +00:00
if ( a > b ) {
let x = a ;
a = b ;
b = x ;
}
b -= a ;
} while ( b ) ;
// rescale
return a << shift ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
/ * *
2019-04-20 20:11:44 +00:00
* The test first tries if any of the first 250 small primes are a factor of the input number and then passes several
* iterations of Miller - Rabin Probabilistic Primality Test ( FIPS 186 - 4 C . 3.1 )
2019-04-19 07:42:28 +00:00
*
2019-05-04 16:29:09 +00:00
* @ param { number | bigint } w An integer to be tested for primality
2019-04-19 10:05:37 +00:00
* @ param { number } iterations The number of iterations for the primality test . The value shall be consistent with Table C . 1 , C . 2 or C . 3
2019-04-19 07:42:28 +00:00
*
2019-04-23 13:22:48 +00:00
* @ return { Promise } A promise that resolves to a boolean that is either true ( a probably prime number ) or false ( definitely composite )
2019-04-19 07:42:28 +00:00
* /
2019-04-19 14:40:11 +00:00
async function isProbablyPrime ( w , iterations = 16 ) {
2019-05-04 16:29:09 +00:00
if ( typeof w === 'number' ) {
w = BigInt ( w ) ;
}
2019-04-20 20:11:44 +00:00
{ // browser
return new Promise ( ( resolve , reject ) => {
2019-05-29 15:44:18 +00:00
const worker = new Worker ( _isProbablyPrimeWorkerUrl ( ) ) ;
2019-04-19 10:05:37 +00:00
worker . onmessage = ( event ) => {
worker . terminate ( ) ;
resolve ( event . data . isPrime ) ;
} ;
2019-04-20 20:11:44 +00:00
worker . onmessageerror = ( event ) => {
reject ( event ) ;
} ;
2019-04-19 10:05:37 +00:00
worker . postMessage ( {
'rnd' : w ,
2019-04-20 20:11:44 +00:00
'iterations' : iterations ,
'id' : 0
2019-04-19 10:05:37 +00:00
} ) ;
} ) ;
}
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
/ * *
2019-04-19 10:05:37 +00:00
* The least common multiple computed as abs ( a * b ) / gcd ( a , b )
2019-04-19 07:42:28 +00:00
* @ param { number | bigint } a
* @ param { number | bigint } b
*
2019-04-19 10:05:37 +00:00
* @ returns { bigint } The least common multiple of a and b
2019-04-19 07:42:28 +00:00
* /
2019-04-19 14:40:11 +00:00
function lcm ( a , b ) {
2019-04-19 07:42:28 +00:00
a = BigInt ( a ) ;
b = BigInt ( b ) ;
2019-05-09 07:39:12 +00:00
if ( a === _ZERO && b === _ZERO )
return _ZERO ;
2019-04-19 10:05:37 +00:00
return abs ( a * b ) / gcd ( a , b ) ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
2019-07-20 08:45:02 +00:00
/ * *
* Maximum . max ( a , b ) == a if a >= b . max ( a , b ) == b if a <= b
*
* @ param { number | bigint } a
* @ param { number | bigint } b
*
* @ returns { bigint } maximum of numbers a and b
* /
function max ( a , b ) {
a = BigInt ( a ) ;
b = BigInt ( b ) ;
return ( a >= b ) ? a : b ;
}
/ * *
* Minimum . min ( a , b ) == b if a >= b . min ( a , b ) == a if a <= b
*
* @ param { number | bigint } a
* @ param { number | bigint } b
*
* @ returns { bigint } minimum of numbers a and b
* /
function min ( a , b ) {
a = BigInt ( a ) ;
b = BigInt ( b ) ;
return ( a >= b ) ? b : a ;
}
2019-04-19 07:42:28 +00:00
/ * *
* Modular inverse .
*
* @ param { number | bigint } a The number to find an inverse for
* @ param { number | bigint } n The modulo
*
2019-05-09 07:39:12 +00:00
* @ returns { bigint } the inverse modulo n or NaN if it does not exist
2019-04-19 07:42:28 +00:00
* /
2019-04-19 14:40:11 +00:00
function modInv ( a , n ) {
2019-05-09 07:39:12 +00:00
if ( a == _ZERO | n <= _ZERO )
return NaN ;
let egcd = eGcd ( toZn ( a , n ) , n ) ;
2019-04-23 14:57:06 +00:00
if ( egcd . b !== _ONE ) {
2019-05-09 07:39:12 +00:00
return NaN ; // modular inverse does not exist
2019-04-19 07:42:28 +00:00
} else {
return toZn ( egcd . x , n ) ;
}
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
/ * *
2019-05-29 15:45:36 +00:00
* Modular exponentiation b * * e mod n . Currently using the right - to - left binary method
*
2019-05-29 15:44:18 +00:00
* @ param { number | bigint } b base
* @ param { number | bigint } e exponent
2019-04-19 07:42:28 +00:00
* @ param { number | bigint } n modulo
*
2019-05-29 15:44:18 +00:00
* @ returns { bigint } b * * e mod n
2019-04-19 07:42:28 +00:00
* /
2019-05-29 15:44:18 +00:00
function modPow ( b , e , n ) {
2019-04-19 07:42:28 +00:00
n = BigInt ( n ) ;
2019-05-09 07:39:12 +00:00
if ( n === _ZERO )
return NaN ;
2019-05-29 15:44:18 +00:00
else if ( n === _ONE )
return _ZERO ;
2019-05-09 07:39:12 +00:00
2019-05-29 15:44:18 +00:00
b = toZn ( b , n ) ;
e = BigInt ( e ) ;
if ( e < _ZERO ) {
return modInv ( modPow ( b , abs ( e ) , n ) , n ) ;
2019-04-19 07:42:28 +00:00
}
2019-05-29 15:44:18 +00:00
let r = _ONE ;
while ( e > 0 ) {
if ( ( e % _TWO ) === _ONE ) {
r = ( r * b ) % n ;
2019-04-19 07:42:28 +00:00
}
2019-05-29 15:44:18 +00:00
e = e / _TWO ;
2019-07-20 08:45:02 +00:00
b = b * * _TWO % n ;
2019-04-19 07:42:28 +00:00
}
2019-05-29 15:44:18 +00:00
return r ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
/ * *
2019-04-19 10:05:37 +00:00
* A probably - prime ( Miller - Rabin ) , cryptographically - secure , random - number generator .
* The browser version uses web workers to parallelise prime look up . Therefore , it does not lock the UI
* main process , and it can be much faster ( if several cores or cpu are available ) .
2019-04-20 20:21:41 +00:00
* The node version can also use worker _threads if they are available ( enabled by default with Node 11 and
2019-04-21 07:39:28 +00:00
* and can be enabled at runtime executing node -- experimental - worker with node >= 10.5 . 0 ) .
2019-04-19 07:42:28 +00:00
*
2019-04-19 10:05:37 +00:00
* @ param { number } bitLength The required bit length for the generated prime
2019-12-09 12:14:47 +00:00
* @ param { number } [ iterations = 16 ] The number of iterations for the Miller - Rabin Probabilistic Primality Test
2019-10-09 12:17:03 +00:00
* @ param { boolean } sync NOT RECOMMENDED . Invoke the function synchronously . It won 't use workers so it' ll be slower and may freeze thw window in browser ' s javascript .
2019-04-19 07:42:28 +00:00
*
2019-10-09 12:56:11 +00:00
* @ returns { Promise } A promise that resolves to a bigint probable prime of bitLength bits .
2019-04-19 07:42:28 +00:00
* /
2019-10-09 12:56:11 +00:00
function prime ( bitLength , iterations = 16 ) {
2019-05-09 07:39:12 +00:00
if ( bitLength < 1 )
throw new RangeError ( ` bitLength MUST be > 0 and it is ${ bitLength } ` ) ;
2019-04-20 20:11:44 +00:00
return new Promise ( ( resolve ) => {
let workerList = [ ] ;
const _onmessage = ( msg , newWorker ) => {
if ( msg . isPrime ) {
// if a prime number has been found, stop all the workers, and return it
for ( let j = 0 ; j < workerList . length ; j ++ ) {
workerList [ j ] . terminate ( ) ;
}
while ( workerList . length ) {
workerList . pop ( ) ;
}
resolve ( msg . value ) ;
} else { // if a composite is found, make the worker test another random number
2019-04-26 13:03:53 +00:00
let buf = randBits ( bitLength , true ) ;
let rnd = fromBuffer ( buf ) ;
try {
newWorker . postMessage ( {
'rnd' : rnd ,
'iterations' : iterations ,
'id' : msg . id
} ) ;
} catch ( error ) {
// The worker has already terminated. There is nothing to handle here
}
2019-04-20 20:11:44 +00:00
}
} ;
{ //browser
2019-04-26 13:03:53 +00:00
let workerURL = _isProbablyPrimeWorkerUrl ( ) ;
2019-04-20 20:11:44 +00:00
for ( let i = 0 ; i < self . navigator . hardwareConcurrency ; i ++ ) {
let newWorker = new Worker ( workerURL ) ;
newWorker . onmessage = ( event ) => _onmessage ( event . data , newWorker ) ;
2019-04-19 10:05:37 +00:00
workerList . push ( newWorker ) ;
}
2019-04-20 20:11:44 +00:00
}
for ( let i = 0 ; i < workerList . length ; i ++ ) {
2019-04-26 13:03:53 +00:00
let buf = randBits ( bitLength , true ) ;
let rnd = fromBuffer ( buf ) ;
workerList [ i ] . postMessage ( {
'rnd' : rnd ,
'iterations' : iterations ,
'id' : i
2019-04-20 20:11:44 +00:00
} ) ;
2019-04-19 07:42:28 +00:00
}
} ) ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
2019-10-09 12:56:11 +00:00
/ * *
* A probably - prime ( Miller - Rabin ) , cryptographically - secure , random - number generator .
* The sync version is NOT RECOMMENDED since it won 't use workers and thus it' ll be slower and may freeze thw window in browser ' s javascript . Please consider using prime ( ) instead .
*
* @ param { number } bitLength The required bit length for the generated prime
2019-12-09 12:14:47 +00:00
* @ param { number } [ iterations = 16 ] The number of iterations for the Miller - Rabin Probabilistic Primality Test
2019-10-09 12:56:11 +00:00
*
* @ returns { bigint } A bigint probable prime of bitLength bits .
* /
function primeSync ( bitLength , iterations = 16 ) {
if ( bitLength < 1 )
throw new RangeError ( ` bitLength MUST be > 0 and it is ${ bitLength } ` ) ;
let rnd = _ZERO ;
do {
rnd = fromBuffer ( randBytesSync ( bitLength / 8 , true ) ) ;
} while ( ! _isProbablyPrime ( rnd , iterations ) ) ;
return rnd ;
}
2019-04-19 07:42:28 +00:00
/ * *
* Returns a cryptographically secure random integer between [ min , max ]
* @ param { bigint } max Returned value will be <= max
2019-12-09 12:14:47 +00:00
* @ param { bigint } [ min = BigInt ( 1 ) ] Returned value will be >= min
2019-04-19 07:42:28 +00:00
*
2019-04-26 13:03:53 +00:00
* @ returns { bigint } A cryptographically secure random bigint between [ min , max ]
2019-04-19 07:42:28 +00:00
* /
2019-04-26 13:03:53 +00:00
function randBetween ( max , min = _ONE ) {
2019-04-20 20:11:44 +00:00
if ( max <= min ) throw new Error ( 'max must be > min' ) ;
const interval = max - min ;
let bitLen = bitLength ( interval ) ;
2019-04-19 07:42:28 +00:00
let rnd ;
do {
2019-04-26 13:03:53 +00:00
let buf = randBits ( bitLen ) ;
2019-04-19 07:42:28 +00:00
rnd = fromBuffer ( buf ) ;
2019-04-20 20:11:44 +00:00
} while ( rnd > interval ) ;
return rnd + min ;
}
/ * *
* Secure random bits for both node and browsers . Node version uses crypto . randomFill ( ) and browser one self . crypto . getRandomValues ( )
*
* @ param { number } bitLength The desired number of random bits
2019-12-09 12:14:47 +00:00
* @ param { boolean } [ forceLength = false ] If we want to force the output to have a specific bit length . It basically forces the msb to be 1
2019-04-20 20:11:44 +00:00
*
2019-04-29 10:29:23 +00:00
* @ returns { Buffer | Uint8Array } A Buffer / UInt8Array ( Node . js / Browser ) filled with cryptographically secure random bits
2019-04-20 20:11:44 +00:00
* /
2019-04-26 13:03:53 +00:00
function randBits ( bitLength , forceLength = false ) {
2019-05-09 07:39:12 +00:00
if ( bitLength < 1 )
throw new RangeError ( ` bitLength MUST be > 0 and it is ${ bitLength } ` ) ;
2019-04-20 20:11:44 +00:00
const byteLength = Math . ceil ( bitLength / 8 ) ;
2019-05-04 16:08:30 +00:00
let rndBytes = randBytesSync ( byteLength , false ) ;
2019-05-09 07:39:12 +00:00
// Fill with 0's the extra bits
2019-04-20 20:11:44 +00:00
rndBytes [ 0 ] = rndBytes [ 0 ] & ( 2 * * ( bitLength % 8 ) - 1 ) ;
if ( forceLength ) {
let mask = ( bitLength % 8 ) ? 2 * * ( ( bitLength % 8 ) - 1 ) : 128 ;
rndBytes [ 0 ] = rndBytes [ 0 ] | mask ;
}
return rndBytes ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 07:42:28 +00:00
/ * *
2019-04-19 10:05:37 +00:00
* Secure random bytes for both node and browsers . Node version uses crypto . randomFill ( ) and browser one self . crypto . getRandomValues ( )
2019-04-19 07:42:28 +00:00
*
2019-04-19 10:05:37 +00:00
* @ param { number } byteLength The desired number of random bytes
2019-12-09 12:14:47 +00:00
* @ param { boolean } [ forceLength = false ] If we want to force the output to have a bit length of 8 * byteLength . It basically forces the msb to be 1
2019-04-19 07:42:28 +00:00
*
2019-05-04 16:08:30 +00:00
* @ returns { Promise } A promise that resolves to a Buffer / UInt8Array ( Node . js / Browser ) filled with cryptographically secure random bytes
2019-04-19 07:42:28 +00:00
* /
2019-04-26 13:03:53 +00:00
function randBytes ( byteLength , forceLength = false ) {
2019-05-09 07:39:12 +00:00
if ( byteLength < 1 )
throw new RangeError ( ` byteLength MUST be > 0 and it is ${ byteLength } ` ) ;
2019-05-04 16:08:30 +00:00
let buf ;
{ // browser
return new Promise ( function ( resolve ) {
buf = new Uint8Array ( byteLength ) ;
self . crypto . getRandomValues ( buf ) ;
2019-05-27 14:42:46 +00:00
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if ( forceLength )
buf [ 0 ] = buf [ 0 ] | 128 ;
2019-05-04 16:08:30 +00:00
resolve ( buf ) ;
} ) ;
}
}
/ * *
* Secure random bytes for both node and browsers . Node version uses crypto . randomFill ( ) and browser one self . crypto . getRandomValues ( )
*
* @ param { number } byteLength The desired number of random bytes
2019-12-09 12:14:47 +00:00
* @ param { boolean } [ forceLength = false ] If we want to force the output to have a bit length of 8 * byteLength . It basically forces the msb to be 1
2019-05-04 16:08:30 +00:00
*
* @ returns { Buffer | Uint8Array } A Buffer / UInt8Array ( Node . js / Browser ) filled with cryptographically secure random bytes
* /
function randBytesSync ( byteLength , forceLength = false ) {
2019-05-09 07:39:12 +00:00
if ( byteLength < 1 )
throw new RangeError ( ` byteLength MUST be > 0 and it is ${ byteLength } ` ) ;
2019-04-26 13:03:53 +00:00
let buf ;
{ // browser
buf = new Uint8Array ( byteLength ) ;
self . crypto . getRandomValues ( buf ) ;
}
// If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
if ( forceLength )
buf [ 0 ] = buf [ 0 ] | 128 ;
return buf ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 10:05:37 +00:00
/ * *
* Finds the smallest positive element that is congruent to a in modulo n
* @ param { number | bigint } a An integer
* @ param { number | bigint } n The modulo
*
* @ returns { bigint } The smallest positive representation of a in modulo n
* /
2019-04-19 14:40:11 +00:00
function toZn ( a , n ) {
2019-04-19 10:05:37 +00:00
n = BigInt ( n ) ;
2019-05-09 07:39:12 +00:00
if ( n <= 0 )
return NaN ;
2019-04-19 10:05:37 +00:00
a = BigInt ( a ) % n ;
return ( a < 0 ) ? a + n : a ;
2019-04-19 14:40:11 +00:00
}
2019-04-19 10:05:37 +00:00
/* HELPER FUNCTIONS */
function fromBuffer ( buf ) {
2019-04-23 14:57:06 +00:00
let ret = _ZERO ;
2019-04-19 10:05:37 +00:00
for ( let i of buf . values ( ) ) {
let bi = BigInt ( i ) ;
ret = ( ret << BigInt ( 8 ) ) + bi ;
}
return ret ;
}
2019-04-26 13:03:53 +00:00
function _isProbablyPrimeWorkerUrl ( ) {
2019-04-20 20:11:44 +00:00
// Let's us first add all the required functions
2019-05-04 16:08:30 +00:00
let workerCode = ` 'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${ eGcd . toString ( ) } ;const modInv = ${ modInv . toString ( ) } ;const modPow = ${ modPow . toString ( ) } ;const toZn = ${ toZn . toString ( ) } ;const randBits = ${ randBits . toString ( ) } ;const randBytesSync = ${ randBytesSync . toString ( ) } ;const randBetween = ${ randBetween . toString ( ) } ;const isProbablyPrime = ${ _isProbablyPrime . toString ( ) } ; ${ bitLength . toString ( ) } ${ fromBuffer . toString ( ) } ` ;
2019-04-20 20:11:44 +00:00
2019-04-26 13:03:53 +00:00
const onmessage = async function ( event ) { // Let's start once we are called
2019-04-19 10:04:06 +00:00
// event.data = {rnd: <bigint>, iterations: <number>}
2019-04-19 10:05:37 +00:00
const isPrime = await isProbablyPrime ( event . data . rnd , event . data . iterations ) ;
2019-04-19 10:04:06 +00:00
postMessage ( {
'isPrime' : isPrime ,
2019-04-20 20:11:44 +00:00
'value' : event . data . rnd ,
'id' : event . data . id
2019-04-19 10:04:06 +00:00
} ) ;
2019-04-20 20:11:44 +00:00
} ;
2019-05-04 16:08:30 +00:00
2019-04-26 13:03:53 +00:00
workerCode += ` onmessage = ${ onmessage . toString ( ) } ; ` ;
2019-04-19 10:04:06 +00:00
2019-04-26 13:03:53 +00:00
return _workerUrl ( workerCode ) ;
}
2019-04-19 10:05:37 +00:00
2019-04-26 13:03:53 +00:00
function _workerUrl ( workerCode ) {
workerCode = ` (() => { ${ workerCode } })() ` ; // encapsulate IIFE
2019-05-29 15:44:18 +00:00
const _blob = new Blob ( [ workerCode ] , { type : 'text/javascript' } ) ;
2019-04-19 14:17:09 +00:00
return window . URL . createObjectURL ( _blob ) ;
2019-04-19 10:04:06 +00:00
}
2019-04-26 13:03:53 +00:00
function _isProbablyPrime ( w , iterations = 16 ) {
2019-04-19 07:42:28 +00:00
/ *
PREFILTERING . Even values but 2 are not primes , so don ' t test .
1 is not a prime and the M - R algorithm needs w > 1.
* /
2019-04-23 14:57:06 +00:00
if ( w === _TWO )
2019-04-19 07:42:28 +00:00
return true ;
2019-04-23 14:57:06 +00:00
else if ( ( w & _ONE ) === _ZERO || w === _ONE )
2019-04-19 07:42:28 +00:00
return false ;
/ *
Test if any of the first 250 small primes are a factor of w . 2 is not tested because it was already tested above .
* /
const firstPrimes = [
3 ,
5 ,
7 ,
11 ,
13 ,
17 ,
19 ,
23 ,
29 ,
31 ,
37 ,
41 ,
43 ,
47 ,
53 ,
59 ,
61 ,
67 ,
71 ,
73 ,
79 ,
83 ,
89 ,
97 ,
101 ,
103 ,
107 ,
109 ,
113 ,
127 ,
131 ,
137 ,
139 ,
149 ,
151 ,
157 ,
163 ,
167 ,
173 ,
179 ,
181 ,
191 ,
193 ,
197 ,
199 ,
211 ,
223 ,
227 ,
229 ,
233 ,
239 ,
241 ,
251 ,
257 ,
263 ,
269 ,
271 ,
277 ,
281 ,
283 ,
293 ,
307 ,
311 ,
313 ,
317 ,
331 ,
337 ,
347 ,
349 ,
353 ,
359 ,
367 ,
373 ,
379 ,
383 ,
389 ,
397 ,
401 ,
409 ,
419 ,
421 ,
431 ,
433 ,
439 ,
443 ,
449 ,
457 ,
461 ,
463 ,
467 ,
479 ,
487 ,
491 ,
499 ,
503 ,
509 ,
521 ,
523 ,
541 ,
547 ,
557 ,
563 ,
569 ,
571 ,
577 ,
587 ,
593 ,
599 ,
601 ,
607 ,
613 ,
617 ,
619 ,
631 ,
641 ,
643 ,
647 ,
653 ,
659 ,
661 ,
673 ,
677 ,
683 ,
691 ,
701 ,
709 ,
719 ,
727 ,
733 ,
739 ,
743 ,
751 ,
757 ,
761 ,
769 ,
773 ,
787 ,
797 ,
809 ,
811 ,
821 ,
823 ,
827 ,
829 ,
839 ,
853 ,
857 ,
859 ,
863 ,
877 ,
881 ,
883 ,
887 ,
907 ,
911 ,
919 ,
929 ,
937 ,
941 ,
947 ,
953 ,
967 ,
971 ,
977 ,
983 ,
991 ,
997 ,
1009 ,
1013 ,
1019 ,
1021 ,
1031 ,
1033 ,
1039 ,
1049 ,
1051 ,
1061 ,
1063 ,
1069 ,
1087 ,
1091 ,
1093 ,
1097 ,
1103 ,
1109 ,
1117 ,
1123 ,
1129 ,
1151 ,
1153 ,
1163 ,
1171 ,
1181 ,
1187 ,
1193 ,
1201 ,
1213 ,
1217 ,
1223 ,
1229 ,
1231 ,
1237 ,
1249 ,
1259 ,
1277 ,
1279 ,
1283 ,
1289 ,
1291 ,
1297 ,
1301 ,
1303 ,
1307 ,
1319 ,
1321 ,
1327 ,
1361 ,
1367 ,
1373 ,
1381 ,
1399 ,
1409 ,
1423 ,
1427 ,
1429 ,
1433 ,
1439 ,
1447 ,
1451 ,
1453 ,
1459 ,
1471 ,
1481 ,
1483 ,
1487 ,
1489 ,
1493 ,
1499 ,
1511 ,
1523 ,
1531 ,
1543 ,
1549 ,
1553 ,
1559 ,
1567 ,
1571 ,
1579 ,
1583 ,
1597 ,
] ;
for ( let i = 0 ; i < firstPrimes . length && ( BigInt ( firstPrimes [ i ] ) <= w ) ; i ++ ) {
const p = BigInt ( firstPrimes [ i ] ) ;
if ( w === p )
return true ;
2019-04-23 14:57:06 +00:00
else if ( w % p === _ZERO )
2019-04-19 07:42:28 +00:00
return false ;
}
/ *
2019-05-28 16:07:34 +00:00
1. Let a be the largest integer such that 2 * * a divides w − 1.
2. m = ( w − 1 ) / 2 * * a .
3. wlen = len ( w ) .
4. For i = 1 to iterations do
4.1 Obtain a string b of wlen bits from an RBG .
Comment : Ensure that 1 < b < w − 1.
4.2 If ( ( b ≤ 1 ) or ( b ≥ w − 1 ) ) , then go to step 4.1 .
4.3 z = b * * m mod w .
4.4 If ( ( z = 1 ) or ( z = w − 1 ) ) , then go to step 4.7 .
4.5 For j = 1 to a − 1 do .
4.5 . 1 z = z * * 2 mod w .
4.5 . 2 If ( z = w − 1 ) , then go to step 4.7 .
4.5 . 3 If ( z = 1 ) , then go to step 4.6 .
4.6 Return COMPOSITE .
4.7 Continue .
Comment : Increment i for the do - loop in step 4.
5. Return PROBABLY PRIME .
* /
2019-04-23 14:57:06 +00:00
let a = _ZERO , d = w - _ONE ;
while ( d % _TWO === _ZERO ) {
d /= _TWO ;
2019-04-19 07:42:28 +00:00
++ a ;
}
2019-04-23 14:57:06 +00:00
let m = ( w - _ONE ) / ( _TWO * * a ) ;
2019-04-19 07:42:28 +00:00
loop : do {
2019-04-26 13:03:53 +00:00
let b = randBetween ( w - _ONE , _TWO ) ;
2019-04-19 07:42:28 +00:00
let z = modPow ( b , m , w ) ;
2019-04-23 14:57:06 +00:00
if ( z === _ONE || z === w - _ONE )
2019-04-19 07:42:28 +00:00
continue ;
for ( let j = 1 ; j < a ; j ++ ) {
2019-04-23 14:57:06 +00:00
z = modPow ( z , _TWO , w ) ;
if ( z === w - _ONE )
2019-04-19 07:42:28 +00:00
continue loop ;
2019-04-23 14:57:06 +00:00
if ( z === _ONE )
2019-04-19 07:42:28 +00:00
break ;
}
return false ;
} while ( -- iterations ) ;
return true ;
2019-04-19 10:04:06 +00:00
}
2019-04-19 07:42:28 +00:00
exports . abs = abs ;
2019-04-29 10:34:20 +00:00
exports . bitLength = bitLength ;
2019-04-19 07:42:28 +00:00
exports . eGcd = eGcd ;
exports . gcd = gcd ;
exports . isProbablyPrime = isProbablyPrime ;
exports . lcm = lcm ;
2019-07-14 10:09:54 +00:00
exports . max = max ;
exports . min = min ;
2019-04-19 07:42:28 +00:00
exports . modInv = modInv ;
exports . modPow = modPow ;
exports . prime = prime ;
2019-10-09 12:56:11 +00:00
exports . primeSync = primeSync ;
2019-04-19 07:42:28 +00:00
exports . randBetween = randBetween ;
2019-04-20 20:11:44 +00:00
exports . randBits = randBits ;
2019-04-19 07:42:28 +00:00
exports . randBytes = randBytes ;
2019-05-04 16:08:30 +00:00
exports . randBytesSync = randBytesSync ;
2019-04-19 07:42:28 +00:00
exports . toZn = toZn ;
return exports ;
} ( { } ) ) ;