better README

This commit is contained in:
Juan Hernández Serrano 2019-04-19 16:40:11 +02:00
parent 12a78d9495
commit de00327fd8
8 changed files with 128 additions and 132 deletions

View File

@ -2,9 +2,7 @@
Utils for working with cryptography using native JS (stage 3) implementation of BigInt. It includes some extra functions to work with modular arithmetics along with secure random numbers and a very fast strong probable prime generation/testing (parallelised multi-threaded Miller-Rabin primality test). It can be used with Node.js (>=10.4.0) and [Web Browsers supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility).
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html)**_
Many platforms provide native support for cryptography, such as [webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html)._
## Installation
bigint-crypto-utils is distributed for [web browsers supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) as an ES6 module or a IIFE file, and for Node.js (>=10.4.0) as a CJS module.
@ -15,7 +13,7 @@ npm install bigint-crypto-utils
```
NPM installation defaults to the ES6 module for browsers and the CJS for Node.js.
For web browsers, you can also directly download the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.mod.min.js) from GitHub.
For web browsers, you can also directly download the minimised version of the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.mod.min.js) from GitHub.
## Usage example

View File

@ -2,9 +2,7 @@
Utils for working with cryptography using native JS (stage 3) implementation of BigInt. It includes some extra functions to work with modular arithmetics along with secure random numbers and a very fast strong probable prime generation/testing (parallelised multi-threaded Miller-Rabin primality test). It can be used with Node.js (>=10.4.0) and [Web Browsers supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility).
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html)**_
Many platforms provide native support for cryptography, such as [webcrypto](https://w3c.github.io/webcrypto/Overview.html) or [node crypto](https://nodejs.org/dist/latest/docs/api/crypto.html).
_The operations supported on BigInts are not constant time. BigInt can be therefore **[unsuitable for use in cryptography](https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html).** Many platforms provide native support for cryptography, such as [Web Cryptography API](https://w3c.github.io/webcrypto/) or [Node.js Crypto](https://nodejs.org/dist/latest/docs/api/crypto.html)._
## Installation
bigint-crypto-utils is distributed for [web browsers supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) as an ES6 module or a IIFE file, and for Node.js (>=10.4.0) as a CJS module.
@ -15,7 +13,7 @@ npm install bigint-crypto-utils
```
NPM installation defaults to the ES6 module for browsers and the CJS for Node.js.
For web browsers, you can also directly download the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.mod.min.js) from GitHub.
For web browsers, you can also directly download the minimised version of the [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/dist/bigint-crypto-utils-latest.browser.mod.min.js) from GitHub.
## Usage example
@ -79,43 +77,43 @@ From a browser, you can just load the module in a html page as:
# bigint-crypto-utils JS Doc
## Constants
## Functions
<dl>
<dt><a href="#abs">abs</a><code>bigint</code></dt>
<dt><a href="#abs">abs(a)</a><code>bigint</code></dt>
<dd><p>Absolute value. abs(a)==a if a&gt;=0. abs(a)==-a if a&lt;0</p>
</dd>
<dt><a href="#eGcd">eGcd</a><code><a href="#egcdReturn">egcdReturn</a></code></dt>
<dt><a href="#eGcd">eGcd(a, b)</a><code><a href="#egcdReturn">egcdReturn</a></code></dt>
<dd><p>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).</p>
</dd>
<dt><a href="#gcd">gcd</a><code>bigint</code></dt>
<dt><a href="#gcd">gcd(a, b)</a><code>bigint</code></dt>
<dd><p>Greatest-common divisor of two integers based on the iterative binary algorithm.</p>
</dd>
<dt><a href="#isProbablyPrime">isProbablyPrime</a><code>Promise</code></dt>
<dt><a href="#isProbablyPrime">isProbablyPrime(w, iterations)</a><code>Promise</code></dt>
<dd><p>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)</p>
</dd>
<dt><a href="#lcm">lcm</a><code>bigint</code></dt>
<dt><a href="#lcm">lcm(a, b)</a><code>bigint</code></dt>
<dd><p>The least common multiple computed as abs(a*b)/gcd(a,b)</p>
</dd>
<dt><a href="#modInv">modInv</a><code>bigint</code></dt>
<dt><a href="#modInv">modInv(a, n)</a><code>bigint</code></dt>
<dd><p>Modular inverse.</p>
</dd>
<dt><a href="#modPow">modPow</a><code>bigint</code></dt>
<dt><a href="#modPow">modPow(a, b, n)</a><code>bigint</code></dt>
<dd><p>Modular exponentiation a**b mod n</p>
</dd>
<dt><a href="#prime">prime</a><code>Promise</code></dt>
<dt><a href="#prime">prime(bitLength, iterations)</a><code>Promise</code></dt>
<dd><p>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).</p>
</dd>
<dt><a href="#randBetween">randBetween</a><code>Promise</code></dt>
<dt><a href="#randBetween">randBetween(max, min)</a><code>Promise</code></dt>
<dd><p>Returns a cryptographically secure random integer between [min,max]</p>
</dd>
<dt><a href="#randBytes">randBytes</a><code>Promise</code></dt>
<dt><a href="#randBytes">randBytes(byteLength, forceLength)</a><code>Promise</code></dt>
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
</dd>
<dt><a href="#toZn">toZn</a><code>bigint</code></dt>
<dt><a href="#toZn">toZn(a, n)</a><code>bigint</code></dt>
<dd><p>Finds the smallest positive element that is congruent to a in modulo n</p>
</dd>
</dl>
@ -130,10 +128,10 @@ main process, and it can be much faster (if several cores or cpu are available).
<a name="abs"></a>
## abs ⇒ <code>bigint</code>
## abs(a)<code>bigint</code>
Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - the absolute value of a
| Param | Type |
@ -142,11 +140,11 @@ Absolute value. abs(a)==a if a>=0. abs(a)==-a if a<0
<a name="eGcd"></a>
## eGcd ⇒ [<code>egcdReturn</code>](#egcdReturn)
## eGcd(a, b) ⇒ [<code>egcdReturn</code>](#egcdReturn)
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).
**Kind**: global constant
**Kind**: global function
| Param | Type |
| --- | --- |
@ -155,10 +153,10 @@ Take positive integers a, b as input, and return a triple (g, x, y), such that a
<a name="gcd"></a>
## gcd ⇒ <code>bigint</code>
## gcd(a, b)<code>bigint</code>
Greatest-common divisor of two integers based on the iterative binary algorithm.
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - The greatest common divisor of a and b
| Param | Type |
@ -168,10 +166,10 @@ Greatest-common divisor of two integers based on the iterative binary algorithm.
<a name="isProbablyPrime"></a>
## isProbablyPrime ⇒ <code>Promise</code>
## isProbablyPrime(w, iterations)<code>Promise</code>
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)
**Kind**: global constant
**Kind**: global function
**Returns**: <code>Promise</code> - A promise that resolve to a boolean that is either true (a probably prime number) or false (definitely composite)
| Param | Type | Description |
@ -181,10 +179,10 @@ The test first tries if any of the first 250 small primes are a factor of the in
<a name="lcm"></a>
## lcm ⇒ <code>bigint</code>
## lcm(a, b)<code>bigint</code>
The least common multiple computed as abs(a*b)/gcd(a,b)
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - The least common multiple of a and b
| Param | Type |
@ -194,10 +192,10 @@ The least common multiple computed as abs(a*b)/gcd(a,b)
<a name="modInv"></a>
## modInv ⇒ <code>bigint</code>
## modInv(a, n)<code>bigint</code>
Modular inverse.
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - the inverse modulo n
| Param | Type | Description |
@ -207,10 +205,10 @@ Modular inverse.
<a name="modPow"></a>
## modPow ⇒ <code>bigint</code>
## modPow(a, b, n)<code>bigint</code>
Modular exponentiation a**b mod n
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - a**b mod n
| Param | Type | Description |
@ -221,12 +219,12 @@ Modular exponentiation a**b mod n
<a name="prime"></a>
## prime ⇒ <code>Promise</code>
## prime(bitLength, iterations)<code>Promise</code>
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).
**Kind**: global constant
**Kind**: global function
**Returns**: <code>Promise</code> - A promise that resolves to a bigint probable prime of bitLength bits
| Param | Type | Description |
@ -236,10 +234,10 @@ main process, and it can be much faster (if several cores or cpu are available).
<a name="randBetween"></a>
## randBetween ⇒ <code>Promise</code>
## randBetween(max, min)<code>Promise</code>
Returns a cryptographically secure random integer between [min,max]
**Kind**: global constant
**Kind**: global function
**Returns**: <code>Promise</code> - A promise that resolves to a cryptographically secure random bigint between [min,max]
| Param | Type | Description |
@ -249,10 +247,10 @@ Returns a cryptographically secure random integer between [min,max]
<a name="randBytes"></a>
## randBytes ⇒ <code>Promise</code>
## randBytes(byteLength, forceLength)<code>Promise</code>
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
**Kind**: global constant
**Kind**: global function
**Returns**: <code>Promise</code> - A promise that resolves to a Buffer/UInt8Array filled with cryptographically secure random bytes
| Param | Type | Description |
@ -262,10 +260,10 @@ Secure random bytes for both node and browsers. Node version uses crypto.randomF
<a name="toZn"></a>
## toZn ⇒ <code>bigint</code>
## toZn(a, n)<code>bigint</code>
Finds the smallest positive element that is congruent to a in modulo n
**Kind**: global constant
**Kind**: global function
**Returns**: <code>bigint</code> - The smallest positive representation of a in modulo n
| Param | Type | Description |

View File

@ -8,10 +8,10 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} the absolute value of a
*/
const abs = function (a) {
function abs(a) {
a = BigInt(a);
return (a >= BigInt(0)) ? a : -a;
};
}
/**
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -28,7 +28,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {egcdReturn}
*/
const eGcd = function (a, b) {
function eGcd(a, b) {
a = BigInt(a);
b = BigInt(b);
let x = BigInt(0);
@ -53,7 +53,7 @@ var bigintCryptoUtils = (function (exports) {
x: x,
y: y
};
};
}
/**
* Greatest-common divisor of two integers based on the iterative binary algorithm.
@ -63,7 +63,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} The greatest common divisor of a and b
*/
const gcd = function (a, b) {
function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = BigInt(0);
@ -85,7 +85,7 @@ var bigintCryptoUtils = (function (exports) {
// rescale
return a << shift;
};
}
/**
* 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)
@ -95,7 +95,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @return {Promise} A promise that resolve to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
const isProbablyPrime = async function (w, iterations = 16) {
async function isProbablyPrime(w, iterations = 16) {
{
return new Promise(resolve => {
let worker = new Worker(_isProbablyPrimeWorkerURL());
@ -111,7 +111,7 @@ var bigintCryptoUtils = (function (exports) {
});
});
}
};
}
/**
* The least common multiple computed as abs(a*b)/gcd(a,b)
@ -120,11 +120,11 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} The least common multiple of a and b
*/
const lcm = function (a, b) {
function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
};
}
/**
* Modular inverse.
@ -134,14 +134,14 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} the inverse modulo n
*/
const modInv = function (a, n) {
function modInv(a, n) {
let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) {
return null; // modular inverse does not exist
} else {
return toZn(egcd.x, n);
}
};
}
/**
* Modular exponentiation a**b mod n
@ -151,7 +151,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} a**b mod n
*/
const modPow = function (a, b, n) {
function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3.
n = BigInt(n);
a = toZn(a, n);
@ -172,7 +172,7 @@ var bigintCryptoUtils = (function (exports) {
x = x % n;
}
return result;
};
}
/**
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
@ -184,7 +184,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits
*/
const prime = async function (bitLength, iterations = 16) {
async function prime(bitLength, iterations = 16) {
return new Promise(async (resolve) => {
{
let workerList = [];
@ -224,7 +224,7 @@ var bigintCryptoUtils = (function (exports) {
}
});
};
}
/**
* Returns a cryptographically secure random integer between [min,max]
@ -233,7 +233,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/
const randBetween = async function (max, min = 1) {
async function randBetween(max, min = 1) {
let bitLen = bitLength(max);
let byteLength = bitLen >> 3;
let remaining = bitLen - (byteLength * 8);
@ -252,7 +252,7 @@ var bigintCryptoUtils = (function (exports) {
rnd = fromBuffer(buf);
} while (rnd > max || rnd < min);
return rnd;
};
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
@ -262,7 +262,7 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array filled with cryptographically secure random bytes
*/
const randBytes = async function (byteLength, forceLength = false) {
async function randBytes(byteLength, forceLength = false) {
return new Promise((resolve) => {
let buf;
@ -275,7 +275,7 @@ var bigintCryptoUtils = (function (exports) {
resolve(buf);
}
});
};
}
/**
* Finds the smallest positive element that is congruent to a in modulo n
@ -284,11 +284,11 @@ var bigintCryptoUtils = (function (exports) {
*
* @returns {bigint} The smallest positive representation of a in modulo n
*/
const toZn = function (a, n) {
function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
};
}

View File

@ -1 +1 @@
var bigintCryptoUtils=function(a){'use strict';function b(a){let b=BigInt(0);for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function c(b){let c=1;do c++;while((b>>=BigInt(1))>BigInt(1));return c}function d(){let a=`(() => {'use strict';const eGcd = ${g.toString()};const modInv = ${j.toString()};const modPow = ${k.toString()};const toZn = ${o.toString()};const randBytes = ${m.toString()};const randBetween = ${l.toString()};const isProbablyPrime = ${e.toString()};${c.toString()}${b.toString()}onmessage = ${async function(a){const b=await i(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd})}.toString()};})()`;var d=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(d)}async function e(c,b=16){if(c===BigInt(2))return!0;if((c&BigInt(1))===BigInt(0)||c===BigInt(1))return!1;const e=[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 a=0;a<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===BigInt(0))return!1}let f=BigInt(0),g=c-BigInt(1);for(;g%BigInt(2)===BigInt(0);)g/=BigInt(2),++f;let h=(c-BigInt(1))/BigInt(2)**f;loop:do{let a=await l(c-BigInt(1),2),b=k(a,h,c);if(b===BigInt(1)||b===c-BigInt(1))continue;for(let a=1;a<f;a++){if(b=k(b,BigInt(2),c),b===c-BigInt(1))continue loop;if(b===BigInt(1))break}return!1}while(--b);return!0}const f=function(b){return b=BigInt(b),b>=BigInt(0)?b:-b},g=function(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}},h=function(c,d){c=f(c),d=f(d);let e=BigInt(0);for(;!((c|d)&BigInt(1));)c>>=BigInt(1),d>>=BigInt(1),e++;for(;!(c&BigInt(1));)c>>=BigInt(1);do{for(;!(d&BigInt(1));)d>>=BigInt(1);if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e},i=async function(a,b=16){return new Promise(c=>{let e=new Worker(d());e.onmessage=a=>{e.terminate(),c(a.data.isPrime)},e.postMessage({rnd:a,iterations:b})})},j=function(b,a){let c=g(b,a);return c.b===BigInt(1)?o(c.x,a):null},k=function(c,d,e){if(e=BigInt(e),c=o(c,e),d=BigInt(d),d<BigInt(0))return j(k(c,f(d),e),e);let g=BigInt(1),h=c;for(;0<d;){var i=d%BigInt(2);d/=BigInt(2),i==BigInt(1)&&(g*=h,g%=e),h*=h,h%=e}return g},l=async function(a,d=1){let e,f=c(a),g=f>>3,h=f-8*g;0<h&&(g++,e=2**h-1);let i;do{let a=await m(g);0<h&&(a[0]&=e),i=b(a)}while(i>a||i<d);return i},m=async function(a,b=!1){return new Promise(c=>{let d;d=new Uint8Array(a),self.crypto.getRandomValues(d),b&&(d[0]|=128),c(d)})},o=function(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b};return a.abs=f,a.eGcd=g,a.gcd=h,a.isProbablyPrime=i,a.lcm=function(c,d){return c=BigInt(c),d=BigInt(d),f(c*d)/h(c,d)},a.modInv=j,a.modPow=k,a.prime=async function(a,c=16){return new Promise(async e=>{{let f=[],g=d();for(let d,h=0;h<self.navigator.hardwareConcurrency;h++)d=new Worker(g),d.onmessage=async g=>{if(g.data.isPrime){for(let a=0;a<f.length;a++)f[a].terminate();for(;f.length;)f.pop();e(g.data.value)}else{let e=BigInt(0);e=b((await m(a/8,!0))),d.postMessage({rnd:e,iterations:c})}},f.push(d);for(const d of f){let e=BigInt(0);e=b((await m(a/8,!0))),d.postMessage({rnd:e,iterations:c})}}})},a.randBetween=l,a.randBytes=m,a.toZn=o,a}({});
var bigintCryptoUtils=function(a){'use strict';function c(b){return b=BigInt(b),b>=BigInt(0)?b:-b}function d(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}}function e(d,e){d=c(d),e=c(e);let f=BigInt(0);for(;!((d|e)&BigInt(1));)d>>=BigInt(1),e>>=BigInt(1),f++;for(;!(d&BigInt(1));)d>>=BigInt(1);do{for(;!(e&BigInt(1));)e>>=BigInt(1);if(d>e){let a=d;d=e,e=a}e-=d}while(e);return d<<f}async function f(a,b=16){return new Promise(c=>{let d=new Worker(n());d.onmessage=a=>{d.terminate(),c(a.data.isPrime)},d.postMessage({rnd:a,iterations:b})})}function g(b,a){let c=d(b,a);return c.b===BigInt(1)?k(c.x,a):null}function h(d,e,f){if(f=BigInt(f),d=k(d,f),e=BigInt(e),e<BigInt(0))return g(h(d,c(e),f),f);let i=BigInt(1),j=d;for(;0<e;){var l=e%BigInt(2);e/=BigInt(2),l==BigInt(1)&&(i*=j,i%=f),j*=j,j%=f}return i}async function i(a,b=1){let c,d=m(a),e=d>>3,f=d-8*e;0<f&&(e++,c=2**f-1);let g;do{let a=await j(e);0<f&&(a[0]&=c),g=l(a)}while(g>a||g<b);return g}async function j(a,b=!1){return new Promise(c=>{let d;d=new Uint8Array(a),self.crypto.getRandomValues(d),b&&(d[0]|=128),c(d)})}function k(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}function l(a){let b=BigInt(0);for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function m(b){let c=1;do c++;while((b>>=BigInt(1))>BigInt(1));return c}function n(){let a=`(() => {'use strict';const eGcd = ${d.toString()};const modInv = ${g.toString()};const modPow = ${h.toString()};const toZn = ${k.toString()};const randBytes = ${j.toString()};const randBetween = ${i.toString()};const isProbablyPrime = ${o.toString()};${m.toString()}${l.toString()}onmessage = ${async function(a){const b=await f(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd})}.toString()};})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}async function o(c,b=16){if(c===BigInt(2))return!0;if((c&BigInt(1))===BigInt(0)||c===BigInt(1))return!1;const e=[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 a=0;a<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===BigInt(0))return!1}let f=BigInt(0),g=c-BigInt(1);for(;g%BigInt(2)===BigInt(0);)g/=BigInt(2),++f;let j=(c-BigInt(1))/BigInt(2)**f;loop:do{let a=await i(c-BigInt(1),2),b=h(a,j,c);if(b===BigInt(1)||b===c-BigInt(1))continue;for(let a=1;a<f;a++){if(b=h(b,BigInt(2),c),b===c-BigInt(1))continue loop;if(b===BigInt(1))break}return!1}while(--b);return!0}return a.abs=c,a.eGcd=d,a.gcd=e,a.isProbablyPrime=f,a.lcm=function(d,f){return d=BigInt(d),f=BigInt(f),c(d*f)/e(d,f)},a.modInv=g,a.modPow=h,a.prime=async function(a,b=16){return new Promise(async c=>{{let d=[],e=n();for(let f,g=0;g<self.navigator.hardwareConcurrency;g++)f=new Worker(e),f.onmessage=async e=>{if(e.data.isPrime){for(let a=0;a<d.length;a++)d[a].terminate();for(;d.length;)d.pop();c(e.data.value)}else{let c=BigInt(0);c=l((await j(a/8,!0))),f.postMessage({rnd:c,iterations:b})}},d.push(f);for(const c of d){let d=BigInt(0);d=l((await j(a/8,!0))),c.postMessage({rnd:d,iterations:b})}}})},a.randBetween=i,a.randBytes=j,a.toZn=k,a}({});

View File

@ -5,10 +5,10 @@
*
* @returns {bigint} the absolute value of a
*/
const abs = function (a) {
function abs(a) {
a = BigInt(a);
return (a >= BigInt(0)) ? a : -a;
};
}
/**
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -25,7 +25,7 @@ const abs = function (a) {
*
* @returns {egcdReturn}
*/
const eGcd = function (a, b) {
function eGcd(a, b) {
a = BigInt(a);
b = BigInt(b);
let x = BigInt(0);
@ -50,7 +50,7 @@ const eGcd = function (a, b) {
x: x,
y: y
};
};
}
/**
* Greatest-common divisor of two integers based on the iterative binary algorithm.
@ -60,7 +60,7 @@ const eGcd = function (a, b) {
*
* @returns {bigint} The greatest common divisor of a and b
*/
const gcd = function (a, b) {
function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = BigInt(0);
@ -82,7 +82,7 @@ const gcd = function (a, b) {
// rescale
return a << shift;
};
}
/**
* 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)
@ -92,7 +92,7 @@ const gcd = function (a, b) {
*
* @return {Promise} A promise that resolve to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
const isProbablyPrime = async function (w, iterations = 16) {
async function isProbablyPrime(w, iterations = 16) {
{
return new Promise(resolve => {
let worker = new Worker(_isProbablyPrimeWorkerURL());
@ -108,7 +108,7 @@ const isProbablyPrime = async function (w, iterations = 16) {
});
});
}
};
}
/**
* The least common multiple computed as abs(a*b)/gcd(a,b)
@ -117,11 +117,11 @@ const isProbablyPrime = async function (w, iterations = 16) {
*
* @returns {bigint} The least common multiple of a and b
*/
const lcm = function (a, b) {
function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
};
}
/**
* Modular inverse.
@ -131,14 +131,14 @@ const lcm = function (a, b) {
*
* @returns {bigint} the inverse modulo n
*/
const modInv = function (a, n) {
function modInv(a, n) {
let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) {
return null; // modular inverse does not exist
} else {
return toZn(egcd.x, n);
}
};
}
/**
* Modular exponentiation a**b mod n
@ -148,7 +148,7 @@ const modInv = function (a, n) {
*
* @returns {bigint} a**b mod n
*/
const modPow = function (a, b, n) {
function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3.
n = BigInt(n);
a = toZn(a, n);
@ -169,7 +169,7 @@ const modPow = function (a, b, n) {
x = x % n;
}
return result;
};
}
/**
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
@ -181,7 +181,7 @@ const modPow = function (a, b, n) {
*
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits
*/
const prime = async function (bitLength, iterations = 16) {
async function prime(bitLength, iterations = 16) {
return new Promise(async (resolve) => {
{
let workerList = [];
@ -221,7 +221,7 @@ const prime = async function (bitLength, iterations = 16) {
}
});
};
}
/**
* Returns a cryptographically secure random integer between [min,max]
@ -230,7 +230,7 @@ const prime = async function (bitLength, iterations = 16) {
*
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/
const randBetween = async function (max, min = 1) {
async function randBetween(max, min = 1) {
let bitLen = bitLength(max);
let byteLength = bitLen >> 3;
let remaining = bitLen - (byteLength * 8);
@ -249,7 +249,7 @@ const randBetween = async function (max, min = 1) {
rnd = fromBuffer(buf);
} while (rnd > max || rnd < min);
return rnd;
};
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
@ -259,7 +259,7 @@ const randBetween = async function (max, min = 1) {
*
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array filled with cryptographically secure random bytes
*/
const randBytes = async function (byteLength, forceLength = false) {
async function randBytes(byteLength, forceLength = false) {
return new Promise((resolve) => {
let buf;
@ -272,7 +272,7 @@ const randBytes = async function (byteLength, forceLength = false) {
resolve(buf);
}
});
};
}
/**
* Finds the smallest positive element that is congruent to a in modulo n
@ -281,11 +281,11 @@ const randBytes = async function (byteLength, forceLength = false) {
*
* @returns {bigint} The smallest positive representation of a in modulo n
*/
const toZn = function (a, n) {
function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
};
}

View File

@ -1 +1 @@
const abs=function(b){return b=BigInt(b),b>=BigInt(0)?b:-b},eGcd=function(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}},gcd=function(c,d){c=abs(c),d=abs(d);let e=BigInt(0);for(;!((c|d)&BigInt(1));)c>>=BigInt(1),d>>=BigInt(1),e++;for(;!(c&BigInt(1));)c>>=BigInt(1);do{for(;!(d&BigInt(1));)d>>=BigInt(1);if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e},isProbablyPrime=async function(a,b=16){return new Promise(c=>{let d=new Worker(_isProbablyPrimeWorkerURL());d.onmessage=a=>{d.terminate(),c(a.data.isPrime)},d.postMessage({rnd:a,iterations:b})})},lcm=function(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)},modInv=function(b,a){let c=eGcd(b,a);return c.b===BigInt(1)?toZn(c.x,a):null},modPow=function(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<BigInt(0))return modInv(modPow(c,abs(d),e),e);let f=BigInt(1),g=c;for(;0<d;){var h=d%BigInt(2);d/=BigInt(2),h==BigInt(1)&&(f*=g,f%=e),g*=g,g%=e}return f},prime=async function(a,b=16){return new Promise(async c=>{{let d=[],e=_isProbablyPrimeWorkerURL();for(let f,g=0;g<self.navigator.hardwareConcurrency;g++)f=new Worker(e),f.onmessage=async e=>{if(e.data.isPrime){for(let a=0;a<d.length;a++)d[a].terminate();for(;d.length;)d.pop();c(e.data.value)}else{let c=BigInt(0);c=fromBuffer((await randBytes(a/8,!0))),f.postMessage({rnd:c,iterations:b})}},d.push(f);for(const c of d){let d=BigInt(0);d=fromBuffer((await randBytes(a/8,!0))),c.postMessage({rnd:d,iterations:b})}}})},randBetween=async function(a,b=1){let c,d=bitLength(a),e=d>>3,f=d-8*e;0<f&&(e++,c=2**f-1);let g;do{let a=await randBytes(e);0<f&&(a[0]&=c),g=fromBuffer(a)}while(g>a||g<b);return g},randBytes=async function(a,b=!1){return new Promise(c=>{let d;d=new Uint8Array(a),self.crypto.getRandomValues(d),b&&(d[0]|=128),c(d)})},toZn=function(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b};function fromBuffer(a){let b=BigInt(0);for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function bitLength(b){let c=1;do c++;while((b>>=BigInt(1))>BigInt(1));return c}function _isProbablyPrimeWorkerURL(){let a=`(() => {'use strict';const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}onmessage = ${async function(a){const b=await isProbablyPrime(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd})}.toString()};})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}async function _isProbablyPrime(c,b=16){if(c===BigInt(2))return!0;if((c&BigInt(1))===BigInt(0)||c===BigInt(1))return!1;const e=[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 a=0;a<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===BigInt(0))return!1}let f=BigInt(0),g=c-BigInt(1);for(;g%BigInt(2)===BigInt(0);)g/=BigInt(2),++f;let h=(c-BigInt(1))/BigInt(2)**f;loop:do{let a=await randBetween(c-BigInt(1),2),b=modPow(a,h,c);if(b===BigInt(1)||b===c-BigInt(1))continue;for(let a=1;a<f;a++){if(b=modPow(b,BigInt(2),c),b===c-BigInt(1))continue loop;if(b===BigInt(1))break}return!1}while(--b);return!0}export{abs,eGcd,gcd,isProbablyPrime,lcm,modInv,modPow,prime,randBetween,randBytes,toZn};
function abs(b){return b=BigInt(b),b>=BigInt(0)?b:-b}function eGcd(c,d){c=BigInt(c),d=BigInt(d);let e=BigInt(0),f=BigInt(1),g=BigInt(1),h=BigInt(0);for(;c!==BigInt(0);){let a=d/c,b=d%c,i=e-g*a,j=f-h*a;d=c,c=b,e=g,f=h,g=i,h=j}return{b:d,x:e,y:f}}function gcd(c,d){c=abs(c),d=abs(d);let e=BigInt(0);for(;!((c|d)&BigInt(1));)c>>=BigInt(1),d>>=BigInt(1),e++;for(;!(c&BigInt(1));)c>>=BigInt(1);do{for(;!(d&BigInt(1));)d>>=BigInt(1);if(c>d){let a=c;c=d,d=a}d-=c}while(d);return c<<e}async function isProbablyPrime(a,b=16){return new Promise(c=>{let d=new Worker(_isProbablyPrimeWorkerURL());d.onmessage=a=>{d.terminate(),c(a.data.isPrime)},d.postMessage({rnd:a,iterations:b})})}function lcm(c,d){return c=BigInt(c),d=BigInt(d),abs(c*d)/gcd(c,d)}function modInv(b,a){let c=eGcd(b,a);return c.b===BigInt(1)?toZn(c.x,a):null}function modPow(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<BigInt(0))return modInv(modPow(c,abs(d),e),e);let f=BigInt(1),g=c;for(;0<d;){var h=d%BigInt(2);d/=BigInt(2),h==BigInt(1)&&(f*=g,f%=e),g*=g,g%=e}return f}async function prime(a,b=16){return new Promise(async c=>{{let d=[],e=_isProbablyPrimeWorkerURL();for(let f,g=0;g<self.navigator.hardwareConcurrency;g++)f=new Worker(e),f.onmessage=async e=>{if(e.data.isPrime){for(let a=0;a<d.length;a++)d[a].terminate();for(;d.length;)d.pop();c(e.data.value)}else{let c=BigInt(0);c=fromBuffer((await randBytes(a/8,!0))),f.postMessage({rnd:c,iterations:b})}},d.push(f);for(const c of d){let d=BigInt(0);d=fromBuffer((await randBytes(a/8,!0))),c.postMessage({rnd:d,iterations:b})}}})}async function randBetween(a,b=1){let c,d=bitLength(a),e=d>>3,f=d-8*e;0<f&&(e++,c=2**f-1);let g;do{let a=await randBytes(e);0<f&&(a[0]&=c),g=fromBuffer(a)}while(g>a||g<b);return g}async function randBytes(a,b=!1){return new Promise(c=>{let d;d=new Uint8Array(a),self.crypto.getRandomValues(d),b&&(d[0]|=128),c(d)})}function toZn(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}function fromBuffer(a){let b=BigInt(0);for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function bitLength(b){let c=1;do c++;while((b>>=BigInt(1))>BigInt(1));return c}function _isProbablyPrimeWorkerURL(){let a=`(() => {'use strict';const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}onmessage = ${async function(a){const b=await isProbablyPrime(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd})}.toString()};})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}async function _isProbablyPrime(c,b=16){if(c===BigInt(2))return!0;if((c&BigInt(1))===BigInt(0)||c===BigInt(1))return!1;const e=[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 a=0;a<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===BigInt(0))return!1}let f=BigInt(0),g=c-BigInt(1);for(;g%BigInt(2)===BigInt(0);)g/=BigInt(2),++f;let h=(c-BigInt(1))/BigInt(2)**f;loop:do{let a=await randBetween(c-BigInt(1),2),b=modPow(a,h,c);if(b===BigInt(1)||b===c-BigInt(1))continue;for(let a=1;a<f;a++){if(b=modPow(b,BigInt(2),c),b===c-BigInt(1))continue loop;if(b===BigInt(1))break}return!1}while(--b);return!0}export{abs,eGcd,gcd,isProbablyPrime,lcm,modInv,modPow,prime,randBetween,randBytes,toZn};

View File

@ -9,10 +9,10 @@ Object.defineProperty(exports, '__esModule', { value: true });
*
* @returns {bigint} the absolute value of a
*/
const abs = function (a) {
function abs(a) {
a = BigInt(a);
return (a >= BigInt(0)) ? a : -a;
};
}
/**
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -29,7 +29,7 @@ const abs = function (a) {
*
* @returns {egcdReturn}
*/
const eGcd = function (a, b) {
function eGcd(a, b) {
a = BigInt(a);
b = BigInt(b);
let x = BigInt(0);
@ -54,7 +54,7 @@ const eGcd = function (a, b) {
x: x,
y: y
};
};
}
/**
* Greatest-common divisor of two integers based on the iterative binary algorithm.
@ -64,7 +64,7 @@ const eGcd = function (a, b) {
*
* @returns {bigint} The greatest common divisor of a and b
*/
const gcd = function (a, b) {
function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = BigInt(0);
@ -86,7 +86,7 @@ const gcd = function (a, b) {
// rescale
return a << shift;
};
}
/**
* 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)
@ -96,11 +96,11 @@ const gcd = function (a, b) {
*
* @return {Promise} A promise that resolve to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
const isProbablyPrime = async function (w, iterations = 16) {
async function isProbablyPrime(w, iterations = 16) {
{
return _isProbablyPrime(w, iterations);
}
};
}
/**
* The least common multiple computed as abs(a*b)/gcd(a,b)
@ -109,11 +109,11 @@ const isProbablyPrime = async function (w, iterations = 16) {
*
* @returns {bigint} The least common multiple of a and b
*/
const lcm = function (a, b) {
function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
};
}
/**
* Modular inverse.
@ -123,14 +123,14 @@ const lcm = function (a, b) {
*
* @returns {bigint} the inverse modulo n
*/
const modInv = function (a, n) {
function modInv(a, n) {
let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) {
return null; // modular inverse does not exist
} else {
return toZn(egcd.x, n);
}
};
}
/**
* Modular exponentiation a**b mod n
@ -140,7 +140,7 @@ const modInv = function (a, n) {
*
* @returns {bigint} a**b mod n
*/
const modPow = function (a, b, n) {
function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3.
n = BigInt(n);
a = toZn(a, n);
@ -161,7 +161,7 @@ const modPow = function (a, b, n) {
x = x % n;
}
return result;
};
}
/**
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
@ -173,7 +173,7 @@ const modPow = function (a, b, n) {
*
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits
*/
const prime = async function (bitLength, iterations = 16) {
async function prime(bitLength, iterations = 16) {
return new Promise(async (resolve) => {
{
let rnd = BigInt(0);
@ -183,7 +183,7 @@ const prime = async function (bitLength, iterations = 16) {
resolve(rnd);
}
});
};
}
/**
* Returns a cryptographically secure random integer between [min,max]
@ -192,7 +192,7 @@ const prime = async function (bitLength, iterations = 16) {
*
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/
const randBetween = async function (max, min = 1) {
async function randBetween(max, min = 1) {
let bitLen = bitLength(max);
let byteLength = bitLen >> 3;
let remaining = bitLen - (byteLength * 8);
@ -211,7 +211,7 @@ const randBetween = async function (max, min = 1) {
rnd = fromBuffer(buf);
} while (rnd > max || rnd < min);
return rnd;
};
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
@ -221,7 +221,7 @@ const randBetween = async function (max, min = 1) {
*
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array filled with cryptographically secure random bytes
*/
const randBytes = async function (byteLength, forceLength = false) {
async function randBytes(byteLength, forceLength = false) {
return new Promise((resolve) => {
let buf;
@ -237,7 +237,7 @@ const randBytes = async function (byteLength, forceLength = false) {
});
}
});
};
}
/**
* Finds the smallest positive element that is congruent to a in modulo n
@ -246,11 +246,11 @@ const randBytes = async function (byteLength, forceLength = false) {
*
* @returns {bigint} The smallest positive representation of a in modulo n
*/
const toZn = function (a, n) {
function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
};
}

View File

@ -7,10 +7,10 @@
*
* @returns {bigint} the absolute value of a
*/
export const abs = function (a) {
export function abs(a) {
a = BigInt(a);
return (a >= BigInt(0)) ? a : -a;
};
}
/**
* @typedef {Object} egcdReturn A triple (g, x, y), such that ax + by = g = gcd(a, b).
@ -27,7 +27,7 @@ export const abs = function (a) {
*
* @returns {egcdReturn}
*/
export const eGcd = function (a, b) {
export function eGcd(a, b) {
a = BigInt(a);
b = BigInt(b);
let x = BigInt(0);
@ -52,7 +52,7 @@ export const eGcd = function (a, b) {
x: x,
y: y
};
};
}
/**
* Greatest-common divisor of two integers based on the iterative binary algorithm.
@ -62,7 +62,7 @@ export const eGcd = function (a, b) {
*
* @returns {bigint} The greatest common divisor of a and b
*/
export const gcd = function (a, b) {
export function gcd(a, b) {
a = abs(a);
b = abs(b);
let shift = BigInt(0);
@ -84,7 +84,7 @@ export const gcd = function (a, b) {
// rescale
return a << shift;
};
}
/**
* 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)
@ -94,7 +94,7 @@ export const gcd = function (a, b) {
*
* @return {Promise} A promise that resolve to a boolean that is either true (a probably prime number) or false (definitely composite)
*/
export const isProbablyPrime = async function (w, iterations = 16) {
export async function isProbablyPrime(w, iterations = 16) {
if (process.browser) {
return new Promise(resolve => {
let worker = new Worker(_isProbablyPrimeWorkerURL());
@ -112,7 +112,7 @@ export const isProbablyPrime = async function (w, iterations = 16) {
} else {
return _isProbablyPrime(w, iterations);
}
};
}
/**
* The least common multiple computed as abs(a*b)/gcd(a,b)
@ -121,11 +121,11 @@ export const isProbablyPrime = async function (w, iterations = 16) {
*
* @returns {bigint} The least common multiple of a and b
*/
export const lcm = function (a, b) {
export function lcm(a, b) {
a = BigInt(a);
b = BigInt(b);
return abs(a * b) / gcd(a, b);
};
}
/**
* Modular inverse.
@ -135,14 +135,14 @@ export const lcm = function (a, b) {
*
* @returns {bigint} the inverse modulo n
*/
export const modInv = function (a, n) {
export function modInv(a, n) {
let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) {
return null; // modular inverse does not exist
} else {
return toZn(egcd.x, n);
}
};
}
/**
* Modular exponentiation a**b mod n
@ -152,7 +152,7 @@ export const modInv = function (a, n) {
*
* @returns {bigint} a**b mod n
*/
export const modPow = function (a, b, n) {
export function modPow(a, b, n) {
// See Knuth, volume 2, section 4.6.3.
n = BigInt(n);
a = toZn(a, n);
@ -173,7 +173,7 @@ export const modPow = function (a, b, n) {
x = x % n;
}
return result;
};
}
/**
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator.
@ -185,7 +185,7 @@ export const modPow = function (a, b, n) {
*
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits
*/
export const prime = async function (bitLength, iterations = 16) {
export async function prime(bitLength, iterations = 16) {
return new Promise(async (resolve) => {
if (process.browser) {
let workerList = [];
@ -231,7 +231,7 @@ export const prime = async function (bitLength, iterations = 16) {
resolve(rnd);
}
});
};
}
/**
* Returns a cryptographically secure random integer between [min,max]
@ -240,7 +240,7 @@ export const prime = async function (bitLength, iterations = 16) {
*
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/
export const randBetween = async function (max, min = 1) {
export async function randBetween(max, min = 1) {
let bitLen = bitLength(max);
let byteLength = bitLen >> 3;
let remaining = bitLen - (byteLength * 8);
@ -259,7 +259,7 @@ export const randBetween = async function (max, min = 1) {
rnd = fromBuffer(buf);
} while (rnd > max || rnd < min);
return rnd;
};
}
/**
* Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
@ -269,7 +269,7 @@ export const randBetween = async function (max, min = 1) {
*
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array filled with cryptographically secure random bytes
*/
export const randBytes = async function (byteLength, forceLength = false) {
export async function randBytes(byteLength, forceLength = false) {
return new Promise((resolve) => {
let buf;
@ -292,7 +292,7 @@ export const randBytes = async function (byteLength, forceLength = false) {
resolve(buf);
}
});
};
}
/**
* Finds the smallest positive element that is congruent to a in modulo n
@ -301,11 +301,11 @@ export const randBytes = async function (byteLength, forceLength = false) {
*
* @returns {bigint} The smallest positive representation of a in modulo n
*/
export const toZn = function (a, n) {
export function toZn(a, n) {
n = BigInt(n);
a = BigInt(a) % n;
return (a < 0) ? a + n : a;
};
}