From 4e52ea75e643249133d1f3e585f52fc65539b287 Mon Sep 17 00:00:00 2001 From: juanelas Date: Mon, 6 Apr 2020 13:34:03 +0200 Subject: [PATCH] JS Standard. Some fixes with the test. Better structure --- README.md | 4 ++-- lib/index.browser.bundle.js | 2 +- lib/index.browser.bundle.mod.js | 2 +- lib/index.browser.mod.js | 13 +++++++++---- lib/index.node.js | 17 +++++++++++------ src/doc/readme-template.md | 2 +- src/js/index.js | 2 +- test/browser/index.iife.html | 26 ++++++++++++++++++++++++++ 8 files changed, 52 insertions(+), 16 deletions(-) create mode 100644 test/browser/index.iife.html diff --git a/README.md b/README.md index 627dc60..b010e77 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # bigint-crypto-utils -Utils for working with cryptography using native JS ([ES-2020](https://tc39.es/ecma262/#sec-bigint-objects)) implementation of BigInt. It includes some extra functions to work with modular arithmetics along with secure random numbers and a fast strong probable prime generator/tester (parallelised multi-threaded Miller-Rabin primality test). It can be used by any [Web Browser or webview supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) and with Node.js (>=10.4.0). In the latter case, for multi-threaded primality tests, you should use Node.js v11 or newer or enable at runtime with `node --experimental-worker` with Node.js version >= 10.5.0 and < 11. +Utils for working with cryptography using native JS ([ES-2020](https://tc39.es/ecma262/#sec-bigint-objects)) implementation of BigInt. It includes some extra functions to work with modular arithmetic along with secure random numbers and a fast strong probable prime generator/tester (parallelized multi-threaded Miller-Rabin primality test). It can be used by any [Web Browser or webview supporting BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility) and with Node.js (>=10.4.0). In the latter case, for multi-threaded primality tests, you should use Node.js v11 or newer or enable at runtime with `node --experimental-worker` with Node.js version >= 10.5.0 and < 11. > 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). @@ -18,7 +18,7 @@ npm install bigint-crypto-utils NPM installation defaults to the minified ES6 module for browsers and the CJS one 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.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 [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub. ## Usage examples diff --git a/lib/index.browser.bundle.js b/lib/index.browser.bundle.js index 63d1e6f..51266c9 100644 --- a/lib/index.browser.bundle.js +++ b/lib/index.browser.bundle.js @@ -1 +1 @@ -var bigintCryptoUtils=function(exports){"use strict";const _ZERO=BigInt(0);const _ONE=BigInt(1);const _TWO=BigInt(2);function abs(a){a=BigInt(a);return a>=_ZERO?a:-a}function bitLength(a){a=BigInt(a);if(a===_ONE){return 1}let bits=1;do{bits++}while((a>>=_ONE)>_ONE);return bits}function eGcd(a,b){a=BigInt(a);b=BigInt(b);if(a<=_ZERO|b<=_ZERO){return NaN}let x=_ZERO;let y=_ONE;let u=_ONE;let v=_ZERO;while(a!==_ZERO){const q=b/a;const r=b%a;const m=x-u*q;const n=y-v*q;b=a;a=r;x=u;y=v;u=m;v=n}return{b:b,x:x,y:y}}function gcd(a,b){a=abs(a);b=abs(b);if(a===_ZERO){return b}else if(b===_ZERO){return a}let shift=_ZERO;while(!((a|b)&_ONE)){a>>=_ONE;b>>=_ONE;shift++}while(!(a&_ONE))a>>=_ONE;do{while(!(b&_ONE))b>>=_ONE;if(a>b){const x=a;a=b;b=x}b-=a}while(b);return a<{const worker=new Worker(_isProbablyPrimeWorkerUrl());worker.onmessage=event=>{worker.terminate();resolve(event.data.isPrime)};worker.onmessageerror=event=>{reject(event)};worker.postMessage({rnd:w,iterations:iterations,id:0})})}}function lcm(a,b){a=BigInt(a);b=BigInt(b);if(a===_ZERO&&b===_ZERO){return _ZERO}return abs(a*b)/gcd(a,b)}function max(a,b){a=BigInt(a);b=BigInt(b);return a>=b?a:b}function min(a,b){a=BigInt(a);b=BigInt(b);return a>=b?b:a}function modInv(a,n){const egcd=eGcd(toZn(a,n),n);if(egcd.b!==_ONE){return NaN}else{return toZn(egcd.x,n)}}function modPow(b,e,n){n=BigInt(n);if(n===_ZERO){return NaN}else if(n===_ONE){return _ZERO}b=toZn(b,n);e=BigInt(e);if(e<_ZERO){return modInv(modPow(b,abs(e),n),n)}let r=_ONE;while(e>0){if(e%_TWO===_ONE){r=r*b%n}e=e/_TWO;b=b**_TWO%n}return r}function prime(bitLength,iterations=16){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}return new Promise(resolve=>{const workerList=[];const _onmessage=(msg,newWorker)=>{if(msg.isPrime){for(let j=0;j_onmessage(event.data,newWorker);workerList.push(newWorker)}}for(let i=0;i 0 and it is ${bitLength}`)}let rnd=_ZERO;do{rnd=fromBuffer(randBytesSync(bitLength/8,true))}while(!_isProbablyPrime(rnd,iterations));return rnd}function randBetween(max,min=_ONE){if(max<=min)throw new Error("max must be > min");const interval=max-min;const bitLen=bitLength(interval);let rnd;do{const buf=randBits(bitLen);rnd=fromBuffer(buf)}while(rnd>interval);return rnd+min}function randBits(bitLength,forceLength=false){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}const byteLength=Math.ceil(bitLength/8);const rndBytes=randBytesSync(byteLength,false);rndBytes[0]=rndBytes[0]&2**(bitLength%8)-1;if(forceLength){const mask=bitLength%8?2**(bitLength%8-1):128;rndBytes[0]=rndBytes[0]|mask}return rndBytes}function randBytes(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{return new Promise((function(resolve){buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf);if(forceLength){buf[0]=buf[0]|128}resolve(buf)}))}}function randBytesSync(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf)}if(forceLength){buf[0]=buf[0]|128}return buf}function toZn(a,n){n=BigInt(n);if(n<=0){return NaN}a=BigInt(a)%n;return a<0?a+n:a}function fromBuffer(buf){let ret=_ZERO;for(const i of buf.values()){const bi=BigInt(i);ret=(ret< {${workerCode}})()`;const _blob=new Blob([workerCode],{type:"text/javascript"});return window.URL.createObjectURL(_blob)}function _isProbablyPrime(w,iterations=16){if(w===_TWO){return true}else if((w&_ONE)===_ZERO||w===_ONE){return false}const firstPrimes=[3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597];for(let i=0;i=_ZERO?a:-a}function bitLength(a){a=BigInt(a);if(a===_ONE){return 1}let bits=1;do{bits++}while((a>>=_ONE)>_ONE);return bits}function eGcd(a,b){a=BigInt(a);b=BigInt(b);if(a<=_ZERO|b<=_ZERO){return NaN}let x=_ZERO;let y=_ONE;let u=_ONE;let v=_ZERO;while(a!==_ZERO){const q=b/a;const r=b%a;const m=x-u*q;const n=y-v*q;b=a;a=r;x=u;y=v;u=m;v=n}return{b:b,x:x,y:y}}function gcd(a,b){a=abs(a);b=abs(b);if(a===_ZERO){return b}else if(b===_ZERO){return a}let shift=_ZERO;while(!((a|b)&_ONE)){a>>=_ONE;b>>=_ONE;shift++}while(!(a&_ONE))a>>=_ONE;do{while(!(b&_ONE))b>>=_ONE;if(a>b){const x=a;a=b;b=x}b-=a}while(b);return a<{const worker=new Worker(_isProbablyPrimeWorkerUrl());worker.onmessage=event=>{worker.terminate();resolve(event.data.isPrime)};worker.onmessageerror=event=>{reject(event)};worker.postMessage({rnd:w,iterations:iterations,id:0})})}}function lcm(a,b){a=BigInt(a);b=BigInt(b);if(a===_ZERO&&b===_ZERO){return _ZERO}return abs(a*b)/gcd(a,b)}function max(a,b){a=BigInt(a);b=BigInt(b);return a>=b?a:b}function min(a,b){a=BigInt(a);b=BigInt(b);return a>=b?b:a}function modInv(a,n){const egcd=eGcd(toZn(a,n),n);if(egcd.b!==_ONE){return NaN}else{return toZn(egcd.x,n)}}function modPow(b,e,n){n=BigInt(n);if(n===_ZERO){return NaN}else if(n===_ONE){return _ZERO}b=toZn(b,n);e=BigInt(e);if(e<_ZERO){return modInv(modPow(b,abs(e),n),n)}let r=_ONE;while(e>0){if(e%_TWO===_ONE){r=r*b%n}e=e/_TWO;b=b**_TWO%n}return r}function prime(bitLength,iterations=16){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}return new Promise(resolve=>{const workerList=[];const _onmessage=(msg,newWorker)=>{if(msg.isPrime){for(let j=0;j_onmessage(event.data,newWorker);workerList.push(newWorker)}}for(let i=0;i 0 and it is ${bitLength}`)}let rnd=_ZERO;do{rnd=fromBuffer(randBytesSync(bitLength/8,true))}while(!_isProbablyPrime(rnd,iterations));return rnd}function randBetween(max,min=_ONE){if(max<=min)throw new Error("max must be > min");const interval=max-min;const bitLen=bitLength(interval);let rnd;do{const buf=randBits(bitLen);rnd=fromBuffer(buf)}while(rnd>interval);return rnd+min}function randBits(bitLength,forceLength=false){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}const byteLength=Math.ceil(bitLength/8);const rndBytes=randBytesSync(byteLength,false);const bitLengthMod8=bitLength%8;if(bitLengthMod8){rndBytes[0]=rndBytes[0]&2**bitLengthMod8-1}if(forceLength){const mask=bitLengthMod8?2**(bitLengthMod8-1):128;rndBytes[0]=rndBytes[0]|mask}return rndBytes}function randBytes(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{return new Promise((function(resolve){buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf);if(forceLength){buf[0]=buf[0]|128}resolve(buf)}))}}function randBytesSync(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf)}if(forceLength){buf[0]=buf[0]|128}return buf}function toZn(a,n){n=BigInt(n);if(n<=0){return NaN}a=BigInt(a)%n;return a<0?a+n:a}function fromBuffer(buf){let ret=_ZERO;for(const i of buf.values()){const bi=BigInt(i);ret=(ret< {${workerCode}})()`;const _blob=new Blob([workerCode],{type:"text/javascript"});return window.URL.createObjectURL(_blob)}function _isProbablyPrime(w,iterations=16){if(w===_TWO){return true}else if((w&_ONE)===_ZERO||w===_ONE){return false}const firstPrimes=[3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597];for(let i=0;i=_ZERO?a:-a}function bitLength(a){a=BigInt(a);if(a===_ONE){return 1}let bits=1;do{bits++}while((a>>=_ONE)>_ONE);return bits}function eGcd(a,b){a=BigInt(a);b=BigInt(b);if(a<=_ZERO|b<=_ZERO){return NaN}let x=_ZERO;let y=_ONE;let u=_ONE;let v=_ZERO;while(a!==_ZERO){const q=b/a;const r=b%a;const m=x-u*q;const n=y-v*q;b=a;a=r;x=u;y=v;u=m;v=n}return{b:b,x:x,y:y}}function gcd(a,b){a=abs(a);b=abs(b);if(a===_ZERO){return b}else if(b===_ZERO){return a}let shift=_ZERO;while(!((a|b)&_ONE)){a>>=_ONE;b>>=_ONE;shift++}while(!(a&_ONE))a>>=_ONE;do{while(!(b&_ONE))b>>=_ONE;if(a>b){const x=a;a=b;b=x}b-=a}while(b);return a<{const worker=new Worker(_isProbablyPrimeWorkerUrl());worker.onmessage=event=>{worker.terminate();resolve(event.data.isPrime)};worker.onmessageerror=event=>{reject(event)};worker.postMessage({rnd:w,iterations:iterations,id:0})})}}function lcm(a,b){a=BigInt(a);b=BigInt(b);if(a===_ZERO&&b===_ZERO){return _ZERO}return abs(a*b)/gcd(a,b)}function max(a,b){a=BigInt(a);b=BigInt(b);return a>=b?a:b}function min(a,b){a=BigInt(a);b=BigInt(b);return a>=b?b:a}function modInv(a,n){const egcd=eGcd(toZn(a,n),n);if(egcd.b!==_ONE){return NaN}else{return toZn(egcd.x,n)}}function modPow(b,e,n){n=BigInt(n);if(n===_ZERO){return NaN}else if(n===_ONE){return _ZERO}b=toZn(b,n);e=BigInt(e);if(e<_ZERO){return modInv(modPow(b,abs(e),n),n)}let r=_ONE;while(e>0){if(e%_TWO===_ONE){r=r*b%n}e=e/_TWO;b=b**_TWO%n}return r}function prime(bitLength,iterations=16){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}return new Promise(resolve=>{const workerList=[];const _onmessage=(msg,newWorker)=>{if(msg.isPrime){for(let j=0;j_onmessage(event.data,newWorker);workerList.push(newWorker)}}for(let i=0;i 0 and it is ${bitLength}`)}let rnd=_ZERO;do{rnd=fromBuffer(randBytesSync(bitLength/8,true))}while(!_isProbablyPrime(rnd,iterations));return rnd}function randBetween(max,min=_ONE){if(max<=min)throw new Error("max must be > min");const interval=max-min;const bitLen=bitLength(interval);let rnd;do{const buf=randBits(bitLen);rnd=fromBuffer(buf)}while(rnd>interval);return rnd+min}function randBits(bitLength,forceLength=false){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}const byteLength=Math.ceil(bitLength/8);const rndBytes=randBytesSync(byteLength,false);rndBytes[0]=rndBytes[0]&2**(bitLength%8)-1;if(forceLength){const mask=bitLength%8?2**(bitLength%8-1):128;rndBytes[0]=rndBytes[0]|mask}return rndBytes}function randBytes(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{return new Promise((function(resolve){buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf);if(forceLength){buf[0]=buf[0]|128}resolve(buf)}))}}function randBytesSync(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf)}if(forceLength){buf[0]=buf[0]|128}return buf}function toZn(a,n){n=BigInt(n);if(n<=0){return NaN}a=BigInt(a)%n;return a<0?a+n:a}function fromBuffer(buf){let ret=_ZERO;for(const i of buf.values()){const bi=BigInt(i);ret=(ret< {${workerCode}})()`;const _blob=new Blob([workerCode],{type:"text/javascript"});return window.URL.createObjectURL(_blob)}function _isProbablyPrime(w,iterations=16){if(w===_TWO){return true}else if((w&_ONE)===_ZERO||w===_ONE){return false}const firstPrimes=[3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597];for(let i=0;i=_ZERO?a:-a}function bitLength(a){a=BigInt(a);if(a===_ONE){return 1}let bits=1;do{bits++}while((a>>=_ONE)>_ONE);return bits}function eGcd(a,b){a=BigInt(a);b=BigInt(b);if(a<=_ZERO|b<=_ZERO){return NaN}let x=_ZERO;let y=_ONE;let u=_ONE;let v=_ZERO;while(a!==_ZERO){const q=b/a;const r=b%a;const m=x-u*q;const n=y-v*q;b=a;a=r;x=u;y=v;u=m;v=n}return{b:b,x:x,y:y}}function gcd(a,b){a=abs(a);b=abs(b);if(a===_ZERO){return b}else if(b===_ZERO){return a}let shift=_ZERO;while(!((a|b)&_ONE)){a>>=_ONE;b>>=_ONE;shift++}while(!(a&_ONE))a>>=_ONE;do{while(!(b&_ONE))b>>=_ONE;if(a>b){const x=a;a=b;b=x}b-=a}while(b);return a<{const worker=new Worker(_isProbablyPrimeWorkerUrl());worker.onmessage=event=>{worker.terminate();resolve(event.data.isPrime)};worker.onmessageerror=event=>{reject(event)};worker.postMessage({rnd:w,iterations:iterations,id:0})})}}function lcm(a,b){a=BigInt(a);b=BigInt(b);if(a===_ZERO&&b===_ZERO){return _ZERO}return abs(a*b)/gcd(a,b)}function max(a,b){a=BigInt(a);b=BigInt(b);return a>=b?a:b}function min(a,b){a=BigInt(a);b=BigInt(b);return a>=b?b:a}function modInv(a,n){const egcd=eGcd(toZn(a,n),n);if(egcd.b!==_ONE){return NaN}else{return toZn(egcd.x,n)}}function modPow(b,e,n){n=BigInt(n);if(n===_ZERO){return NaN}else if(n===_ONE){return _ZERO}b=toZn(b,n);e=BigInt(e);if(e<_ZERO){return modInv(modPow(b,abs(e),n),n)}let r=_ONE;while(e>0){if(e%_TWO===_ONE){r=r*b%n}e=e/_TWO;b=b**_TWO%n}return r}function prime(bitLength,iterations=16){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}return new Promise(resolve=>{const workerList=[];const _onmessage=(msg,newWorker)=>{if(msg.isPrime){for(let j=0;j_onmessage(event.data,newWorker);workerList.push(newWorker)}}for(let i=0;i 0 and it is ${bitLength}`)}let rnd=_ZERO;do{rnd=fromBuffer(randBytesSync(bitLength/8,true))}while(!_isProbablyPrime(rnd,iterations));return rnd}function randBetween(max,min=_ONE){if(max<=min)throw new Error("max must be > min");const interval=max-min;const bitLen=bitLength(interval);let rnd;do{const buf=randBits(bitLen);rnd=fromBuffer(buf)}while(rnd>interval);return rnd+min}function randBits(bitLength,forceLength=false){if(bitLength<1){throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`)}const byteLength=Math.ceil(bitLength/8);const rndBytes=randBytesSync(byteLength,false);const bitLengthMod8=bitLength%8;if(bitLengthMod8){rndBytes[0]=rndBytes[0]&2**bitLengthMod8-1}if(forceLength){const mask=bitLengthMod8?2**(bitLengthMod8-1):128;rndBytes[0]=rndBytes[0]|mask}return rndBytes}function randBytes(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{return new Promise((function(resolve){buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf);if(forceLength){buf[0]=buf[0]|128}resolve(buf)}))}}function randBytesSync(byteLength,forceLength=false){if(byteLength<1){throw new RangeError(`byteLength MUST be > 0 and it is ${byteLength}`)}let buf;{buf=new Uint8Array(byteLength);self.crypto.getRandomValues(buf)}if(forceLength){buf[0]=buf[0]|128}return buf}function toZn(a,n){n=BigInt(n);if(n<=0){return NaN}a=BigInt(a)%n;return a<0?a+n:a}function fromBuffer(buf){let ret=_ZERO;for(const i of buf.values()){const bi=BigInt(i);ret=(ret< {${workerCode}})()`;const _blob=new Blob([workerCode],{type:"text/javascript"});return window.URL.createObjectURL(_blob)}function _isProbablyPrime(w,iterations=16){if(w===_TWO){return true}else if((w&_ONE)===_ZERO||w===_ONE){return false}const firstPrimes=[3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597];for(let i=0;i 0 and it is ${bitLength}`) } + if (bitLength < 1) { + throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) + } const byteLength = Math.ceil(bitLength / 8) const rndBytes = randBytesSync(byteLength, false) - // Fill with 0's the extra bits - rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1) + const bitLengthMod8 = bitLength % 8 + if (bitLengthMod8) { + // Fill with 0's the extra bits + rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1) + } if (forceLength) { - const mask = (bitLength % 8) ? 2 ** ((bitLength % 8) - 1) : 128 + const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128 rndBytes[0] = rndBytes[0] | mask } return rndBytes diff --git a/lib/index.node.js b/lib/index.node.js index 7c31d51..160bc39 100644 --- a/lib/index.node.js +++ b/lib/index.node.js @@ -362,14 +362,19 @@ function randBetween (max, min = _ONE) { * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bits */ function randBits (bitLength, forceLength = false) { - if (bitLength < 1) { throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) } + if (bitLength < 1) { + throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`) + } const byteLength = Math.ceil(bitLength / 8) const rndBytes = randBytesSync(byteLength, false) - // Fill with 0's the extra bits - rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1) + const bitLengthMod8 = bitLength % 8 + if (bitLengthMod8) { + // Fill with 0's the extra bits + rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1) + } if (forceLength) { - const mask = (bitLength % 8) ? 2 ** ((bitLength % 8) - 1) : 128 + const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128 rndBytes[0] = rndBytes[0] | mask } return rndBytes @@ -769,8 +774,8 @@ let _useWorkers = true // The following is just to check whether Node.js can use } catch (e) { console.log(`[bigint-crypto-utils] WARNING: This node version doesn't support worker_threads. You should enable them in order to greatly speedup the generation of big prime numbers. - · With Node 11 it is enabled by default (consider upgrading). - · With Node 10, starting with 10.5.0, you can enable worker_threads at runtime executing node --experimental-worker `) + · With Node >=11 it is enabled by default (consider upgrading). + · With Node 10, starting with 10.4.0, you can enable worker_threads at runtime executing node --experimental-worker `) return false } })() diff --git a/src/doc/readme-template.md b/src/doc/readme-template.md index 95b294f..f8648c2 100644 --- a/src/doc/readme-template.md +++ b/src/doc/readme-template.md @@ -18,7 +18,7 @@ npm install bigint-crypto-utils NPM installation defaults to the minified ES6 module for browsers and the CJS one 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.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 [IIFE file](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/bigint-crypto-utils/master/lib/index.browser.bundle.mod.js) from GitHub. ## Usage examples diff --git a/src/js/index.js b/src/js/index.js index 7b1fb16..d17ab77 100644 --- a/src/js/index.js +++ b/src/js/index.js @@ -833,7 +833,7 @@ if (!process.browser) { // Node.js console.log(`[bigint-crypto-utils] WARNING: This node version doesn't support worker_threads. You should enable them in order to greatly speedup the generation of big prime numbers. · With Node >=11 it is enabled by default (consider upgrading). - · With Node 10, starting with 10.5.0, you can enable worker_threads at runtime executing node --experimental-worker `) + · With Node 10, starting with 10.4.0, you can enable worker_threads at runtime executing node --experimental-worker `) return false } })() diff --git a/test/browser/index.iife.html b/test/browser/index.iife.html new file mode 100644 index 0000000..0470298 --- /dev/null +++ b/test/browser/index.iife.html @@ -0,0 +1,26 @@ + + + + + Primes + + + + +
result of primeSync() will show up here
+
result of prime() will show up here
+ + + + + + \ No newline at end of file