minor improvements in code structure

This commit is contained in:
juanelas 2019-04-23 16:57:06 +02:00
parent bad4ebde36
commit 6bb0b2f78e
6 changed files with 167 additions and 145 deletions

View File

@ -10,7 +10,7 @@ var bigintCryptoUtils = (function (exports) {
*/ */
function abs(a) { function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? a : -a;
} }
/** /**
@ -31,12 +31,12 @@ var bigintCryptoUtils = (function (exports) {
function eGcd(a, b) { function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -66,15 +66,15 @@ var bigintCryptoUtils = (function (exports) {
function gcd(a, b) { function gcd(a, b) {
a = abs(a); a = abs(a);
b = abs(b); b = abs(b);
let shift = BigInt(0); let shift = _ZERO;
while (!((a | b) & BigInt(1))) { while (!((a | b) & _ONE)) {
a >>= BigInt(1); a >>= _ONE;
b >>= BigInt(1); b >>= _ONE;
shift++; shift++;
} }
while (!(a & BigInt(1))) a >>= BigInt(1); while (!(a & _ONE)) a >>= _ONE;
do { do {
while (!(b & BigInt(1))) b >>= BigInt(1); while (!(b & _ONE)) b >>= _ONE;
if (a > b) { if (a > b) {
let x = a; let x = a;
a = b; a = b;
@ -142,7 +142,7 @@ var bigintCryptoUtils = (function (exports) {
*/ */
function modInv(a, n) { function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
@ -162,15 +162,15 @@ var bigintCryptoUtils = (function (exports) {
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -248,7 +248,7 @@ var bigintCryptoUtils = (function (exports) {
* *
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max] * @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/ */
async function randBetween(max, min = BigInt(1)) { async function randBetween(max, min = _ONE) {
if (max <= min) throw new Error('max must be > min'); if (max <= min) throw new Error('max must be > min');
const interval = max - min; const interval = max - min;
let bitLen = bitLength(interval); let bitLen = bitLength(interval);
@ -321,7 +321,7 @@ var bigintCryptoUtils = (function (exports) {
/* HELPER FUNCTIONS */ /* HELPER FUNCTIONS */
function fromBuffer(buf) { function fromBuffer(buf) {
let ret = BigInt(0); let ret = _ZERO;
for (let i of buf.values()) { for (let i of buf.values()) {
let bi = BigInt(i); let bi = BigInt(i);
ret = (ret << BigInt(8)) + bi; ret = (ret << BigInt(8)) + bi;
@ -333,13 +333,13 @@ var bigintCryptoUtils = (function (exports) {
let bits = 1; let bits = 1;
do { do {
bits++; bits++;
} while ((a >>= BigInt(1)) > BigInt(1)); } while ((a >>= _ONE) > _ONE);
return bits; return bits;
} }
function _isProbablyPrimeWorkerURL() { function _isProbablyPrimeWorkerURL() {
// Let's us first add all the required functions // Let's us first add all the required functions
let workerCode = `'use strict';const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`; 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 randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;
const _onmessage = async function (event) { // Let's start once we are called const _onmessage = async function (event) { // Let's start once we are called
// event.data = {rnd: <bigint>, iterations: <number>} // event.data = {rnd: <bigint>, iterations: <number>}
@ -364,9 +364,9 @@ var bigintCryptoUtils = (function (exports) {
PREFILTERING. Even values but 2 are not primes, so don't test. 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. 1 is not a prime and the M-R algorithm needs w>1.
*/ */
if (w === BigInt(2)) if (w === _TWO)
return true; return true;
else if ((w & BigInt(1)) === BigInt(0) || w === BigInt(1)) else if ((w & _ONE) === _ZERO || w === _ONE)
return false; return false;
/* /*
@ -628,7 +628,7 @@ var bigintCryptoUtils = (function (exports) {
const p = BigInt(firstPrimes[i]); const p = BigInt(firstPrimes[i]);
if (w === p) if (w === p)
return true; return true;
else if (w % p === BigInt(0)) else if (w % p === _ZERO)
return false; return false;
} }
@ -651,25 +651,25 @@ var bigintCryptoUtils = (function (exports) {
Comment: Increment i for the do-loop in step 4. Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME. 5. Return PROBABLY PRIME.
*/ */
let a = BigInt(0), d = w - BigInt(1); let a = _ZERO, d = w - _ONE;
while (d % BigInt(2) === BigInt(0)) { while (d % _TWO === _ZERO) {
d /= BigInt(2); d /= _TWO;
++a; ++a;
} }
let m = (w - BigInt(1)) / (BigInt(2) ** a); let m = (w - _ONE) / (_TWO ** a);
loop: do { loop: do {
let b = await randBetween(w - BigInt(1), BigInt(2)); let b = await randBetween(w - _ONE, _TWO);
let z = modPow(b, m, w); let z = modPow(b, m, w);
if (z === BigInt(1) || z === w - BigInt(1)) if (z === _ONE || z === w - _ONE)
continue; continue;
for (let j = 1; j < a; j++) { for (let j = 1; j < a; j++) {
z = modPow(z, BigInt(2), w); z = modPow(z, _TWO, w);
if (z === w - BigInt(1)) if (z === w - _ONE)
continue loop; continue loop;
if (z === BigInt(1)) if (z === _ONE)
break; break;
} }
return false; return false;
@ -678,6 +678,11 @@ var bigintCryptoUtils = (function (exports) {
return true; return true;
} }
/* HELPLER CONSTANTS/VARIABLES*/
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
exports.abs = abs; exports.abs = abs;
exports.eGcd = eGcd; exports.eGcd = eGcd;
exports.gcd = gcd; exports.gcd = gcd;

View File

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

View File

@ -7,7 +7,7 @@
*/ */
function abs(a) { function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? a : -a;
} }
/** /**
@ -28,12 +28,12 @@ function abs(a) {
function eGcd(a, b) { function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -63,15 +63,15 @@ function eGcd(a, b) {
function gcd(a, b) { function gcd(a, b) {
a = abs(a); a = abs(a);
b = abs(b); b = abs(b);
let shift = BigInt(0); let shift = _ZERO;
while (!((a | b) & BigInt(1))) { while (!((a | b) & _ONE)) {
a >>= BigInt(1); a >>= _ONE;
b >>= BigInt(1); b >>= _ONE;
shift++; shift++;
} }
while (!(a & BigInt(1))) a >>= BigInt(1); while (!(a & _ONE)) a >>= _ONE;
do { do {
while (!(b & BigInt(1))) b >>= BigInt(1); while (!(b & _ONE)) b >>= _ONE;
if (a > b) { if (a > b) {
let x = a; let x = a;
a = b; a = b;
@ -139,7 +139,7 @@ function lcm(a, b) {
*/ */
function modInv(a, n) { function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
@ -159,15 +159,15 @@ function modPow(a, b, n) {
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -245,7 +245,7 @@ async function prime(bitLength, iterations = 16) {
* *
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max] * @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/ */
async function randBetween(max, min = BigInt(1)) { async function randBetween(max, min = _ONE) {
if (max <= min) throw new Error('max must be > min'); if (max <= min) throw new Error('max must be > min');
const interval = max - min; const interval = max - min;
let bitLen = bitLength(interval); let bitLen = bitLength(interval);
@ -318,7 +318,7 @@ function toZn(a, n) {
/* HELPER FUNCTIONS */ /* HELPER FUNCTIONS */
function fromBuffer(buf) { function fromBuffer(buf) {
let ret = BigInt(0); let ret = _ZERO;
for (let i of buf.values()) { for (let i of buf.values()) {
let bi = BigInt(i); let bi = BigInt(i);
ret = (ret << BigInt(8)) + bi; ret = (ret << BigInt(8)) + bi;
@ -330,13 +330,13 @@ function bitLength(a) {
let bits = 1; let bits = 1;
do { do {
bits++; bits++;
} while ((a >>= BigInt(1)) > BigInt(1)); } while ((a >>= _ONE) > _ONE);
return bits; return bits;
} }
function _isProbablyPrimeWorkerURL() { function _isProbablyPrimeWorkerURL() {
// Let's us first add all the required functions // Let's us first add all the required functions
let workerCode = `'use strict';const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`; 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 randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;
const _onmessage = async function (event) { // Let's start once we are called const _onmessage = async function (event) { // Let's start once we are called
// event.data = {rnd: <bigint>, iterations: <number>} // event.data = {rnd: <bigint>, iterations: <number>}
@ -361,9 +361,9 @@ async function _isProbablyPrime(w, iterations = 16) {
PREFILTERING. Even values but 2 are not primes, so don't test. 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. 1 is not a prime and the M-R algorithm needs w>1.
*/ */
if (w === BigInt(2)) if (w === _TWO)
return true; return true;
else if ((w & BigInt(1)) === BigInt(0) || w === BigInt(1)) else if ((w & _ONE) === _ZERO || w === _ONE)
return false; return false;
/* /*
@ -625,7 +625,7 @@ async function _isProbablyPrime(w, iterations = 16) {
const p = BigInt(firstPrimes[i]); const p = BigInt(firstPrimes[i]);
if (w === p) if (w === p)
return true; return true;
else if (w % p === BigInt(0)) else if (w % p === _ZERO)
return false; return false;
} }
@ -648,25 +648,25 @@ async function _isProbablyPrime(w, iterations = 16) {
Comment: Increment i for the do-loop in step 4. Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME. 5. Return PROBABLY PRIME.
*/ */
let a = BigInt(0), d = w - BigInt(1); let a = _ZERO, d = w - _ONE;
while (d % BigInt(2) === BigInt(0)) { while (d % _TWO === _ZERO) {
d /= BigInt(2); d /= _TWO;
++a; ++a;
} }
let m = (w - BigInt(1)) / (BigInt(2) ** a); let m = (w - _ONE) / (_TWO ** a);
loop: do { loop: do {
let b = await randBetween(w - BigInt(1), BigInt(2)); let b = await randBetween(w - _ONE, _TWO);
let z = modPow(b, m, w); let z = modPow(b, m, w);
if (z === BigInt(1) || z === w - BigInt(1)) if (z === _ONE || z === w - _ONE)
continue; continue;
for (let j = 1; j < a; j++) { for (let j = 1; j < a; j++) {
z = modPow(z, BigInt(2), w); z = modPow(z, _TWO, w);
if (z === w - BigInt(1)) if (z === w - _ONE)
continue loop; continue loop;
if (z === BigInt(1)) if (z === _ONE)
break; break;
} }
return false; return false;
@ -675,4 +675,9 @@ async function _isProbablyPrime(w, iterations = 16) {
return true; return true;
} }
/* HELPLER CONSTANTS/VARIABLES*/
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
export { abs, eGcd, gcd, isProbablyPrime, lcm, modInv, modPow, prime, randBetween, randBits, randBytes, toZn }; export { abs, eGcd, gcd, isProbablyPrime, lcm, modInv, modPow, prime, randBetween, randBits, randBytes, toZn };

View File

@ -1 +1 @@
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,d)=>{let e=new Worker(_isProbablyPrimeWorkerURL());e.onmessage=a=>{e.terminate(),c(a.data.isPrime)},e.onmessageerror=a=>{d(a)},e.postMessage({rnd:a,iterations:b,id:0})})}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(c=>{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;a<d.length;a++)d[a].terminate();for(;d.length;)d.pop();c(e.value)}else randBits(a,!0).then(a=>{let c=fromBuffer(a);try{f.postMessage({rnd:c,iterations:b,id:e.id})}catch(a){}})};{let a=_isProbablyPrimeWorkerURL();for(let b,c=0;c<self.navigator.hardwareConcurrency;c++)b=new Worker(a),b.onmessage=a=>e(a.data,b),d.push(b)}for(let e=0;e<d.length;e++)randBits(a,!0).then(a=>{let c=fromBuffer(a);d[e].postMessage({rnd:c,iterations:b,id:e})})})}async function randBetween(a,b=BigInt(1)){if(a<=b)throw new Error("max must be > min");const c=a-b;let d,e=bitLength(c);do{let a=await randBits(e);d=fromBuffer(a)}while(d>c);return d+b}async function randBits(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=await randBytes(d,!1);if(e[0]&=2**(a%8)-1,b){let b=a%8?2**(a%8-1):128;e[0]|=b}return e}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 randBits = ${randBits.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;a+=`onmessage = ${async function(a){const b=await isProbablyPrime(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd,id:a.data.id})}.toString()};`,a=`(() => {${a}})()`;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),BigInt(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,randBits,randBytes,toZn}; function abs(b){return b=BigInt(b),b>=_ZERO?b:-b}function eGcd(c,d){c=BigInt(c),d=BigInt(d);let e=_ZERO,f=_ONE,g=_ONE,h=_ZERO;for(;c!==_ZERO;){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=_ZERO;for(;!((c|d)&_ONE);)c>>=_ONE,d>>=_ONE,e++;for(;!(c&_ONE);)c>>=_ONE;do{for(;!(d&_ONE);)d>>=_ONE;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,d)=>{let e=new Worker(_isProbablyPrimeWorkerURL());e.onmessage=a=>{e.terminate(),c(a.data.isPrime)},e.onmessageerror=a=>{d(a)},e.postMessage({rnd:a,iterations:b,id:0})})}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===_ONE?toZn(c.x,a):null}function modPow(c,d,e){if(e=BigInt(e),c=toZn(c,e),d=BigInt(d),d<_ZERO)return modInv(modPow(c,abs(d),e),e);let f=_ONE,g=c;for(;0<d;){var h=d%_TWO;d/=_TWO,h==_ONE&&(f*=g,f%=e),g*=g,g%=e}return f}async function prime(a,b=16){return new Promise(c=>{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;a<d.length;a++)d[a].terminate();for(;d.length;)d.pop();c(e.value)}else randBits(a,!0).then(a=>{let c=fromBuffer(a);try{f.postMessage({rnd:c,iterations:b,id:e.id})}catch(a){}})};{let a=_isProbablyPrimeWorkerURL();for(let b,c=0;c<self.navigator.hardwareConcurrency;c++)b=new Worker(a),b.onmessage=a=>e(a.data,b),d.push(b)}for(let e=0;e<d.length;e++)randBits(a,!0).then(a=>{let c=fromBuffer(a);d[e].postMessage({rnd:c,iterations:b,id:e})})})}async function randBetween(a,b=_ONE){if(a<=b)throw new Error("max must be > min");const c=a-b;let d,e=bitLength(c);do{let a=await randBits(e);d=fromBuffer(a)}while(d>c);return d+b}async function randBits(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=await randBytes(d,!1);if(e[0]&=2**(a%8)-1,b){let b=a%8?2**(a%8-1):128;e[0]|=b}return e}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=_ZERO;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>>=_ONE)>_ONE);return c}function _isProbablyPrimeWorkerURL(){let a=`'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 randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;a+=`onmessage = ${async function(a){const b=await isProbablyPrime(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd,id:a.data.id})}.toString()};`,a=`(() => {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}async function _isProbablyPrime(c,b=16){if(c===_TWO)return!0;if((c&_ONE)===_ZERO||c===_ONE)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===_ZERO)return!1}let f=_ZERO,g=c-_ONE;for(;g%_TWO===_ZERO;)g/=_TWO,++f;let h=(c-_ONE)/_TWO**f;loop:do{let a=await randBetween(c-_ONE,_TWO),b=modPow(a,h,c);if(b===_ONE||b===c-_ONE)continue;for(let a=1;a<f;a++){if(b=modPow(b,_TWO,c),b===c-_ONE)continue loop;if(b===_ONE)break}return!1}while(--b);return!0}const _ZERO=BigInt(0),_ONE=BigInt(1),_TWO=BigInt(2);export{abs,eGcd,gcd,isProbablyPrime,lcm,modInv,modPow,prime,randBetween,randBits,randBytes,toZn};

View File

@ -11,7 +11,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
*/ */
function abs(a) { function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? a : -a;
} }
/** /**
@ -32,12 +32,12 @@ function abs(a) {
function eGcd(a, b) { function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -67,15 +67,15 @@ function eGcd(a, b) {
function gcd(a, b) { function gcd(a, b) {
a = abs(a); a = abs(a);
b = abs(b); b = abs(b);
let shift = BigInt(0); let shift = _ZERO;
while (!((a | b) & BigInt(1))) { while (!((a | b) & _ONE)) {
a >>= BigInt(1); a >>= _ONE;
b >>= BigInt(1); b >>= _ONE;
shift++; shift++;
} }
while (!(a & BigInt(1))) a >>= BigInt(1); while (!(a & _ONE)) a >>= _ONE;
do { do {
while (!(b & BigInt(1))) b >>= BigInt(1); while (!(b & _ONE)) b >>= _ONE;
if (a > b) { if (a > b) {
let x = a; let x = a;
a = b; a = b;
@ -147,7 +147,7 @@ function lcm(a, b) {
*/ */
function modInv(a, n) { function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
@ -167,15 +167,15 @@ function modPow(a, b, n) {
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -199,7 +199,7 @@ function modPow(a, b, n) {
*/ */
async function prime(bitLength, iterations = 16) { async function prime(bitLength, iterations = 16) {
if (!_useWorkers) { if (!_useWorkers) {
let rnd = BigInt(0); let rnd = _ZERO;
do { do {
rnd = fromBuffer(await randBytes(bitLength / 8, true)); rnd = fromBuffer(await randBytes(bitLength / 8, true));
} while (! await _isProbablyPrime(rnd, iterations)); } while (! await _isProbablyPrime(rnd, iterations));
@ -261,7 +261,7 @@ async function prime(bitLength, iterations = 16) {
* *
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max] * @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/ */
async function randBetween(max, min = BigInt(1)) { async function randBetween(max, min = _ONE) {
if (max <= min) throw new Error('max must be > min'); if (max <= min) throw new Error('max must be > min');
const interval = max - min; const interval = max - min;
let bitLen = bitLength(interval); let bitLen = bitLength(interval);
@ -337,7 +337,7 @@ function toZn(a, n) {
/* HELPER FUNCTIONS */ /* HELPER FUNCTIONS */
function fromBuffer(buf) { function fromBuffer(buf) {
let ret = BigInt(0); let ret = _ZERO;
for (let i of buf.values()) { for (let i of buf.values()) {
let bi = BigInt(i); let bi = BigInt(i);
ret = (ret << BigInt(8)) + bi; ret = (ret << BigInt(8)) + bi;
@ -349,7 +349,7 @@ function bitLength(a) {
let bits = 1; let bits = 1;
do { do {
bits++; bits++;
} while ((a >>= BigInt(1)) > BigInt(1)); } while ((a >>= _ONE) > _ONE);
return bits; return bits;
} }
@ -358,9 +358,9 @@ async function _isProbablyPrime(w, iterations = 16) {
PREFILTERING. Even values but 2 are not primes, so don't test. 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. 1 is not a prime and the M-R algorithm needs w>1.
*/ */
if (w === BigInt(2)) if (w === _TWO)
return true; return true;
else if ((w & BigInt(1)) === BigInt(0) || w === BigInt(1)) else if ((w & _ONE) === _ZERO || w === _ONE)
return false; return false;
/* /*
@ -622,7 +622,7 @@ async function _isProbablyPrime(w, iterations = 16) {
const p = BigInt(firstPrimes[i]); const p = BigInt(firstPrimes[i]);
if (w === p) if (w === p)
return true; return true;
else if (w % p === BigInt(0)) else if (w % p === _ZERO)
return false; return false;
} }
@ -645,25 +645,25 @@ async function _isProbablyPrime(w, iterations = 16) {
Comment: Increment i for the do-loop in step 4. Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME. 5. Return PROBABLY PRIME.
*/ */
let a = BigInt(0), d = w - BigInt(1); let a = _ZERO, d = w - _ONE;
while (d % BigInt(2) === BigInt(0)) { while (d % _TWO === _ZERO) {
d /= BigInt(2); d /= _TWO;
++a; ++a;
} }
let m = (w - BigInt(1)) / (BigInt(2) ** a); let m = (w - _ONE) / (_TWO ** a);
loop: do { loop: do {
let b = await randBetween(w - BigInt(1), BigInt(2)); let b = await randBetween(w - _ONE, _TWO);
let z = modPow(b, m, w); let z = modPow(b, m, w);
if (z === BigInt(1) || z === w - BigInt(1)) if (z === _ONE || z === w - _ONE)
continue; continue;
for (let j = 1; j < a; j++) { for (let j = 1; j < a; j++) {
z = modPow(z, BigInt(2), w); z = modPow(z, _TWO, w);
if (z === w - BigInt(1)) if (z === w - _ONE)
continue loop; continue loop;
if (z === BigInt(1)) if (z === _ONE)
break; break;
} }
return false; return false;
@ -672,9 +672,13 @@ async function _isProbablyPrime(w, iterations = 16) {
return true; return true;
} }
let _useWorkers = true; /* HELPLER CONSTANTS/VARIABLES*/
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
{ let _useWorkers = true; // The following is just to check wheter Node.js can use workers
{ // Node.js
_useWorkers = (function _workers() { _useWorkers = (function _workers() {
try { try {
require.resolve('worker_threads'); require.resolve('worker_threads');
@ -689,7 +693,9 @@ This node version doesn't support worker_threads. You should enable them in orde
})(); })();
} }
if (_useWorkers) { // node.js
if (_useWorkers) { // node.js with support for workers
const { parentPort, isMainThread } = require('worker_threads'); const { parentPort, isMainThread } = require('worker_threads');
if (!isMainThread) { // worker if (!isMainThread) { // worker
parentPort.on('message', async function (data) { // Let's start once we are called parentPort.on('message', async function (data) { // Let's start once we are called

View File

@ -9,7 +9,7 @@
*/ */
export function abs(a) { export function abs(a) {
a = BigInt(a); a = BigInt(a);
return (a >= BigInt(0)) ? a : -a; return (a >= _ZERO) ? a : -a;
} }
/** /**
@ -30,12 +30,12 @@ export function abs(a) {
export function eGcd(a, b) { export function eGcd(a, b) {
a = BigInt(a); a = BigInt(a);
b = BigInt(b); b = BigInt(b);
let x = BigInt(0); let x = _ZERO;
let y = BigInt(1); let y = _ONE;
let u = BigInt(1); let u = _ONE;
let v = BigInt(0); let v = _ZERO;
while (a !== BigInt(0)) { while (a !== _ZERO) {
let q = b / a; let q = b / a;
let r = b % a; let r = b % a;
let m = x - (u * q); let m = x - (u * q);
@ -65,15 +65,15 @@ export function eGcd(a, b) {
export function gcd(a, b) { export function gcd(a, b) {
a = abs(a); a = abs(a);
b = abs(b); b = abs(b);
let shift = BigInt(0); let shift = _ZERO;
while (!((a | b) & BigInt(1))) { while (!((a | b) & _ONE)) {
a >>= BigInt(1); a >>= _ONE;
b >>= BigInt(1); b >>= _ONE;
shift++; shift++;
} }
while (!(a & BigInt(1))) a >>= BigInt(1); while (!(a & _ONE)) a >>= _ONE;
do { do {
while (!(b & BigInt(1))) b >>= BigInt(1); while (!(b & _ONE)) b >>= _ONE;
if (a > b) { if (a > b) {
let x = a; let x = a;
a = b; a = b;
@ -164,7 +164,7 @@ export function lcm(a, b) {
*/ */
export function modInv(a, n) { export function modInv(a, n) {
let egcd = eGcd(a, n); let egcd = eGcd(a, n);
if (egcd.b !== BigInt(1)) { if (egcd.b !== _ONE) {
return null; // modular inverse does not exist return null; // modular inverse does not exist
} else { } else {
return toZn(egcd.x, n); return toZn(egcd.x, n);
@ -184,15 +184,15 @@ export function modPow(a, b, n) {
n = BigInt(n); n = BigInt(n);
a = toZn(a, n); a = toZn(a, n);
b = BigInt(b); b = BigInt(b);
if (b < BigInt(0)) { if (b < _ZERO) {
return modInv(modPow(a, abs(b), n), n); return modInv(modPow(a, abs(b), n), n);
} }
let result = BigInt(1); let result = _ONE;
let x = a; let x = a;
while (b > 0) { while (b > 0) {
var leastSignificantBit = b % BigInt(2); var leastSignificantBit = b % _TWO;
b = b / BigInt(2); b = b / _TWO;
if (leastSignificantBit == BigInt(1)) { if (leastSignificantBit == _ONE) {
result = result * x; result = result * x;
result = result % n; result = result % n;
} }
@ -216,7 +216,7 @@ export function modPow(a, b, n) {
*/ */
export async function prime(bitLength, iterations = 16) { export async function prime(bitLength, iterations = 16) {
if (!process.browser && !_useWorkers) { if (!process.browser && !_useWorkers) {
let rnd = BigInt(0); let rnd = _ZERO;
do { do {
rnd = fromBuffer(await randBytes(bitLength / 8, true)); rnd = fromBuffer(await randBytes(bitLength / 8, true));
} while (! await _isProbablyPrime(rnd, iterations)); } while (! await _isProbablyPrime(rnd, iterations));
@ -285,7 +285,7 @@ export async function prime(bitLength, iterations = 16) {
* *
* @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max] * @returns {Promise} A promise that resolves to a cryptographically secure random bigint between [min,max]
*/ */
export async function randBetween(max, min = BigInt(1)) { export async function randBetween(max, min = _ONE) {
if (max <= min) throw new Error('max must be > min'); if (max <= min) throw new Error('max must be > min');
const interval = max - min; const interval = max - min;
let bitLen = bitLength(interval); let bitLen = bitLength(interval);
@ -368,7 +368,7 @@ export function toZn(a, n) {
/* HELPER FUNCTIONS */ /* HELPER FUNCTIONS */
function fromBuffer(buf) { function fromBuffer(buf) {
let ret = BigInt(0); let ret = _ZERO;
for (let i of buf.values()) { for (let i of buf.values()) {
let bi = BigInt(i); let bi = BigInt(i);
ret = (ret << BigInt(8)) + bi; ret = (ret << BigInt(8)) + bi;
@ -380,13 +380,13 @@ function bitLength(a) {
let bits = 1; let bits = 1;
do { do {
bits++; bits++;
} while ((a >>= BigInt(1)) > BigInt(1)); } while ((a >>= _ONE) > _ONE);
return bits; return bits;
} }
function _isProbablyPrimeWorkerURL() { function _isProbablyPrimeWorkerURL() {
// Let's us first add all the required functions // Let's us first add all the required functions
let workerCode = `'use strict';const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`; 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 randBytes = ${randBytes.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;
const _onmessage = async function (event) { // Let's start once we are called const _onmessage = async function (event) { // Let's start once we are called
// event.data = {rnd: <bigint>, iterations: <number>} // event.data = {rnd: <bigint>, iterations: <number>}
@ -411,9 +411,9 @@ async function _isProbablyPrime(w, iterations = 16) {
PREFILTERING. Even values but 2 are not primes, so don't test. 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. 1 is not a prime and the M-R algorithm needs w>1.
*/ */
if (w === BigInt(2)) if (w === _TWO)
return true; return true;
else if ((w & BigInt(1)) === BigInt(0) || w === BigInt(1)) else if ((w & _ONE) === _ZERO || w === _ONE)
return false; return false;
/* /*
@ -675,7 +675,7 @@ async function _isProbablyPrime(w, iterations = 16) {
const p = BigInt(firstPrimes[i]); const p = BigInt(firstPrimes[i]);
if (w === p) if (w === p)
return true; return true;
else if (w % p === BigInt(0)) else if (w % p === _ZERO)
return false; return false;
} }
@ -698,25 +698,25 @@ async function _isProbablyPrime(w, iterations = 16) {
Comment: Increment i for the do-loop in step 4. Comment: Increment i for the do-loop in step 4.
5. Return PROBABLY PRIME. 5. Return PROBABLY PRIME.
*/ */
let a = BigInt(0), d = w - BigInt(1); let a = _ZERO, d = w - _ONE;
while (d % BigInt(2) === BigInt(0)) { while (d % _TWO === _ZERO) {
d /= BigInt(2); d /= _TWO;
++a; ++a;
} }
let m = (w - BigInt(1)) / (BigInt(2) ** a); let m = (w - _ONE) / (_TWO ** a);
loop: do { loop: do {
let b = await randBetween(w - BigInt(1), BigInt(2)); let b = await randBetween(w - _ONE, _TWO);
let z = modPow(b, m, w); let z = modPow(b, m, w);
if (z === BigInt(1) || z === w - BigInt(1)) if (z === _ONE || z === w - _ONE)
continue; continue;
for (let j = 1; j < a; j++) { for (let j = 1; j < a; j++) {
z = modPow(z, BigInt(2), w); z = modPow(z, _TWO, w);
if (z === w - BigInt(1)) if (z === w - _ONE)
continue loop; continue loop;
if (z === BigInt(1)) if (z === _ONE)
break; break;
} }
return false; return false;
@ -725,9 +725,13 @@ async function _isProbablyPrime(w, iterations = 16) {
return true; return true;
} }
let _useWorkers = true; /* HELPLER CONSTANTS/VARIABLES*/
const _ZERO = BigInt(0);
const _ONE = BigInt(1);
const _TWO = BigInt(2);
if (!process.browser) { let _useWorkers = true; // The following is just to check wheter Node.js can use workers
if (!process.browser) { // Node.js
_useWorkers = (function _workers() { _useWorkers = (function _workers() {
try { try {
require.resolve('worker_threads'); require.resolve('worker_threads');
@ -742,7 +746,9 @@ This node version doesn't support worker_threads. You should enable them in orde
})(); })();
} }
if (!process.browser && _useWorkers) { // node.js
if (!process.browser && _useWorkers) { // node.js with support for workers
const { parentPort, isMainThread } = require('worker_threads'); const { parentPort, isMainThread } = require('worker_threads');
if (!isMainThread) { // worker if (!isMainThread) { // worker
parentPort.on('message', async function (data) { // Let's start once we are called parentPort.on('message', async function (data) { // Let's start once we are called