paillier-bigint
Advanced tools
Comparing version 1.0.9 to 1.1.0
@@ -134,3 +134,3 @@ var paillierBigint = (function (exports) { | ||
return new Promise((resolve, reject) => { | ||
let worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
const worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
@@ -191,31 +191,33 @@ worker.onmessage = (event) => { | ||
/** | ||
* Modular exponentiation a**b mod n | ||
* @param {number|bigint} a base | ||
* @param {number|bigint} b exponent | ||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method | ||
* | ||
* @param {number|bigint} b base | ||
* @param {number|bigint} e exponent | ||
* @param {number|bigint} n modulo | ||
* | ||
* @returns {bigint} a**b mod n | ||
* @returns {bigint} b**e mod n | ||
*/ | ||
function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
function modPow(b, e, n) { | ||
n = BigInt(n); | ||
if (n === _ZERO) | ||
return NaN; | ||
else if (n === _ONE) | ||
return _ZERO; | ||
a = toZn(a, n); | ||
b = BigInt(b); | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
b = toZn(b, n); | ||
e = BigInt(e); | ||
if (e < _ZERO) { | ||
return modInv(modPow(b, abs(e), n), n); | ||
} | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b & _ONE; | ||
b = b / _TWO; | ||
if (leastSignificantBit === _ONE) { | ||
result = (result * x) % n; | ||
let r = _ONE; | ||
while (e > 0) { | ||
if ((e % _TWO) === _ONE) { | ||
r = (r * b) % n; | ||
} | ||
x = (x * x) % n; | ||
e = e / _TWO; | ||
b = b ** _TWO % n; | ||
} | ||
return result; | ||
return r; | ||
} | ||
@@ -232,4 +234,5 @@ | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* @param {boolean} sync NOT RECOMMENDED. Invoke the function synchronously. It won't use workers so it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits. | ||
*/ | ||
@@ -286,2 +289,21 @@ function prime(bitLength, iterations = 16) { | ||
/** | ||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator. | ||
* The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead. | ||
* | ||
* @param {number} bitLength The required bit length for the generated prime | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* | ||
* @returns {bigint} A bigint probable prime of bitLength bits. | ||
*/ | ||
function primeSync(bitLength, iterations = 16) { | ||
if (bitLength < 1) | ||
throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`); | ||
let rnd = _ZERO; | ||
do { | ||
rnd = fromBuffer(randBytesSync(bitLength / 8, true)); | ||
} while (!_isProbablyPrime(rnd, iterations)); | ||
return rnd; | ||
} | ||
/** | ||
* Returns a cryptographically secure random integer between [min,max] | ||
@@ -401,3 +423,3 @@ * @param {bigint} max Returned value will be <= max | ||
workerCode = `(() => {${workerCode}})()`; // encapsulate IIFE | ||
var _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
const _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
return window.URL.createObjectURL(_blob); | ||
@@ -734,6 +756,6 @@ } | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode | ||
* Generates a pair private, public key for the Paillier cryptosystem. | ||
* | ||
* @param {number} bitLength - the bit lenght of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
@@ -744,3 +766,3 @@ * @returns {Promise} - a promise that resolves to a {@link KeyPair} of public, private keys | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLenght) | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
@@ -775,2 +797,42 @@ p = await prime(Math.floor(bitLength$1 / 2) + 1); | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
* Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
* @returns {@link KeyPair} - a {@link KeyPair} of public, private keys | ||
*/ | ||
const generateRandomKeysSync = function (bitLength$1 = 4096, simpleVariant = false) { | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
p = primeSync(Math.floor(bitLength$1 / 2) + 1); | ||
q = primeSync(Math.floor(bitLength$1 / 2)); | ||
n = p * q; | ||
} while (q === p || bitLength(n) != bitLength$1); | ||
phi = (p - _ONE$1) * (q - _ONE$1); | ||
n2 = n ** BigInt(2); | ||
if (simpleVariant === true) { | ||
//If using p,q of equivalent length, a simpler variant of the key | ||
// generation steps would be to set | ||
// g=n+1, lambda=(p-1)(q-1), mu=lambda.invertm(n) | ||
g = n + _ONE$1; | ||
lambda = phi; | ||
mu = modInv(lambda, n); | ||
} else { | ||
g = getGenerator(n, n2); | ||
lambda = lcm(p - _ONE$1, q - _ONE$1); | ||
mu = modInv(L(modPow(g, lambda, n2), n), n); | ||
} | ||
const publicKey = new PublicKey(n, g); | ||
const privateKey = new PrivateKey(lambda, mu, p, q, publicKey); | ||
return { publicKey: publicKey, privateKey: privateKey }; | ||
}; | ||
/** | ||
* Class for a Paillier public key | ||
@@ -899,2 +961,3 @@ */ | ||
exports.generateRandomKeys = generateRandomKeys; | ||
exports.generateRandomKeysSync = generateRandomKeysSync; | ||
@@ -901,0 +964,0 @@ return exports; |
@@ -1,1 +0,1 @@ | ||
var paillierBigint=function(a){'use strict';function c(b){return b=BigInt(b),b>=z?b:-b}function d(b){if(b=BigInt(b),b===A)return 1;let c=1;do c++;while((b>>=A)>A);return c}function e(c,d){if(c=BigInt(c),d=BigInt(d),c<=z|d<=z)return NaN;let e=z,f=A,g=A,h=z;for(;c!==z;){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){if(d=c(d),e=c(e),d===z)return e;if(e===z)return d;let f=z;for(;!((d|e)&A);)d>>=A,e>>=A,f++;for(;!(d&A);)d>>=A;do{for(;!(e&A);)e>>=A;if(d>e){let a=d;d=e,e=a}e-=d}while(e);return d<<f}async function g(a,b=16){return"number"==typeof a&&(a=BigInt(a)),new Promise((c,d)=>{let e=new Worker(q());e.onmessage=a=>{e.terminate(),c(a.data.isPrime)},e.onmessageerror=a=>{d(a)},e.postMessage({rnd:a,iterations:b,id:0})})}function h(d,e){return d=BigInt(d),e=BigInt(e),d===z&&e===z?z:c(d*e)/f(d,e)}function i(b,a){if(b==z|a<=z)return NaN;let c=e(o(b,a),a);return c.b===A?o(c.x,a):NaN}function j(d,e,f){if(f=BigInt(f),f===z)return NaN;if(d=o(d,f),e=BigInt(e),e<z)return i(j(d,c(e),f),f);let g=A,h=d;for(;0<e;){var k=e&A;e/=B,k===A&&(g=g*h%f),h=h*h%f}return g}function k(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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=m(a,!0),d=p(c);try{f.postMessage({rnd:d,iterations:b,id:e.id})}catch(a){}}};{let a=q();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=m(a,!0),f=p(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})}function l(a,b=A){if(a<=b)throw new Error("max must be > min");const c=a-b;let e,f=d(c);do{let a=m(f);e=p(a)}while(e>c);return e+b}function m(a,b=!1){var c=Math.ceil;if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);const d=c(a/8);let e=n(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 n(a,b=!1){if(1>a)throw new RangeError(`byteLength MUST be > 0 and it is ${a}`);let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function o(b,c){return(c=BigInt(c),0>=c)?NaN:(b=BigInt(b)%c,0>b?b+c:b)}function p(a){let b=z;for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function q(){let a=`'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${e.toString()};const modInv = ${i.toString()};const modPow = ${j.toString()};const toZn = ${o.toString()};const randBits = ${m.toString()};const randBytesSync = ${n.toString()};const randBetween = ${l.toString()};const isProbablyPrime = ${s.toString()};${d.toString()}${p.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()};`,r(a)}function r(a){a=`(() => {${a}})()`;var b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}function s(c,b=16){if(c===B)return!0;if((c&A)===z||c===A)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===z)return!1}let f=z,g=c-A;for(;g%B===z;)g/=B,++f;let h=(c-A)/B**f;loop:do{let a=l(c-A,B),b=j(a,h,c);if(b===A||b===c-A)continue;for(let a=1;a<f;a++){if(b=j(b,B,c),b===c-A)continue loop;if(b===A)break}return!1}while(--b);return!0}function t(b,a){return(b-C)/a}function b(a,b=j(a,2)){const c=l(a),d=l(a);return(c*a+C)*j(d,a,b)%b}const z=BigInt(0),A=BigInt(1),B=BigInt(2),C=BigInt(1),D=class{constructor(a,b){this.n=BigInt(a),this._n2=this.n**BigInt(2),this.g=BigInt(b)}get bitLength(){return d(this.n)}encrypt(a){let b;return b=l(this.n),j(this.g,a,this._n2)*j(b,this.n,this._n2)%this._n2}addition(...a){return a.reduce((a,b)=>a*BigInt(b)%this._n2,C)}multiply(a,b){return"string"==typeof b&&(b=BigInt(b)),j(BigInt(a),b,this._n2)}},E=class{constructor(a,b,c,d,e){this.lambda=BigInt(a),this.mu=BigInt(b),this._p=BigInt(c),this._q=BigInt(d),this.publicKey=e}get bitLength(){return d(this.publicKey.n)}get n(){return this.publicKey.n}decrypt(a){return t(j(BigInt(a),this.lambda,this.publicKey._n2),this.publicKey.n)*this.mu%this.publicKey.n}};return a.PrivateKey=E,a.PublicKey=D,a.generateRandomKeys=async function(a=4096,c=!1){var e=Math.floor;let f,l,m,o,r,s,u,v;do f=await k(e(a/2)+1),l=await k(e(a/2)),m=f*l;while(l===f||d(m)!=a);o=(f-C)*(l-C),r=m**BigInt(2),!0===c?(s=m+C,u=o,v=i(u,m)):(s=b(m,r),u=h(f-C,l-C),v=i(t(j(s,u,r),m),m));const w=new D(m,s),x=new E(u,v,f,l,w);return{publicKey:w,privateKey:x}},a}({}); | ||
var paillierBigint=function(a){'use strict';var m=Math.floor;function c(b){return b=BigInt(b),b>=z?b:-b}function d(b){if(b=BigInt(b),b===A)return 1;let c=1;do c++;while((b>>=A)>A);return c}function e(c,d){if(c=BigInt(c),d=BigInt(d),c<=z|d<=z)return NaN;let e=z,f=A,g=A,h=z;for(;c!==z;){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){if(d=c(d),e=c(e),d===z)return e;if(e===z)return d;let f=z;for(;!((d|e)&A);)d>>=A,e>>=A,f++;for(;!(d&A);)d>>=A;do{for(;!(e&A);)e>>=A;if(d>e){let a=d;d=e,e=a}e-=d}while(e);return d<<f}async function g(a,b=16){return"number"==typeof a&&(a=BigInt(a)),new Promise((c,d)=>{const e=new Worker(u());e.onmessage=a=>{e.terminate(),c(a.data.isPrime)},e.onmessageerror=a=>{d(a)},e.postMessage({rnd:a,iterations:b,id:0})})}function h(d,e){return d=BigInt(d),e=BigInt(e),d===z&&e===z?z:c(d*e)/f(d,e)}function i(b,a){if(b==z|a<=z)return NaN;let c=e(s(b,a),a);return c.b===A?s(c.x,a):NaN}function j(a,d,f){if(f=BigInt(f),f===z)return NaN;if(f===A)return z;if(a=s(a,f),d=BigInt(d),d<z)return i(j(a,c(d),f),f);let g=A;for(;0<d;)d%B===A&&(g=g*a%f),d/=B,a=a**B%f;return g}function k(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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=p(a,!0),d=t(c);try{f.postMessage({rnd:d,iterations:b,id:e.id})}catch(a){}}};{let a=u();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=p(a,!0),f=t(c);d[e].postMessage({rnd:f,iterations:b,id:e})}})}function l(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);let c=z;do c=t(q(a/8,!0));while(!w(c,b));return c}function o(a,b=A){if(a<=b)throw new Error("max must be > min");const c=a-b;let e,f=d(c);do{let a=p(f);e=t(a)}while(e>c);return e+b}function p(a,b=!1){var c=Math.ceil;if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);const d=c(a/8);let e=q(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 q(a,b=!1){if(1>a)throw new RangeError(`byteLength MUST be > 0 and it is ${a}`);let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function s(b,c){return(c=BigInt(c),0>=c)?NaN:(b=BigInt(b)%c,0>b?b+c:b)}function t(a){let b=z;for(let c of a.values()){let a=BigInt(c);b=(b<<BigInt(8))+a}return b}function u(){let a=`'use strict';const _ZERO = BigInt(0);const _ONE = BigInt(1);const _TWO = BigInt(2);const eGcd = ${e.toString()};const modInv = ${i.toString()};const modPow = ${j.toString()};const toZn = ${s.toString()};const randBits = ${p.toString()};const randBytesSync = ${q.toString()};const randBetween = ${o.toString()};const isProbablyPrime = ${w.toString()};${d.toString()}${t.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()};`,v(a)}function v(a){a=`(() => {${a}})()`;const b=new Blob([a],{type:"text/javascript"});return window.URL.createObjectURL(b)}function w(c,b=16){if(c===B)return!0;if((c&A)===z||c===A)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===z)return!1}let f=z,g=c-A;for(;g%B===z;)g/=B,++f;let h=(c-A)/B**f;loop:do{let a=o(c-A,B),b=j(a,h,c);if(b===A||b===c-A)continue;for(let a=1;a<f;a++){if(b=j(b,B,c),b===c-A)continue loop;if(b===A)break}return!1}while(--b);return!0}function x(b,a){return(b-C)/a}function b(a,b=j(a,2)){const c=o(a),d=o(a);return(c*a+C)*j(d,a,b)%b}const z=BigInt(0),A=BigInt(1),B=BigInt(2),C=BigInt(1),D=class{constructor(a,b){this.n=BigInt(a),this._n2=this.n**BigInt(2),this.g=BigInt(b)}get bitLength(){return d(this.n)}encrypt(a){let b;return b=o(this.n),j(this.g,a,this._n2)*j(b,this.n,this._n2)%this._n2}addition(...a){return a.reduce((a,b)=>a*BigInt(b)%this._n2,C)}multiply(a,b){return"string"==typeof b&&(b=BigInt(b)),j(BigInt(a),b,this._n2)}},E=class{constructor(a,b,c,d,e){this.lambda=BigInt(a),this.mu=BigInt(b),this._p=BigInt(c),this._q=BigInt(d),this.publicKey=e}get bitLength(){return d(this.publicKey.n)}get n(){return this.publicKey.n}decrypt(a){return x(j(BigInt(a),this.lambda,this.publicKey._n2),this.publicKey.n)*this.mu%this.publicKey.n}};return a.PrivateKey=E,a.PublicKey=D,a.generateRandomKeys=async function(a=4096,c=!1){let e,f,l,o,r,s,t,u;do e=await k(m(a/2)+1),f=await k(m(a/2)),l=e*f;while(f===e||d(l)!=a);o=(e-C)*(f-C),r=l**BigInt(2),!0===c?(s=l+C,t=o,u=i(t,l)):(s=b(l,r),t=h(e-C,f-C),u=i(x(j(s,t,r),l),l));const v=new D(l,s),w=new E(t,u,e,f,v);return{publicKey:v,privateKey:w}},a.generateRandomKeysSync=function(a=4096,c=!1){let e,f,k,o,r,s,t,u;do e=l(m(a/2)+1),f=l(m(a/2)),k=e*f;while(f===e||d(k)!=a);o=(e-C)*(f-C),r=k**BigInt(2),!0===c?(s=k+C,t=o,u=i(t,k)):(s=b(k,r),t=h(e-C,f-C),u=i(x(j(s,t,r),k),k));const v=new D(k,s),w=new E(t,u,e,f,v);return{publicKey:v,privateKey:w}},a}({}); |
@@ -131,3 +131,3 @@ const _ZERO = BigInt(0); | ||
return new Promise((resolve, reject) => { | ||
let worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
const worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
@@ -188,31 +188,33 @@ worker.onmessage = (event) => { | ||
/** | ||
* Modular exponentiation a**b mod n | ||
* @param {number|bigint} a base | ||
* @param {number|bigint} b exponent | ||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method | ||
* | ||
* @param {number|bigint} b base | ||
* @param {number|bigint} e exponent | ||
* @param {number|bigint} n modulo | ||
* | ||
* @returns {bigint} a**b mod n | ||
* @returns {bigint} b**e mod n | ||
*/ | ||
function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
function modPow(b, e, n) { | ||
n = BigInt(n); | ||
if (n === _ZERO) | ||
return NaN; | ||
else if (n === _ONE) | ||
return _ZERO; | ||
a = toZn(a, n); | ||
b = BigInt(b); | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
b = toZn(b, n); | ||
e = BigInt(e); | ||
if (e < _ZERO) { | ||
return modInv(modPow(b, abs(e), n), n); | ||
} | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b & _ONE; | ||
b = b / _TWO; | ||
if (leastSignificantBit === _ONE) { | ||
result = (result * x) % n; | ||
let r = _ONE; | ||
while (e > 0) { | ||
if ((e % _TWO) === _ONE) { | ||
r = (r * b) % n; | ||
} | ||
x = (x * x) % n; | ||
e = e / _TWO; | ||
b = b ** _TWO % n; | ||
} | ||
return result; | ||
return r; | ||
} | ||
@@ -229,4 +231,5 @@ | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* @param {boolean} sync NOT RECOMMENDED. Invoke the function synchronously. It won't use workers so it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits. | ||
*/ | ||
@@ -283,2 +286,21 @@ function prime(bitLength, iterations = 16) { | ||
/** | ||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator. | ||
* The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead. | ||
* | ||
* @param {number} bitLength The required bit length for the generated prime | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* | ||
* @returns {bigint} A bigint probable prime of bitLength bits. | ||
*/ | ||
function primeSync(bitLength, iterations = 16) { | ||
if (bitLength < 1) | ||
throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`); | ||
let rnd = _ZERO; | ||
do { | ||
rnd = fromBuffer(randBytesSync(bitLength / 8, true)); | ||
} while (!_isProbablyPrime(rnd, iterations)); | ||
return rnd; | ||
} | ||
/** | ||
* Returns a cryptographically secure random integer between [min,max] | ||
@@ -398,3 +420,3 @@ * @param {bigint} max Returned value will be <= max | ||
workerCode = `(() => {${workerCode}})()`; // encapsulate IIFE | ||
var _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
const _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
return window.URL.createObjectURL(_blob); | ||
@@ -731,6 +753,6 @@ } | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode | ||
* Generates a pair private, public key for the Paillier cryptosystem. | ||
* | ||
* @param {number} bitLength - the bit lenght of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
@@ -741,3 +763,3 @@ * @returns {Promise} - a promise that resolves to a {@link KeyPair} of public, private keys | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLenght) | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
@@ -772,2 +794,42 @@ p = await prime(Math.floor(bitLength$1 / 2) + 1); | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
* Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
* @returns {@link KeyPair} - a {@link KeyPair} of public, private keys | ||
*/ | ||
const generateRandomKeysSync = function (bitLength$1 = 4096, simpleVariant = false) { | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
p = primeSync(Math.floor(bitLength$1 / 2) + 1); | ||
q = primeSync(Math.floor(bitLength$1 / 2)); | ||
n = p * q; | ||
} while (q === p || bitLength(n) != bitLength$1); | ||
phi = (p - _ONE$1) * (q - _ONE$1); | ||
n2 = n ** BigInt(2); | ||
if (simpleVariant === true) { | ||
//If using p,q of equivalent length, a simpler variant of the key | ||
// generation steps would be to set | ||
// g=n+1, lambda=(p-1)(q-1), mu=lambda.invertm(n) | ||
g = n + _ONE$1; | ||
lambda = phi; | ||
mu = modInv(lambda, n); | ||
} else { | ||
g = getGenerator(n, n2); | ||
lambda = lcm(p - _ONE$1, q - _ONE$1); | ||
mu = modInv(L(modPow(g, lambda, n2), n), n); | ||
} | ||
const publicKey = new PublicKey(n, g); | ||
const privateKey = new PrivateKey(lambda, mu, p, q, publicKey); | ||
return { publicKey: publicKey, privateKey: privateKey }; | ||
}; | ||
/** | ||
* Class for a Paillier public key | ||
@@ -893,2 +955,2 @@ */ | ||
export { PrivateKey, PublicKey, generateRandomKeys }; | ||
export { PrivateKey, PublicKey, generateRandomKeys, generateRandomKeysSync }; |
@@ -1,1 +0,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){if(b=BigInt(b),b===_ONE)return 1;let c=1;do c++;while((b>>=_ONE)>_ONE);return c}function eGcd(c,d){if(c=BigInt(c),d=BigInt(d),c<=_ZERO|d<=_ZERO)return NaN;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){if(c=abs(c),d=abs(d),c===_ZERO)return d;if(d===_ZERO)return c;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"number"==typeof a&&(a=BigInt(a)),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),c===_ZERO&&d===_ZERO?_ZERO:abs(c*d)/gcd(c,d)}function modInv(b,a){if(b==_ZERO|a<=_ZERO)return NaN;let c=eGcd(toZn(b,a),a);return c.b===_ONE?toZn(c.x,a):NaN}function modPow(c,d,e){if(e=BigInt(e),e===_ZERO)return NaN;if(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&_ONE;d/=_TWO,h===_ONE&&(f=f*g%e),g=g*g%e}return f}function prime(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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;if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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 randBytesSync(a,b=!1){if(1>a)throw new RangeError(`byteLength MUST be > 0 and it is ${a}`);let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function toZn(b,c){return(c=BigInt(c),0>=c)?NaN:(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}const _ONE$1=BigInt(1),generateRandomKeys=async function(a=4096,b=!1){var c=Math.floor;let d,e,f,h,i,j,k,l;do d=await prime(c(a/2)+1),e=await prime(c(a/2)),f=d*e;while(e===d||bitLength(f)!=a);h=(d-_ONE$1)*(e-_ONE$1),i=f**BigInt(2),!0===b?(j=f+_ONE$1,k=h,l=modInv(k,f)):(j=getGenerator(f,i),k=lcm(d-_ONE$1,e-_ONE$1),l=modInv(L(modPow(j,k,i),f),f));const m=new PublicKey(f,j),o=new PrivateKey(k,l,d,e,m);return{publicKey:m,privateKey:o}},PublicKey=class{constructor(a,b){this.n=BigInt(a),this._n2=this.n**BigInt(2),this.g=BigInt(b)}get bitLength(){return bitLength(this.n)}encrypt(a){let b;return b=randBetween(this.n),modPow(this.g,a,this._n2)*modPow(b,this.n,this._n2)%this._n2}addition(...a){return a.reduce((a,b)=>a*BigInt(b)%this._n2,_ONE$1)}multiply(a,b){return"string"==typeof b&&(b=BigInt(b)),modPow(BigInt(a),b,this._n2)}},PrivateKey=class{constructor(a,b,c,d,e){this.lambda=BigInt(a),this.mu=BigInt(b),this._p=BigInt(c),this._q=BigInt(d),this.publicKey=e}get bitLength(){return bitLength(this.publicKey.n)}get n(){return this.publicKey.n}decrypt(a){return L(modPow(BigInt(a),this.lambda,this.publicKey._n2),this.publicKey.n)*this.mu%this.publicKey.n}};function L(b,a){return(b-_ONE$1)/a}function getGenerator(a,b=modPow(a,2)){const c=randBetween(a),d=randBetween(a);return(c*a+_ONE$1)*modPow(d,a,b)%b}export{PrivateKey,PublicKey,generateRandomKeys}; | ||
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=BigInt(b),b===_ONE)return 1;let c=1;do c++;while((b>>=_ONE)>_ONE);return c}function eGcd(c,d){if(c=BigInt(c),d=BigInt(d),c<=_ZERO|d<=_ZERO)return NaN;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){if(c=abs(c),d=abs(d),c===_ZERO)return d;if(d===_ZERO)return c;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"number"==typeof a&&(a=BigInt(a)),new Promise((c,d)=>{const 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),c===_ZERO&&d===_ZERO?_ZERO:abs(c*d)/gcd(c,d)}function modInv(b,a){if(b==_ZERO|a<=_ZERO)return NaN;let c=eGcd(toZn(b,a),a);return c.b===_ONE?toZn(c.x,a):NaN}function modPow(a,c,d){if(d=BigInt(d),d===_ZERO)return NaN;if(d===_ONE)return _ZERO;if(a=toZn(a,d),c=BigInt(c),c<_ZERO)return modInv(modPow(a,abs(c),d),d);let f=_ONE;for(;0<c;)c%_TWO===_ONE&&(f=f*a%d),c/=_TWO,a=a**_TWO%d;return f}function prime(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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 primeSync(a,b=16){if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);let c=_ZERO;do c=fromBuffer(randBytesSync(a/8,!0));while(!_isProbablyPrime(c,b));return c}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;if(1>a)throw new RangeError(`bitLength MUST be > 0 and it is ${a}`);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 randBytesSync(a,b=!1){if(1>a)throw new RangeError(`byteLength MUST be > 0 and it is ${a}`);let c;return c=new Uint8Array(a),self.crypto.getRandomValues(c),b&&(c[0]|=128),c}function toZn(b,c){return(c=BigInt(c),0>=c)?NaN:(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}})()`;const 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}const _ONE$1=BigInt(1),generateRandomKeys=async function(a=4096,b=!1){var c=Math.floor;let d,e,f,h,i,j,k,l;do d=await prime(c(a/2)+1),e=await prime(c(a/2)),f=d*e;while(e===d||bitLength(f)!=a);h=(d-_ONE$1)*(e-_ONE$1),i=f**BigInt(2),!0===b?(j=f+_ONE$1,k=h,l=modInv(k,f)):(j=getGenerator(f,i),k=lcm(d-_ONE$1,e-_ONE$1),l=modInv(L(modPow(j,k,i),f),f));const m=new PublicKey(f,j),o=new PrivateKey(k,l,d,e,m);return{publicKey:m,privateKey:o}},generateRandomKeysSync=function(a=4096,b=!1){var c=Math.floor;let d,e,f,h,i,j,k,l;do d=primeSync(c(a/2)+1),e=primeSync(c(a/2)),f=d*e;while(e===d||bitLength(f)!=a);h=(d-_ONE$1)*(e-_ONE$1),i=f**BigInt(2),!0===b?(j=f+_ONE$1,k=h,l=modInv(k,f)):(j=getGenerator(f,i),k=lcm(d-_ONE$1,e-_ONE$1),l=modInv(L(modPow(j,k,i),f),f));const m=new PublicKey(f,j),o=new PrivateKey(k,l,d,e,m);return{publicKey:m,privateKey:o}},PublicKey=class{constructor(a,b){this.n=BigInt(a),this._n2=this.n**BigInt(2),this.g=BigInt(b)}get bitLength(){return bitLength(this.n)}encrypt(a){let b;return b=randBetween(this.n),modPow(this.g,a,this._n2)*modPow(b,this.n,this._n2)%this._n2}addition(...a){return a.reduce((a,b)=>a*BigInt(b)%this._n2,_ONE$1)}multiply(a,b){return"string"==typeof b&&(b=BigInt(b)),modPow(BigInt(a),b,this._n2)}},PrivateKey=class{constructor(a,b,c,d,e){this.lambda=BigInt(a),this.mu=BigInt(b),this._p=BigInt(c),this._q=BigInt(d),this.publicKey=e}get bitLength(){return bitLength(this.publicKey.n)}get n(){return this.publicKey.n}decrypt(a){return L(modPow(BigInt(a),this.lambda,this.publicKey._n2),this.publicKey.n)*this.mu%this.publicKey.n}};function L(b,a){return(b-_ONE$1)/a}function getGenerator(a,b=modPow(a,2)){const c=randBetween(a),d=randBetween(a);return(c*a+_ONE$1)*modPow(d,a,b)%b}export{PrivateKey,PublicKey,generateRandomKeys,generateRandomKeysSync}; |
@@ -16,6 +16,6 @@ 'use strict'; | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode | ||
* Generates a pair private, public key for the Paillier cryptosystem. | ||
* | ||
* @param {number} bitLength - the bit lenght of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
@@ -26,3 +26,3 @@ * @returns {Promise} - a promise that resolves to a {@link KeyPair} of public, private keys | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLenght) | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
@@ -57,2 +57,42 @@ p = await bcu.prime(Math.floor(bitLength / 2) + 1); | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
* Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
* @returns {@link KeyPair} - a {@link KeyPair} of public, private keys | ||
*/ | ||
const generateRandomKeysSync = function (bitLength = 4096, simpleVariant = false) { | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
p = bcu.primeSync(Math.floor(bitLength / 2) + 1); | ||
q = bcu.primeSync(Math.floor(bitLength / 2)); | ||
n = p * q; | ||
} while (q === p || bcu.bitLength(n) != bitLength); | ||
phi = (p - _ONE) * (q - _ONE); | ||
n2 = n ** BigInt(2); | ||
if (simpleVariant === true) { | ||
//If using p,q of equivalent length, a simpler variant of the key | ||
// generation steps would be to set | ||
// g=n+1, lambda=(p-1)(q-1), mu=lambda.invertm(n) | ||
g = n + _ONE; | ||
lambda = phi; | ||
mu = bcu.modInv(lambda, n); | ||
} else { | ||
g = getGenerator(n, n2); | ||
lambda = bcu.lcm(p - _ONE, q - _ONE); | ||
mu = bcu.modInv(L(bcu.modPow(g, lambda, n2), n), n); | ||
} | ||
const publicKey = new PublicKey(n, g); | ||
const privateKey = new PrivateKey(lambda, mu, p, q, publicKey); | ||
return { publicKey: publicKey, privateKey: privateKey }; | ||
}; | ||
/** | ||
* Class for a Paillier public key | ||
@@ -181,1 +221,2 @@ */ | ||
exports.generateRandomKeys = generateRandomKeys; | ||
exports.generateRandomKeysSync = generateRandomKeysSync; |
{ | ||
"name": "paillier-bigint", | ||
"version": "1.0.9", | ||
"version": "1.1.0", | ||
"description": "An implementation of the Paillier cryptosystem using native JS (stage 3) implementation of BigInt", | ||
@@ -37,14 +37,14 @@ "keywords": [ | ||
"eslint": "^5.16.0", | ||
"jsdoc-to-markdown": "^5.0.0", | ||
"mocha": "^6.1.4", | ||
"rollup": "^1.12.3", | ||
"jsdoc-to-markdown": "^5.0.1", | ||
"mocha": "^6.2.1", | ||
"rollup": "^1.23.1", | ||
"rollup-plugin-babel-minify": "^8.0.0", | ||
"rollup-plugin-commonjs": "^10.0.0", | ||
"rollup-plugin-node-resolve": "^5.0.0", | ||
"rollup-plugin-replace": "^2.2.0", | ||
"rollup-plugin-multi-entry": "^2.1.0" | ||
"rollup-plugin-commonjs": "^10.1.0", | ||
"rollup-plugin-multi-entry": "^2.1.0", | ||
"rollup-plugin-node-resolve": "^5.2.0", | ||
"rollup-plugin-replace": "^2.2.0" | ||
}, | ||
"dependencies": { | ||
"bigint-crypto-utils": "^2.1.7" | ||
"bigint-crypto-utils": "^2.3.1" | ||
} | ||
} |
@@ -167,4 +167,8 @@ # paillier-bigint | ||
<dt><a href="#generateRandomKeys">generateRandomKeys</a> ⇒ <code>Promise</code></dt> | ||
<dd><p>Generates a pair private, public key for the Paillier cryptosystem in synchronous mode</p> | ||
<dd><p>Generates a pair private, public key for the Paillier cryptosystem.</p> | ||
</dd> | ||
<dt><a href="#generateRandomKeysSync">generateRandomKeysSync</a> ⇒</dt> | ||
<dd><p>Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript.</p> | ||
</dd> | ||
<dt><a href="#PublicKey">PublicKey</a></dt> | ||
@@ -306,3 +310,3 @@ <dd><p>Class for a Paillier public key</p> | ||
## generateRandomKeys ⇒ <code>Promise</code> | ||
Generates a pair private, public key for the Paillier cryptosystem in synchronous mode | ||
Generates a pair private, public key for the Paillier cryptosystem. | ||
@@ -314,5 +318,19 @@ **Kind**: global constant | ||
| --- | --- | --- | | ||
| bitLength | <code>number</code> | the bit lenght of the public modulo | | ||
| simplevariant | <code>boolean</code> | use the simple variant to compute the generator | | ||
| bitLength | <code>number</code> | the bit length of the public modulo | | ||
| simplevariant | <code>boolean</code> | use the simple variant to compute the generator (g=n+1) | | ||
<a name="generateRandomKeysSync"></a> | ||
## generateRandomKeysSync ⇒ | ||
Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. | ||
**Kind**: global constant | ||
**Returns**: [KeyPair](#KeyPair) - a [KeyPair](#KeyPair) of public, private keys | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| bitLength | <code>number</code> | the bit length of the public modulo | | ||
| simplevariant | <code>boolean</code> | use the simple variant to compute the generator (g=n+1) | | ||
<a name="PublicKey"></a> | ||
@@ -319,0 +337,0 @@ |
@@ -13,6 +13,6 @@ 'use strict'; | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode | ||
* Generates a pair private, public key for the Paillier cryptosystem. | ||
* | ||
* @param {number} bitLength - the bit lenght of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
@@ -23,3 +23,3 @@ * @returns {Promise} - a promise that resolves to a {@link KeyPair} of public, private keys | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLenght) | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
@@ -54,2 +54,42 @@ p = await bcu.prime(Math.floor(bitLength / 2) + 1); | ||
/** | ||
* Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
* Synchronous mode is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @param {number} bitLength - the bit length of the public modulo | ||
* @param {boolean} simplevariant - use the simple variant to compute the generator (g=n+1) | ||
* | ||
* @returns {@link KeyPair} - a {@link KeyPair} of public, private keys | ||
*/ | ||
export const generateRandomKeysSync = function (bitLength = 4096, simpleVariant = false) { | ||
let p, q, n, phi, n2, g, lambda, mu; | ||
// if p and q are bitLength/2 long -> 2**(bitLength - 2) <= n < 2**(bitLength) | ||
do { | ||
p = bcu.primeSync(Math.floor(bitLength / 2) + 1); | ||
q = bcu.primeSync(Math.floor(bitLength / 2)); | ||
n = p * q; | ||
} while (q === p || bcu.bitLength(n) != bitLength); | ||
phi = (p - _ONE) * (q - _ONE); | ||
n2 = n ** BigInt(2); | ||
if (simpleVariant === true) { | ||
//If using p,q of equivalent length, a simpler variant of the key | ||
// generation steps would be to set | ||
// g=n+1, lambda=(p-1)(q-1), mu=lambda.invertm(n) | ||
g = n + _ONE; | ||
lambda = phi; | ||
mu = bcu.modInv(lambda, n); | ||
} else { | ||
g = getGenerator(n, n2); | ||
lambda = bcu.lcm(p - _ONE, q - _ONE); | ||
mu = bcu.modInv(L(bcu.modPow(g, lambda, n2), n), n); | ||
} | ||
const publicKey = new PublicKey(n, g); | ||
const privateKey = new PrivateKey(lambda, mu, p, q, publicKey); | ||
return { publicKey: publicKey, privateKey: privateKey }; | ||
}; | ||
/** | ||
* Class for a Paillier public key | ||
@@ -56,0 +96,0 @@ */ |
@@ -131,3 +131,3 @@ const _ZERO = BigInt(0); | ||
return new Promise((resolve, reject) => { | ||
let worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
const worker = new Worker(_isProbablyPrimeWorkerUrl()); | ||
@@ -168,2 +168,30 @@ worker.onmessage = (event) => { | ||
/** | ||
* Maximum. max(a,b)==a if a>=b. max(a,b)==b if a<=b | ||
* | ||
* @param {number|bigint} a | ||
* @param {number|bigint} b | ||
* | ||
* @returns {bigint} maximum of numbers a and b | ||
*/ | ||
function max(a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
return (a >= b) ? a : b; | ||
} | ||
/** | ||
* Minimum. min(a,b)==b if a>=b. min(a,b)==a if a<=b | ||
* | ||
* @param {number|bigint} a | ||
* @param {number|bigint} b | ||
* | ||
* @returns {bigint} minimum of numbers a and b | ||
*/ | ||
function min(a, b) { | ||
a = BigInt(a); | ||
b = BigInt(b); | ||
return (a >= b) ? b : a; | ||
} | ||
/** | ||
* Modular inverse. | ||
@@ -189,31 +217,33 @@ * | ||
/** | ||
* Modular exponentiation a**b mod n | ||
* @param {number|bigint} a base | ||
* @param {number|bigint} b exponent | ||
* Modular exponentiation b**e mod n. Currently using the right-to-left binary method | ||
* | ||
* @param {number|bigint} b base | ||
* @param {number|bigint} e exponent | ||
* @param {number|bigint} n modulo | ||
* | ||
* @returns {bigint} a**b mod n | ||
* @returns {bigint} b**e mod n | ||
*/ | ||
function modPow(a, b, n) { | ||
// See Knuth, volume 2, section 4.6.3. | ||
function modPow(b, e, n) { | ||
n = BigInt(n); | ||
if (n === _ZERO) | ||
return NaN; | ||
else if (n === _ONE) | ||
return _ZERO; | ||
a = toZn(a, n); | ||
b = BigInt(b); | ||
if (b < _ZERO) { | ||
return modInv(modPow(a, abs(b), n), n); | ||
b = toZn(b, n); | ||
e = BigInt(e); | ||
if (e < _ZERO) { | ||
return modInv(modPow(b, abs(e), n), n); | ||
} | ||
let result = _ONE; | ||
let x = a; | ||
while (b > 0) { | ||
var leastSignificantBit = b & _ONE; | ||
b = b / _TWO; | ||
if (leastSignificantBit === _ONE) { | ||
result = (result * x) % n; | ||
let r = _ONE; | ||
while (e > 0) { | ||
if ((e % _TWO) === _ONE) { | ||
r = (r * b) % n; | ||
} | ||
x = (x * x) % n; | ||
e = e / _TWO; | ||
b = b ** _TWO % n; | ||
} | ||
return result; | ||
return r; | ||
} | ||
@@ -230,4 +260,5 @@ | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* @param {boolean} sync NOT RECOMMENDED. Invoke the function synchronously. It won't use workers so it'll be slower and may freeze thw window in browser's javascript. | ||
* | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits. | ||
*/ | ||
@@ -284,2 +315,21 @@ function prime(bitLength, iterations = 16) { | ||
/** | ||
* A probably-prime (Miller-Rabin), cryptographically-secure, random-number generator. | ||
* The sync version is NOT RECOMMENDED since it won't use workers and thus it'll be slower and may freeze thw window in browser's javascript. Please consider using prime() instead. | ||
* | ||
* @param {number} bitLength The required bit length for the generated prime | ||
* @param {number} iterations The number of iterations for the Miller-Rabin Probabilistic Primality Test | ||
* | ||
* @returns {bigint} A bigint probable prime of bitLength bits. | ||
*/ | ||
function primeSync(bitLength, iterations = 16) { | ||
if (bitLength < 1) | ||
throw new RangeError(`bitLength MUST be > 0 and it is ${bitLength}`); | ||
let rnd = _ZERO; | ||
do { | ||
rnd = fromBuffer(randBytesSync(bitLength / 8, true)); | ||
} while (!_isProbablyPrime(rnd, iterations)); | ||
return rnd; | ||
} | ||
/** | ||
* Returns a cryptographically secure random integer between [min,max] | ||
@@ -424,3 +474,3 @@ * @param {bigint} max Returned value will be <= max | ||
workerCode = `(() => {${workerCode}})()`; // encapsulate IIFE | ||
var _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
const _blob = new Blob([workerCode], { type: 'text/javascript' }); | ||
return window.URL.createObjectURL(_blob); | ||
@@ -749,2 +799,3 @@ } | ||
var bigintCryptoUtilsLatest_browser_mod = /*#__PURE__*/Object.freeze({ | ||
__proto__: null, | ||
abs: abs, | ||
@@ -756,5 +807,8 @@ bitLength: bitLength, | ||
lcm: lcm, | ||
max: max, | ||
min: min, | ||
modInv: modInv, | ||
modPow: modPow, | ||
prime: prime, | ||
primeSync: primeSync, | ||
randBetween: randBetween, | ||
@@ -834,1 +888,9 @@ randBits: randBits, | ||
} | ||
describe('Testing generateRandomKeysSync(2048) NOT RECOMMENDED', function () { | ||
it('it should return a publicKey and a privateKey with public modulus of 2048 bits', function () { | ||
const keyPair = paillierBigint.generateRandomKeysSync(2048); | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(paillierBigint.PublicKey); | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(paillierBigint.PrivateKey); | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(2048); | ||
}); | ||
}); |
@@ -70,1 +70,9 @@ 'use strict'; | ||
} | ||
describe('Testing generateRandomKeysSync(2048) NOT RECOMMENDED', function () { | ||
it('it should return a publicKey and a privateKey with public modulus of 2048 bits', function () { | ||
const keyPair = paillierBigint.generateRandomKeysSync(2048); | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(paillierBigint.PublicKey); | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(paillierBigint.PrivateKey); | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(2048); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
144179
3319
467
Updatedbigint-crypto-utils@^2.3.1