More tests. Fixed bug in modInv(a,n) when a was < 0
This commit is contained in:
parent
fb3dd95190
commit
1ffd1f949d
|
@ -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);
|
alert(p.toString() + '\nIs prime?\n' + isPrime);
|
||||||
|
|
||||||
// Get a cryptographically secure random number between 1 and 2**256 bits.
|
// 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);
|
alert(rnd);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
22
README.md
22
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);
|
alert(p.toString() + '\nIs prime?\n' + isPrime);
|
||||||
|
|
||||||
// Get a cryptographically secure random number between 1 and 2**256 bits.
|
// 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);
|
alert(rnd);
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
@ -123,7 +123,10 @@ and can be enabled at runtime executing node --experimental-worker with node >
|
||||||
<dt><a href="#randBits">randBits(bitLength, forceLength)</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
<dt><a href="#randBits">randBits(bitLength, forceLength)</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
||||||
<dd><p>Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
<dd><p>Secure random bits for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="#randBytes">randBytes(byteLength, forceLength)</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
<dt><a href="#randBytes">randBytes(byteLength, forceLength)</a> ⇒ <code>Promise</code></dt>
|
||||||
|
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
||||||
|
</dd>
|
||||||
|
<dt><a href="#randBytesSync">randBytesSync(byteLength, forceLength)</a> ⇒ <code>Buffer</code> | <code>Uint8Array</code></dt>
|
||||||
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
<dd><p>Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()</p>
|
||||||
</dd>
|
</dd>
|
||||||
<dt><a href="#toZn">toZn(a, n)</a> ⇒ <code>bigint</code></dt>
|
<dt><a href="#toZn">toZn(a, n)</a> ⇒ <code>bigint</code></dt>
|
||||||
|
@ -288,7 +291,20 @@ Secure random bits for both node and browsers. Node version uses crypto.randomFi
|
||||||
|
|
||||||
<a name="randBytes"></a>
|
<a name="randBytes"></a>
|
||||||
|
|
||||||
## randBytes(byteLength, forceLength) ⇒ <code>Buffer</code> \| <code>Uint8Array</code>
|
## randBytes(byteLength, forceLength) ⇒ <code>Promise</code>
|
||||||
|
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
||||||
|
|
||||||
|
**Kind**: global function
|
||||||
|
**Returns**: <code>Promise</code> - A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes
|
||||||
|
|
||||||
|
| Param | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| byteLength | <code>number</code> | The desired number of random bytes |
|
||||||
|
| forceLength | <code>boolean</code> | If we want to force the output to have a bit length of 8*byteLength. It basically forces the msb to be 1 |
|
||||||
|
|
||||||
|
<a name="randBytesSync"></a>
|
||||||
|
|
||||||
|
## randBytesSync(byteLength, forceLength) ⇒ <code>Buffer</code> \| <code>Uint8Array</code>
|
||||||
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
Secure random bytes for both node and browsers. Node version uses crypto.randomFill() and browser one self.crypto.getRandomValues()
|
||||||
|
|
||||||
**Kind**: global function
|
**Kind**: global function
|
||||||
|
|
|
@ -25,6 +25,8 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
* @returns {number} - the bit length
|
* @returns {number} - the bit length
|
||||||
*/
|
*/
|
||||||
function bitLength(a) {
|
function bitLength(a) {
|
||||||
|
if (a === _ONE)
|
||||||
|
return 1;
|
||||||
let bits = 1;
|
let bits = 1;
|
||||||
do {
|
do {
|
||||||
bits++;
|
bits++;
|
||||||
|
@ -160,7 +162,7 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
* @returns {bigint} the inverse modulo n
|
* @returns {bigint} the inverse modulo n
|
||||||
*/
|
*/
|
||||||
function modInv(a, n) {
|
function modInv(a, n) {
|
||||||
let egcd = eGcd(a, n);
|
let egcd = eGcd(toZn(a,n), n);
|
||||||
if (egcd.b !== _ONE) {
|
if (egcd.b !== _ONE) {
|
||||||
return null; // modular inverse does not exist
|
return null; // modular inverse does not exist
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,7 +289,7 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
*/
|
*/
|
||||||
function randBits(bitLength, forceLength = false) {
|
function randBits(bitLength, forceLength = false) {
|
||||||
const byteLength = Math.ceil(bitLength / 8);
|
const byteLength = Math.ceil(bitLength / 8);
|
||||||
let rndBytes = randBytes(byteLength, false);
|
let rndBytes = randBytesSync(byteLength, false);
|
||||||
// Fill with 0's the extra birs
|
// Fill with 0's the extra birs
|
||||||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
||||||
if (forceLength) {
|
if (forceLength) {
|
||||||
|
@ -303,9 +305,28 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @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
|
* @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) {
|
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;
|
let buf;
|
||||||
{ // browser
|
{ // browser
|
||||||
buf = new Uint8Array(byteLength);
|
buf = new Uint8Array(byteLength);
|
||||||
|
@ -345,7 +366,7 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
|
|
||||||
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 _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
|
const onmessage = async function (event) { // Let's start once we are called
|
||||||
// event.data = {rnd: <bigint>, iterations: <number>}
|
// event.data = {rnd: <bigint>, iterations: <number>}
|
||||||
|
@ -699,6 +720,7 @@ var bigintCryptoUtils = (function (exports) {
|
||||||
exports.randBetween = randBetween;
|
exports.randBetween = randBetween;
|
||||||
exports.randBits = randBits;
|
exports.randBits = randBits;
|
||||||
exports.randBytes = randBytes;
|
exports.randBytes = randBytes;
|
||||||
|
exports.randBytesSync = randBytesSync;
|
||||||
exports.toZn = toZn;
|
exports.toZn = toZn;
|
||||||
|
|
||||||
return exports;
|
return exports;
|
||||||
|
|
|
@ -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<<f}async function g(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 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<r)return h(i(d,c(e),f),f);let g=s,j=d;for(;0<e;){var k=e%t;e/=t,k==s&&(g*=j,g%=f),j*=j,j%=f}return g}function j(a,b=s){if(a<=b)throw new Error("max must be > 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<<BigInt(8))+a}return b}function o(){let a=`'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${e.toString()};const modInv = ${h.toString()};const modPow = ${i.toString()};const toZn = ${m.toString()};const randBits = ${k.toString()};const randBytes = ${l.toString()};const randBetween = ${j.toString()};const isProbablyPrime = ${q.toString()};${d.toString()}${n.toString()}`;return a+=`onmessage = ${async function(a){const b=await g(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd,id:a.data.id})}.toString()};`,p(a)}function p(a){a=`(() => {${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<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===r)return!1}let f=r,g=c-s;for(;g%t===r;)g/=t,++f;let h=(c-s)/t**f;loop:do{let a=j(c-s,t),b=i(a,h,c);if(b===s||b===c-s)continue;for(let a=1;a<f;a++){if(b=i(b,t,c),b===c-s)continue loop;if(b===s)break}return!1}while(--b);return!0}const r=BigInt(0),s=BigInt(1),t=BigInt(2);return a.abs=c,a.bitLength=d,a.eGcd=e,a.gcd=f,a.isProbablyPrime=g,a.lcm=function(d,e){return d=BigInt(d),e=BigInt(e),c(d*e)/f(d,e)},a.modInv=h,a.modPow=i,a.prime=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{let c=k(a,!0),d=n(c);try{f.postMessage({rnd:d,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++){let c=k(a,!0),f=n(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})},a.randBetween=j,a.randBits=k,a.randBytes=l,a.toZn=m,a}({});
|
var bigintCryptoUtils=function(a){'use strict';function c(b){return b=BigInt(b),b>=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<<f}async function g(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 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<r)return h(i(d,c(e),f),f);let g=s,j=d;for(;0<e;){var k=e%t;e/=t,k==s&&(g*=j,g%=f),j*=j,j%=f}return g}function j(a,b=s){if(a<=b)throw new Error("max must be > 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<<BigInt(8))+a}return b}function o(){let a=`'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${e.toString()};const modInv = ${h.toString()};const modPow = ${i.toString()};const toZn = ${m.toString()};const randBits = ${k.toString()};const randBytesSync = ${l.toString()};const randBetween = ${j.toString()};const isProbablyPrime = ${q.toString()};${d.toString()}${n.toString()}`;return a+=`onmessage = ${async function(a){const b=await g(a.data.rnd,a.data.iterations);postMessage({isPrime:b,value:a.data.rnd,id:a.data.id})}.toString()};`,p(a)}function p(a){a=`(() => {${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<e.length&&BigInt(e[a])<=c;a++){const b=BigInt(e[a]);if(c===b)return!0;if(c%b===r)return!1}let f=r,g=c-s;for(;g%t===r;)g/=t,++f;let h=(c-s)/t**f;loop:do{let a=j(c-s,t),b=i(a,h,c);if(b===s||b===c-s)continue;for(let a=1;a<f;a++){if(b=i(b,t,c),b===c-s)continue loop;if(b===s)break}return!1}while(--b);return!0}const r=BigInt(0),s=BigInt(1),t=BigInt(2);return a.abs=c,a.bitLength=d,a.eGcd=e,a.gcd=f,a.isProbablyPrime=g,a.lcm=function(d,e){return d=BigInt(d),e=BigInt(e),c(d*e)/f(d,e)},a.modInv=h,a.modPow=i,a.prime=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{let c=k(a,!0),d=n(c);try{f.postMessage({rnd:d,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++){let c=k(a,!0),f=n(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})},a.randBetween=j,a.randBits=k,a.randBytes=function(a,b=!1){let c;return new Promise(function(b){c=new Uint8Array(a),self.crypto.getRandomValues(c),b(c)})},a.randBytesSync=l,a.toZn=m,a}({});
|
||||||
|
|
|
@ -22,6 +22,8 @@ function abs(a) {
|
||||||
* @returns {number} - the bit length
|
* @returns {number} - the bit length
|
||||||
*/
|
*/
|
||||||
function bitLength(a) {
|
function bitLength(a) {
|
||||||
|
if (a === _ONE)
|
||||||
|
return 1;
|
||||||
let bits = 1;
|
let bits = 1;
|
||||||
do {
|
do {
|
||||||
bits++;
|
bits++;
|
||||||
|
@ -157,7 +159,7 @@ function lcm(a, b) {
|
||||||
* @returns {bigint} the inverse modulo n
|
* @returns {bigint} the inverse modulo n
|
||||||
*/
|
*/
|
||||||
function modInv(a, n) {
|
function modInv(a, n) {
|
||||||
let egcd = eGcd(a, n);
|
let egcd = eGcd(toZn(a,n), n);
|
||||||
if (egcd.b !== _ONE) {
|
if (egcd.b !== _ONE) {
|
||||||
return null; // modular inverse does not exist
|
return null; // modular inverse does not exist
|
||||||
} else {
|
} else {
|
||||||
|
@ -284,7 +286,7 @@ function randBetween(max, min = _ONE) {
|
||||||
*/
|
*/
|
||||||
function randBits(bitLength, forceLength = false) {
|
function randBits(bitLength, forceLength = false) {
|
||||||
const byteLength = Math.ceil(bitLength / 8);
|
const byteLength = Math.ceil(bitLength / 8);
|
||||||
let rndBytes = randBytes(byteLength, false);
|
let rndBytes = randBytesSync(byteLength, false);
|
||||||
// Fill with 0's the extra birs
|
// Fill with 0's the extra birs
|
||||||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
||||||
if (forceLength) {
|
if (forceLength) {
|
||||||
|
@ -300,9 +302,28 @@ function randBits(bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @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
|
* @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) {
|
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;
|
let buf;
|
||||||
{ // browser
|
{ // browser
|
||||||
buf = new Uint8Array(byteLength);
|
buf = new Uint8Array(byteLength);
|
||||||
|
@ -342,7 +363,7 @@ function fromBuffer(buf) {
|
||||||
|
|
||||||
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 _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
|
const onmessage = async function (event) { // Let's start once we are called
|
||||||
// event.data = {rnd: <bigint>, iterations: <number>}
|
// event.data = {rnd: <bigint>, iterations: <number>}
|
||||||
|
@ -684,4 +705,4 @@ function _isProbablyPrime(w, iterations = 16) {
|
||||||
return true;
|
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 };
|
||||||
|
|
|
@ -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<<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}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{let c=randBits(a,!0),d=fromBuffer(c);try{f.postMessage({rnd:d,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++){let c=randBits(a,!0),f=fromBuffer(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})}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=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<<BigInt(8))+a}return b}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()}`;return 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()};`,_workerUrl(a)}function _workerUrl(a){a=`(() => {${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<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=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}export{abs,bitLength,eGcd,gcd,isProbablyPrime,lcm,modInv,modPow,prime,randBetween,randBits,randBytes,toZn};
|
const _ZERO=BigInt(0),_ONE=BigInt(1),_TWO=BigInt(2);function abs(b){return b=BigInt(b),b>=_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<<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(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<d;){var h=d%_TWO;d/=_TWO,h==_ONE&&(f*=g,f%=e),g*=g,g%=e}return f}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{let c=randBits(a,!0),d=fromBuffer(c);try{f.postMessage({rnd:d,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++){let c=randBits(a,!0),f=fromBuffer(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})}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=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<<BigInt(8))+a}return b}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 randBytesSync = ${randBytesSync.toString()};const randBetween = ${randBetween.toString()};const isProbablyPrime = ${_isProbablyPrime.toString()};${bitLength.toString()}${fromBuffer.toString()}`;return 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()};`,_workerUrl(a)}function _workerUrl(a){a=`(() => {${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<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=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}export{abs,bitLength,eGcd,gcd,isProbablyPrime,lcm,modInv,modPow,prime,randBetween,randBits,randBytes,randBytesSync,toZn};
|
||||||
|
|
|
@ -26,6 +26,8 @@ function abs(a) {
|
||||||
* @returns {number} - the bit length
|
* @returns {number} - the bit length
|
||||||
*/
|
*/
|
||||||
function bitLength(a) {
|
function bitLength(a) {
|
||||||
|
if (a === _ONE)
|
||||||
|
return 1;
|
||||||
let bits = 1;
|
let bits = 1;
|
||||||
do {
|
do {
|
||||||
bits++;
|
bits++;
|
||||||
|
@ -167,7 +169,7 @@ function lcm(a, b) {
|
||||||
* @returns {bigint} the inverse modulo n
|
* @returns {bigint} the inverse modulo n
|
||||||
*/
|
*/
|
||||||
function modInv(a, n) {
|
function modInv(a, n) {
|
||||||
let egcd = eGcd(a, n);
|
let egcd = eGcd(toZn(a,n), n);
|
||||||
if (egcd.b !== _ONE) {
|
if (egcd.b !== _ONE) {
|
||||||
return null; // modular inverse does not exist
|
return null; // modular inverse does not exist
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,7 +224,7 @@ function prime(bitLength, iterations = 16) {
|
||||||
if (!_useWorkers) {
|
if (!_useWorkers) {
|
||||||
let rnd = _ZERO;
|
let rnd = _ZERO;
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytes(bitLength / 8, true));
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true));
|
||||||
} while (!_isProbablyPrime(rnd, iterations));
|
} while (!_isProbablyPrime(rnd, iterations));
|
||||||
return new Promise((resolve) => { resolve(rnd); });
|
return new Promise((resolve) => { resolve(rnd); });
|
||||||
}
|
}
|
||||||
|
@ -302,7 +304,7 @@ function randBetween(max, min = _ONE) {
|
||||||
*/
|
*/
|
||||||
function randBits(bitLength, forceLength = false) {
|
function randBits(bitLength, forceLength = false) {
|
||||||
const byteLength = Math.ceil(bitLength / 8);
|
const byteLength = Math.ceil(bitLength / 8);
|
||||||
let rndBytes = randBytes(byteLength, false);
|
let rndBytes = randBytesSync(byteLength, false);
|
||||||
// Fill with 0's the extra birs
|
// Fill with 0's the extra birs
|
||||||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
||||||
if (forceLength) {
|
if (forceLength) {
|
||||||
|
@ -318,9 +320,31 @@ function randBits(bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @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
|
* @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) {
|
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;
|
let buf;
|
||||||
{ // node
|
{ // node
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
@ -724,4 +748,5 @@ exports.prime = prime;
|
||||||
exports.randBetween = randBetween;
|
exports.randBetween = randBetween;
|
||||||
exports.randBits = randBits;
|
exports.randBits = randBits;
|
||||||
exports.randBytes = randBytes;
|
exports.randBytes = randBytes;
|
||||||
|
exports.randBytesSync = randBytesSync;
|
||||||
exports.toZn = toZn;
|
exports.toZn = toZn;
|
||||||
|
|
40
src/main.js
40
src/main.js
|
@ -24,6 +24,8 @@ export function abs(a) {
|
||||||
* @returns {number} - the bit length
|
* @returns {number} - the bit length
|
||||||
*/
|
*/
|
||||||
export function bitLength(a) {
|
export function bitLength(a) {
|
||||||
|
if (a === _ONE)
|
||||||
|
return 1;
|
||||||
let bits = 1;
|
let bits = 1;
|
||||||
do {
|
do {
|
||||||
bits++;
|
bits++;
|
||||||
|
@ -184,7 +186,7 @@ export function lcm(a, b) {
|
||||||
* @returns {bigint} the inverse modulo n
|
* @returns {bigint} the inverse modulo n
|
||||||
*/
|
*/
|
||||||
export function modInv(a, n) {
|
export function modInv(a, n) {
|
||||||
let egcd = eGcd(a, n);
|
let egcd = eGcd(toZn(a,n), n);
|
||||||
if (egcd.b !== _ONE) {
|
if (egcd.b !== _ONE) {
|
||||||
return null; // modular inverse does not exist
|
return null; // modular inverse does not exist
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,7 +241,7 @@ export function prime(bitLength, iterations = 16) {
|
||||||
if (!process.browser && !_useWorkers) {
|
if (!process.browser && !_useWorkers) {
|
||||||
let rnd = _ZERO;
|
let rnd = _ZERO;
|
||||||
do {
|
do {
|
||||||
rnd = fromBuffer(randBytes(bitLength / 8, true));
|
rnd = fromBuffer(randBytesSync(bitLength / 8, true));
|
||||||
} while (!_isProbablyPrime(rnd, iterations));
|
} while (!_isProbablyPrime(rnd, iterations));
|
||||||
return new Promise((resolve) => { resolve(rnd); });
|
return new Promise((resolve) => { resolve(rnd); });
|
||||||
}
|
}
|
||||||
|
@ -326,7 +328,7 @@ export function randBetween(max, min = _ONE) {
|
||||||
*/
|
*/
|
||||||
export function randBits(bitLength, forceLength = false) {
|
export function randBits(bitLength, forceLength = false) {
|
||||||
const byteLength = Math.ceil(bitLength / 8);
|
const byteLength = Math.ceil(bitLength / 8);
|
||||||
let rndBytes = randBytes(byteLength, false);
|
let rndBytes = randBytesSync(byteLength, false);
|
||||||
// Fill with 0's the extra birs
|
// Fill with 0's the extra birs
|
||||||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1);
|
||||||
if (forceLength) {
|
if (forceLength) {
|
||||||
|
@ -342,9 +344,37 @@ export function randBits(bitLength, forceLength = false) {
|
||||||
* @param {number} byteLength The desired number of random bytes
|
* @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
|
* @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) {
|
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;
|
let buf;
|
||||||
if (!process.browser) { // node
|
if (!process.browser) { // node
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
|
@ -388,7 +418,7 @@ function fromBuffer(buf) {
|
||||||
|
|
||||||
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 _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
|
const onmessage = async function (event) { // Let's start once we are called
|
||||||
// event.data = {rnd: <bigint>, iterations: <number>}
|
// event.data = {rnd: <bigint>, iterations: <number>}
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -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 = [
|
const numbers = [
|
||||||
{
|
{
|
||||||
value: BigInt(1),
|
value: BigInt(1),
|
||||||
|
@ -54,7 +168,7 @@ const numbers = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('Testing validation of prime numbers', function () {
|
describe('isProbablyPrime', function () {
|
||||||
for (const num of numbers) {
|
for (const num of numbers) {
|
||||||
describe(`isProbablyPrime(${num.value})`, function () {
|
describe(`isProbablyPrime(${num.value})`, function () {
|
||||||
it(`should return ${num.prime}`, async 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 = [
|
const bitLengths = [
|
||||||
1024,
|
1024,
|
||||||
2048,
|
2048,
|
||||||
|
@ -77,16 +315,48 @@ const bitLengths = [
|
||||||
4096
|
4096
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('Testing generation of prime numbers', function () {
|
describe('prime', function () {
|
||||||
for (const bitLength of bitLengths) {
|
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 () {
|
it(`should return a random ${bitLength}-bits probable prime`, async function () {
|
||||||
let prime = await bigintCryptoUtils.prime(bitLength);
|
let prime = await bigintCryptoUtils.prime(bitLength);
|
||||||
let bits = 1;
|
let primeBitLength = bigintCryptoUtils.bitLength(prime);
|
||||||
do {
|
chai.expect(primeBitLength).to.equal(bitLength);
|
||||||
bits++;
|
});
|
||||||
} while ((prime >>= BigInt(1)) > BigInt(1));
|
});
|
||||||
chai.expect(bits).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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -56,7 +56,7 @@ const numbers = [
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('Testing validation of prime numbers', function () {
|
describe('isProbablyPrime', function () {
|
||||||
for (const num of numbers) {
|
for (const num of numbers) {
|
||||||
describe(`isProbablyPrime(${num.value})`, function () {
|
describe(`isProbablyPrime(${num.value})`, function () {
|
||||||
it(`should return ${num.prime}`, async function () {
|
it(`should return ${num.prime}`, async function () {
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
|
@ -12,16 +12,13 @@ const bitLengths = [
|
||||||
4096
|
4096
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('Testing generation of prime numbers', function () {
|
describe('prime', function () {
|
||||||
for (const bitLength of bitLengths) {
|
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 () {
|
it(`should return a random ${bitLength}-bits probable prime`, async function () {
|
||||||
let prime = await bigintCryptoUtils.prime(bitLength);
|
let prime = await bigintCryptoUtils.prime(bitLength);
|
||||||
let bits = 1;
|
let primeBitLength = bigintCryptoUtils.bitLength(prime);
|
||||||
do {
|
chai.expect(primeBitLength).to.equal(bitLength);
|
||||||
bits++;
|
|
||||||
} while ((prime >>= BigInt(1)) > BigInt(1));
|
|
||||||
chai.expect(bits).to.equal(bitLength);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in New Issue