diff --git a/README.hbs b/README.hbs
index 8b209c2..78db684 100644
--- a/README.hbs
+++ b/README.hbs
@@ -73,7 +73,7 @@ From a browser, you can just load the module in a html page as:
alert(p.toString() + '\nIs prime?\n' + isPrime);
// Get a cryptographically secure random number between 1 and 2**256 bits.
- const rnd = await bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256));
+ const rnd = bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256));
alert(rnd);
})();
diff --git a/README.md b/README.md
index 9fa5392..fd31d38 100644
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ From a browser, you can just load the module in a html page as:
alert(p.toString() + '\nIs prime?\n' + isPrime);
// Get a cryptographically secure random number between 1 and 2**256 bits.
- const rnd = await bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256));
+ const rnd = bigintCryptoUtils.randBetween(BigInt(2) ** BigInt(256));
alert(rnd);
})();
@@ -123,7 +123,10 @@ and can be enabled at runtime executing node --experimental-worker with node >
randBits(bitLength, forceLength) ⇒ Buffer
| Uint8Array
Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
-randBytes(byteLength, forceLength) ⇒ Buffer
| Uint8Array
+randBytes(byteLength, forceLength) ⇒ Promise
+Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
+
+randBytesSync(byteLength, forceLength) ⇒ Buffer
| Uint8Array
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
toZn(a, n) ⇒ bigint
@@ -288,7 +291,20 @@ Secure random bits for both node and browsers. Node version uses crypto.randomFi
-## randBytes(byteLength, forceLength) ⇒ Buffer
\| Uint8Array
+## randBytes(byteLength, forceLength) ⇒ Promise
+Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
+
+**Kind**: global function
+**Returns**: Promise
- A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+
+| Param | Type | Description |
+| --- | --- | --- |
+| byteLength | number
| The desired number of random bytes |
+| forceLength | boolean
| If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1 |
+
+
+
+## randBytesSync(byteLength, forceLength) ⇒ Buffer
\| Uint8Array
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
**Kind**: global function
diff --git a/dist/bigint-crypto-utils-latest.browser.js b/dist/bigint-crypto-utils-latest.browser.js
index 9af7d40..30afa49 100644
--- a/dist/bigint-crypto-utils-latest.browser.js
+++ b/dist/bigint-crypto-utils-latest.browser.js
@@ -25,6 +25,8 @@ var bigintCryptoUtils = (function (exports) {
* @returns {number} - the bit length
*/
function bitLength(a) {
+ if (a === _ONE)
+ return 1;
let bits = 1;
do {
bits++;
@@ -160,7 +162,7 @@ var bigintCryptoUtils = (function (exports) {
* @returns {bigint} the inverse modulo n
*/
function modInv(a, n) {
- let egcd = eGcd(a, n);
+ let egcd = eGcd(toZn(a,n), n);
if (egcd.b !== _ONE) {
return null; // modular inverse does not exist
} else {
@@ -287,7 +289,7 @@ var bigintCryptoUtils = (function (exports) {
*/
function randBits(bitLength, forceLength = false) {
const byteLength = Math.ceil(bitLength / 8);
- let rndBytes = randBytes(byteLength, false);
+ let rndBytes = randBytesSync(byteLength, false);
// Fill with 0's the extra birs
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
if (forceLength) {
@@ -303,9 +305,28 @@ var bigintCryptoUtils = (function (exports) {
* @param {number} byteLength The desired number of random bytes
* @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
- * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ * @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
function randBytes(byteLength, forceLength = false) {
+ let buf;
+ { // browser
+ return new Promise(function (resolve) {
+ buf = new Uint8Array(byteLength);
+ self.crypto.getRandomValues(buf);
+ resolve(buf);
+ });
+ }
+ }
+
+ /**
+ * Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
+ *
+ * @param {number} byteLength The desired number of random bytes
+ * @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
+ *
+ * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ */
+ function randBytesSync(byteLength, forceLength = false) {
let buf;
{ // browser
buf = new Uint8Array(byteLength);
@@ -345,7 +366,7 @@ var bigintCryptoUtils = (function (exports) {
function _isProbablyPrimeWorkerUrl() {
// Let's us first add all the required functions
- 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()}`;
+ let workerCode = `'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytesSync = ${randBytesSync.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;
const onmessage = async function (event) { // Let's start once we are called
// event.data = {rnd: , iterations: }
@@ -356,7 +377,7 @@ var bigintCryptoUtils = (function (exports) {
'id': event.data.id
});
};
-
+
workerCode += `onmessage = ${onmessage.toString()};`;
return _workerUrl(workerCode);
@@ -699,6 +720,7 @@ var bigintCryptoUtils = (function (exports) {
exports.randBetween = randBetween;
exports.randBits = randBits;
exports.randBytes = randBytes;
+ exports.randBytesSync = randBytesSync;
exports.toZn = toZn;
return exports;
diff --git a/dist/bigint-crypto-utils-latest.browser.min.js b/dist/bigint-crypto-utils-latest.browser.min.js
index ab98f8d..931b432 100644
--- a/dist/bigint-crypto-utils-latest.browser.min.js
+++ b/dist/bigint-crypto-utils-latest.browser.min.js
@@ -1 +1 @@
-var bigintCryptoUtils=function(a){'use strict';function c(b){return b=BigInt(b),b>=r?b:-b}function d(b){let c=1;do c++;while((b>>=s)>s);return c}function e(c,d){c=BigInt(c),d=BigInt(d);let e=r,f=s,g=s,h=r;for(;c!==r;){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 f(d,e){d=c(d),e=c(e);let f=r;for(;!((d|e)&s);)d>>=s,e>>=s,f++;for(;!(d&s);)d>>=s;do{for(;!(e&s);)e>>=s;if(d>e){let a=d;d=e,e=a}e-=d}while(e);return 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 h(b,a){let c=e(b,a);return c.b===s?m(c.x,a):null}function i(d,e,f){if(f=BigInt(f),d=m(d,f),e=BigInt(e),e min");const c=a-b;let e,f=d(c);do{let a=k(f);e=n(a)}while(e>c);return e+b}function k(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=l(d,!1);if(e[0]&=2**(a%8)-1,b){let b=a%8?2**(a%8-1):128;e[0]|=b}return e}function l(a,b=!1){let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function m(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}function n(a){let b=r;for(let c of a.values()){let a=BigInt(c);b=(b< {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}function q(c,b=16){if(c===t)return!0;if((c&s)===r||c===s)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{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;ae(a.data,b),d.push(b)}for(let e=0;e=r?b:-b}function d(b){if(b===s)return 1;let c=1;do c++;while((b>>=s)>s);return c}function e(c,d){c=BigInt(c),d=BigInt(d);let e=r,f=s,g=s,h=r;for(;c!==r;){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 f(d,e){d=c(d),e=c(e);let f=r;for(;!((d|e)&s);)d>>=s,e>>=s,f++;for(;!(d&s);)d>>=s;do{for(;!(e&s);)e>>=s;if(d>e){let a=d;d=e,e=a}e-=d}while(e);return 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 h(b,a){let c=e(m(b,a),a);return c.b===s?m(c.x,a):null}function i(d,e,f){if(f=BigInt(f),d=m(d,f),e=BigInt(e),e min");const c=a-b;let e,f=d(c);do{let a=k(f);e=n(a)}while(e>c);return e+b}function k(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=l(d,!1);if(e[0]&=2**(a%8)-1,b){let b=a%8?2**(a%8-1):128;e[0]|=b}return e}function l(a,b=!1){let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function m(b,c){return c=BigInt(c),b=BigInt(b)%c,0>b?b+c:b}function n(a){let b=r;for(let c of a.values()){let a=BigInt(c);b=(b< {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}function q(c,b=16){if(c===t)return!0;if((c&s)===r||c===s)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{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;ae(a.data,b),d.push(b)}for(let e=0;e, iterations: }
@@ -353,7 +374,7 @@ function _isProbablyPrimeWorkerUrl() {
'id': event.data.id
});
};
-
+
workerCode += `onmessage = ${onmessage.toString()};`;
return _workerUrl(workerCode);
@@ -684,4 +705,4 @@ function _isProbablyPrime(w, iterations = 16) {
return true;
}
-export { abs, bitLength, eGcd, gcd, isProbablyPrime, lcm, modInv, modPow, prime, randBetween, randBits, randBytes, toZn };
+export { abs, bitLength, eGcd, gcd, isProbablyPrime, lcm, modInv, modPow, prime, randBetween, randBits, randBytes, randBytesSync, toZn };
diff --git a/dist/bigint-crypto-utils-latest.browser.mod.min.js b/dist/bigint-crypto-utils-latest.browser.mod.min.js
index 921b928..55312e0 100644
--- a/dist/bigint-crypto-utils-latest.browser.mod.min.js
+++ b/dist/bigint-crypto-utils-latest.browser.mod.min.js
@@ -1 +1 @@
-const _ZERO=BigInt(0),_ONE=BigInt(1),_TWO=BigInt(2);function abs(b){return b=BigInt(b),b>=_ZERO?b:-b}function bitLength(b){let c=1;do c++;while((b>>=_ONE)>_ONE);return c}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<{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{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;ae(a.data,b),d.push(b)}for(let e=0;e min");const c=a-b;let d,e=bitLength(c);do{let a=randBits(e);d=fromBuffer(a)}while(d>c);return d+b}function randBits(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=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}function randBytes(a,b=!1){let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}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< {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}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=_ZERO?b:-b}function bitLength(b){if(b===_ONE)return 1;let c=1;do c++;while((b>>=_ONE)>_ONE);return c}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<{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(toZn(b,a),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{let d=[];const e=(e,f)=>{if(e.isPrime){for(let a=0;ae(a.data,b),d.push(b)}for(let e=0;e min");const c=a-b;let d,e=bitLength(c);do{let a=randBits(e);d=fromBuffer(a)}while(d>c);return d+b}function randBits(a,b=!1){var c=Math.ceil;const d=c(a/8);let e=randBytesSync(d,!1);if(e[0]&=2**(a%8)-1,b){let b=a%8?2**(a%8-1):128;e[0]|=b}return e}function randBytes(a,b=!1){let c;return new Promise(function(b){c=new Uint8Array(a),self.crypto.getRandomValues(c),b(c)})}function randBytesSync(a,b=!1){let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}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< {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}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 { resolve(rnd); });
}
@@ -302,7 +304,7 @@ function randBetween(max, min = _ONE) {
*/
function randBits(bitLength, forceLength = false) {
const byteLength = Math.ceil(bitLength / 8);
- let rndBytes = randBytes(byteLength, false);
+ let rndBytes = randBytesSync(byteLength, false);
// Fill with 0's the extra birs
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
if (forceLength) {
@@ -318,9 +320,31 @@ function randBits(bitLength, forceLength = false) {
* @param {number} byteLength The desired number of random bytes
* @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
- * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ * @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
function randBytes(byteLength, forceLength = false) {
+ let buf;
+ { // node
+ const crypto = require('crypto');
+ buf = Buffer.alloc(byteLength);
+ return crypto.randomFill(buf, function (resolve) {
+ // If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
+ if (forceLength)
+ buf[0] = buf[0] | 128;
+ resolve(buf);
+ });
+ }
+}
+
+/**
+ * Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
+ *
+ * @param {number} byteLength The desired number of random bytes
+ * @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
+ *
+ * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ */
+function randBytesSync(byteLength, forceLength = false) {
let buf;
{ // node
const crypto = require('crypto');
@@ -724,4 +748,5 @@ exports.prime = prime;
exports.randBetween = randBetween;
exports.randBits = randBits;
exports.randBytes = randBytes;
+exports.randBytesSync = randBytesSync;
exports.toZn = toZn;
diff --git a/src/main.js b/src/main.js
index f448e00..df13dc5 100644
--- a/src/main.js
+++ b/src/main.js
@@ -24,6 +24,8 @@ export function abs(a) {
* @returns {number} - the bit length
*/
export function bitLength(a) {
+ if (a === _ONE)
+ return 1;
let bits = 1;
do {
bits++;
@@ -184,7 +186,7 @@ export function lcm(a, b) {
* @returns {bigint} the inverse modulo n
*/
export function modInv(a, n) {
- let egcd = eGcd(a, n);
+ let egcd = eGcd(toZn(a,n), n);
if (egcd.b !== _ONE) {
return null; // modular inverse does not exist
} else {
@@ -239,7 +241,7 @@ export function prime(bitLength, iterations = 16) {
if (!process.browser && !_useWorkers) {
let rnd = _ZERO;
do {
- rnd = fromBuffer(randBytes(bitLength / 8, true));
+ rnd = fromBuffer(randBytesSync(bitLength / 8, true));
} while (!_isProbablyPrime(rnd, iterations));
return new Promise((resolve) => { resolve(rnd); });
}
@@ -326,7 +328,7 @@ export function randBetween(max, min = _ONE) {
*/
export function randBits(bitLength, forceLength = false) {
const byteLength = Math.ceil(bitLength / 8);
- let rndBytes = randBytes(byteLength, false);
+ let rndBytes = randBytesSync(byteLength, false);
// Fill with 0's the extra birs
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
if (forceLength) {
@@ -342,9 +344,37 @@ export function randBits(bitLength, forceLength = false) {
* @param {number} byteLength The desired number of random bytes
* @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
*
- * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ * @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
*/
export function randBytes(byteLength, forceLength = false) {
+ let buf;
+ if (!process.browser) { // node
+ const crypto = require('crypto');
+ buf = Buffer.alloc(byteLength);
+ return crypto.randomFill(buf, function (resolve) {
+ // If fixed length is required we put the first bit to 1 -> to get the necessary bitLength
+ if (forceLength)
+ buf[0] = buf[0] | 128;
+ resolve(buf);
+ });
+ } else { // browser
+ return new Promise(function (resolve) {
+ buf = new Uint8Array(byteLength);
+ self.crypto.getRandomValues(buf);
+ resolve(buf);
+ });
+ }
+}
+
+/**
+ * Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
+ *
+ * @param {number} byteLength The desired number of random bytes
+ * @param {boolean} forceLength If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1
+ *
+ * @returns {Buffer|Uint8Array} A Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
+ */
+export function randBytesSync(byteLength, forceLength = false) {
let buf;
if (!process.browser) { // node
const crypto = require('crypto');
@@ -388,7 +418,7 @@ function fromBuffer(buf) {
function _isProbablyPrimeWorkerUrl() {
// Let's us first add all the required functions
- 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()}`;
+ let workerCode = `'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${eGcd.toString()};const modInv = ${modInv.toString()};const modPow = ${modPow.toString()};const toZn = ${toZn.toString()};const randBits = ${randBits.toString()};const randBytesSync = ${randBytesSync.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;
const onmessage = async function (event) { // Let's start once we are called
// event.data = {rnd: , iterations: }
@@ -399,7 +429,7 @@ function _isProbablyPrimeWorkerUrl() {
'id': event.data.id
});
};
-
+
workerCode += `onmessage = ${onmessage.toString()};`;
return _workerUrl(workerCode);
diff --git a/test/abs.js b/test/abs.js
new file mode 100644
index 0000000..eec1ad3
--- /dev/null
+++ b/test/abs.js
@@ -0,0 +1,37 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ value: BigInt(1),
+ abs: BigInt(1)
+ },
+ {
+ value: BigInt(-2),
+ abs: BigInt(2)
+ },
+ {
+ value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
+ abs: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
+ },
+ {
+ value: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
+ abs: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
+ }
+];
+
+describe('abs', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`abs(${input.value})`, function () {
+ it(`should return ${input.abs}`, function () {
+ ret = bigintCryptoUtils.abs(input.value);
+ chai.expect(ret).to.equal(input.abs);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/bitLength.js b/test/bitLength.js
new file mode 100644
index 0000000..4edde04
--- /dev/null
+++ b/test/bitLength.js
@@ -0,0 +1,34 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ value: BigInt(1),
+ bitLength: 1
+ },
+ {
+ value: BigInt(-2),
+ bitLength: 2
+ },
+ {
+ value: BigInt(11592217955149597331),
+ abs: BigInt(11592217955149597331),
+ bitLength: 64
+ }
+];
+
+describe('bitLength', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`bitLength(${input.value})`, function () {
+ it(`should return ${input.bitLength}`, function () {
+ ret = bigintCryptoUtils.bitLength(input.value);
+ chai.expect(ret).to.equal(input.bitLength);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/browser/tests.js b/test/browser/tests.js
index 9851ee2..4963374 100644
--- a/test/browser/tests.js
+++ b/test/browser/tests.js
@@ -3,6 +3,120 @@
+const inputs = [
+ {
+ value: BigInt(1),
+ abs: BigInt(1)
+ },
+ {
+ value: BigInt(-2),
+ abs: BigInt(2)
+ },
+ {
+ value: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777'),
+ abs: BigInt('115922179551495973383410176342643722334557255682879605864838806293659619625004303206250384392546855063844106965156287951749387634112551089284595541103692716528774876311641700929986988023197242224581099872580798960693521778607396791006450968430359009613295725905514216842343121690916290236558767890728449777')
+ },
+ {
+ value: BigInt('-918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203'),
+ abs: BigInt('918145944120889203205646923554374144932845997937845799234617798611046542304088105084854788397071323714642587188481158334265864050544813693415594035822877094557870151480865568334936301231664228940480803192289508235412296324312748621874408067955753620604885023289655277704554716080844406284392300643321715285709865081125252390440327650852470312931679380011885102491340191287595160450544053114365852338670819405357496612993587404998677760882578064637552397840566752638770525765833183986360029736508910848408875329873614164495552615086579144675027852136994842529623698055210822311666048300438808691619782893307972452223713060928388502843564836966586109748062827799521852219158489504529458627699284110902303538160168376473182639384638674469114371472053977558648090155686345760457454061117853710619580819749222459422610617170567016772342291486643520567969321969827786373531753524990712622940069883277763528926899970596407140603912036918433859986491820017690762751824769335720368488097262208835708414085501930989486498185503469986946236128468697606998536541209764920494156326791142098506801288127033229779646920082892258428128572765585196779698362187479280520327053508580551167899837393726371144977951402741307021389967382422805567365901203')
+ }
+];
+
+describe('abs', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`abs(${input.value})`, function () {
+ it(`should return ${input.abs}`, function () {
+ ret = bigintCryptoUtils.abs(input.value);
+ chai.expect(ret).to.equal(input.abs);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
+const inputs$1 = [
+ {
+ value: BigInt(1),
+ bitLength: 1
+ },
+ {
+ value: BigInt(-2),
+ bitLength: 2
+ },
+ {
+ value: BigInt(11592217955149597331),
+ abs: BigInt(11592217955149597331),
+ bitLength: 64
+ }
+];
+
+describe('bitLength', function () {
+ for (const input of inputs$1) {
+ let ret;
+ describe(`bitLength(${input.value})`, function () {
+ it(`should return ${input.bitLength}`, function () {
+ ret = bigintCryptoUtils.bitLength(input.value);
+ chai.expect(ret).to.equal(input.bitLength);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
+const inputs$2 = [
+ {
+ a: BigInt(1),
+ b: BigInt(1),
+ gcd: BigInt(1)
+ },
+ {
+ a: BigInt(1),
+ b: BigInt('14546149867129487614601346814'),
+ gcd: BigInt(1)
+ },
+ {
+ a: BigInt(27),
+ b: BigInt(18),
+ gcd: BigInt(9)
+ },
+ {
+ a: BigInt(-27),
+ b: BigInt(18),
+ gcd: BigInt(9)
+ },
+ {
+ a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
+ b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ gcd: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109')
+ }
+];
+
+describe('gcd', function () {
+ for (const input of inputs$2) {
+ let ret;
+ describe(`gcd(${input.a}, ${input.b})`, function () {
+ it(`should return ${input.gcd}`, function () {
+ ret = bigintCryptoUtils.gcd(input.a, input.b);
+ chai.expect(ret).to.equal(input.gcd);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
const numbers = [
{
value: BigInt(1),
@@ -54,7 +168,7 @@ const numbers = [
}
];
-describe('Testing validation of prime numbers', function () {
+describe('isProbablyPrime', function () {
for (const num of numbers) {
describe(`isProbablyPrime(${num.value})`, function () {
it(`should return ${num.prime}`, async function () {
@@ -70,6 +184,130 @@ describe('Testing validation of prime numbers', function () {
+const inputs$3 = [
+ {
+ a: BigInt(1),
+ b: BigInt(1),
+ lcm: BigInt(1)
+ },
+ {
+ a: BigInt(1),
+ b: BigInt('14546149867129487614601346814'),
+ lcm: BigInt('14546149867129487614601346814')
+ },
+ {
+ a: BigInt(27),
+ b: BigInt(18),
+ lcm: BigInt(27) * BigInt(2)
+ },
+ {
+ a: BigInt(-27),
+ b: BigInt(18),
+ lcm: BigInt(27) * BigInt(2)
+ },
+ {
+ a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
+ b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ lcm: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ }
+];
+
+describe('lcm', function () {
+ for (const input of inputs$3) {
+ let ret;
+ describe(`lcm(${input.a}, ${input.b})`, function () {
+ it(`should return ${input.lcm}`, function () {
+ ret = bigintCryptoUtils.lcm(input.a, input.b);
+ chai.expect(ret).to.equal(input.lcm);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
+const inputs$4 = [
+ {
+ a: BigInt(1),
+ n: BigInt(19),
+ modInv: BigInt(1)
+ },
+ {
+ a: BigInt(2),
+ n: BigInt(5),
+ modInv: BigInt(3)
+ },
+ {
+ a: BigInt(-2),
+ n: BigInt(5),
+ modInv: BigInt(2)
+ }
+];
+
+describe('modInv', function () {
+ for (const input of inputs$4) {
+ let ret;
+ describe(`modInv(${input.a}, ${input.n})`, function () {
+ it(`should return ${input.modInv}`, function () {
+ ret = bigintCryptoUtils.modInv(input.a, input.n);
+ chai.expect(ret).to.equal(input.modInv);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
+const inputs$5 = [
+ {
+ a: BigInt(4),
+ b: BigInt(-1),
+ n: BigInt(19),
+ modPow: BigInt(5)
+ },
+ {
+ a: BigInt(-5),
+ b: BigInt(2),
+ n: BigInt(7),
+ modPow: BigInt(4)
+ },
+ {
+ a: BigInt(2),
+ b: BigInt(255),
+ n: BigInt(64),
+ modPow: BigInt(0)
+ },
+ {
+ a: BigInt(3),
+ b: BigInt(3),
+ n: BigInt(25),
+ modPow: BigInt(2)
+ }
+];
+
+describe('modPow', function () {
+ for (const input of inputs$5) {
+ let ret;
+ describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
+ it(`should return ${input.modPow}`, function () {
+ ret = bigintCryptoUtils.modPow(input.a, input.b, input.n);
+ chai.expect(ret).to.equal(input.modPow);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
const bitLengths = [
1024,
2048,
@@ -77,16 +315,48 @@ const bitLengths = [
4096
];
-describe('Testing generation of prime numbers', function () {
+describe('prime', function () {
for (const bitLength of bitLengths) {
- describe(`Executing prime(${bitLength})`, function () {
+ describe(`prime(${bitLength})`, function () {
it(`should return a random ${bitLength}-bits probable prime`, async function () {
let prime = await bigintCryptoUtils.prime(bitLength);
- let bits = 1;
- do {
- bits++;
- } while ((prime >>= BigInt(1)) > BigInt(1));
- chai.expect(bits).to.equal(bitLength);
+ let primeBitLength = bigintCryptoUtils.bitLength(prime);
+ chai.expect(primeBitLength).to.equal(bitLength);
+ });
+ });
+ }
+});
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+
+
+
+const inputs$6 = [
+ {
+ a: BigInt(1),
+ n: BigInt(19),
+ toZn: BigInt(1)
+ },
+ {
+ a: BigInt(-25),
+ n: BigInt(9),
+ toZn: BigInt(2)
+ },
+ {
+ a: BigInt('12359782465012847510249'),
+ n: BigInt(5),
+ toZn: BigInt(4)
+ }
+];
+
+describe('toZn', function () {
+ for (const input of inputs$6) {
+ let ret;
+ describe(`toZn(${input.a}, ${input.n})`, function () {
+ it(`should return ${input.toZn}`, function () {
+ ret = bigintCryptoUtils.toZn(input.a, input.n);
+ chai.expect(ret).to.equal(input.toZn);
});
});
}
diff --git a/test/gcd.js b/test/gcd.js
new file mode 100644
index 0000000..7657e2c
--- /dev/null
+++ b/test/gcd.js
@@ -0,0 +1,46 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ a: BigInt(1),
+ b: BigInt(1),
+ gcd: BigInt(1)
+ },
+ {
+ a: BigInt(1),
+ b: BigInt('14546149867129487614601346814'),
+ gcd: BigInt(1)
+ },
+ {
+ a: BigInt(27),
+ b: BigInt(18),
+ gcd: BigInt(9)
+ },
+ {
+ a: BigInt(-27),
+ b: BigInt(18),
+ gcd: BigInt(9)
+ },
+ {
+ a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
+ b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ gcd: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109')
+ }
+];
+
+describe('gcd', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`gcd(${input.a}, ${input.b})`, function () {
+ it(`should return ${input.gcd}`, function () {
+ ret = bigintCryptoUtils.gcd(input.a, input.b);
+ chai.expect(ret).to.equal(input.gcd);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/01_PrimeValidation.js b/test/isProbablyPrime.js
similarity index 98%
rename from test/01_PrimeValidation.js
rename to test/isProbablyPrime.js
index 08cb852..a64eaae 100644
--- a/test/01_PrimeValidation.js
+++ b/test/isProbablyPrime.js
@@ -56,7 +56,7 @@ const numbers = [
}
];
-describe('Testing validation of prime numbers', function () {
+describe('isProbablyPrime', function () {
for (const num of numbers) {
describe(`isProbablyPrime(${num.value})`, function () {
it(`should return ${num.prime}`, async function () {
diff --git a/test/lcm.js b/test/lcm.js
new file mode 100644
index 0000000..84f15d9
--- /dev/null
+++ b/test/lcm.js
@@ -0,0 +1,46 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ a: BigInt(1),
+ b: BigInt(1),
+ lcm: BigInt(1)
+ },
+ {
+ a: BigInt(1),
+ b: BigInt('14546149867129487614601346814'),
+ lcm: BigInt('14546149867129487614601346814')
+ },
+ {
+ a: BigInt(27),
+ b: BigInt(18),
+ lcm: BigInt(27) * BigInt(2)
+ },
+ {
+ a: BigInt(-27),
+ b: BigInt(18),
+ lcm: BigInt(27) * BigInt(2)
+ },
+ {
+ a: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109'),
+ b: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ lcm: BigInt('168694196579467171180863939518634764192343817610869919231900537093664715354591592262546800497540343203057121816378265655992490621138321114570420047522219942818258345349322155251835677199539229050711145144861404607171419723967136221126986330819362088262358855325306938646602003059377699727688477555163239222109') * BigInt('144678545212641449725111562354371812236197961234111744040227045242578772124779004756249085154188369039159690638725821245974978963371615699005072473649705367893567309027634121825164880046600125480885803891136149601797439273507802533807541605261215613891134865916295914192271736572001975016089773532547481638243'),
+ }
+];
+
+describe('lcm', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`lcm(${input.a}, ${input.b})`, function () {
+ it(`should return ${input.lcm}`, function () {
+ ret = bigintCryptoUtils.lcm(input.a, input.b);
+ chai.expect(ret).to.equal(input.lcm);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/modInv.js b/test/modInv.js
new file mode 100644
index 0000000..6437170
--- /dev/null
+++ b/test/modInv.js
@@ -0,0 +1,36 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ a: BigInt(1),
+ n: BigInt(19),
+ modInv: BigInt(1)
+ },
+ {
+ a: BigInt(2),
+ n: BigInt(5),
+ modInv: BigInt(3)
+ },
+ {
+ a: BigInt(-2),
+ n: BigInt(5),
+ modInv: BigInt(2)
+ }
+];
+
+describe('modInv', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`modInv(${input.a}, ${input.n})`, function () {
+ it(`should return ${input.modInv}`, function () {
+ ret = bigintCryptoUtils.modInv(input.a, input.n);
+ chai.expect(ret).to.equal(input.modInv);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/modPow.js b/test/modPow.js
new file mode 100644
index 0000000..8b5d92f
--- /dev/null
+++ b/test/modPow.js
@@ -0,0 +1,45 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ a: BigInt(4),
+ b: BigInt(-1),
+ n: BigInt(19),
+ modPow: BigInt(5)
+ },
+ {
+ a: BigInt(-5),
+ b: BigInt(2),
+ n: BigInt(7),
+ modPow: BigInt(4)
+ },
+ {
+ a: BigInt(2),
+ b: BigInt(255),
+ n: BigInt(64),
+ modPow: BigInt(0)
+ },
+ {
+ a: BigInt(3),
+ b: BigInt(3),
+ n: BigInt(25),
+ modPow: BigInt(2)
+ }
+];
+
+describe('modPow', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`modPow(${input.a}, ${input.b}, ${input.n})`, function () {
+ it(`should return ${input.modPow}`, function () {
+ ret = bigintCryptoUtils.modPow(input.a, input.b, input.n);
+ chai.expect(ret).to.equal(input.modPow);
+ });
+ });
+ }
+});
\ No newline at end of file
diff --git a/test/02_PrimeGeneration.js b/test/prime.js
similarity index 63%
rename from test/02_PrimeGeneration.js
rename to test/prime.js
index be8f07a..58c58b4 100644
--- a/test/02_PrimeGeneration.js
+++ b/test/prime.js
@@ -12,16 +12,13 @@ const bitLengths = [
4096
];
-describe('Testing generation of prime numbers', function () {
+describe('prime', function () {
for (const bitLength of bitLengths) {
- describe(`Executing prime(${bitLength})`, function () {
+ describe(`prime(${bitLength})`, function () {
it(`should return a random ${bitLength}-bits probable prime`, async function () {
let prime = await bigintCryptoUtils.prime(bitLength);
- let bits = 1;
- do {
- bits++;
- } while ((prime >>= BigInt(1)) > BigInt(1));
- chai.expect(bits).to.equal(bitLength);
+ let primeBitLength = bigintCryptoUtils.bitLength(prime);
+ chai.expect(primeBitLength).to.equal(bitLength);
});
});
}
diff --git a/test/toZn.js b/test/toZn.js
new file mode 100644
index 0000000..cf5234c
--- /dev/null
+++ b/test/toZn.js
@@ -0,0 +1,36 @@
+'use strict';
+
+// For the browser test builder to work you MUST import them module in a variable that
+// is the camelised version of the package name.
+const bigintCryptoUtils = require('../dist/bigint-crypto-utils-latest.node');
+const chai = require('chai');
+
+const inputs = [
+ {
+ a: BigInt(1),
+ n: BigInt(19),
+ toZn: BigInt(1)
+ },
+ {
+ a: BigInt(-25),
+ n: BigInt(9),
+ toZn: BigInt(2)
+ },
+ {
+ a: BigInt('12359782465012847510249'),
+ n: BigInt(5),
+ toZn: BigInt(4)
+ }
+];
+
+describe('toZn', function () {
+ for (const input of inputs) {
+ let ret;
+ describe(`toZn(${input.a}, ${input.n})`, function () {
+ it(`should return ${input.toZn}`, function () {
+ ret = bigintCryptoUtils.toZn(input.a, input.n);
+ chai.expect(ret).to.equal(input.toZn);
+ });
+ });
+ }
+});
\ No newline at end of file