paillier-bigint
Advanced tools
Comparing version 2.0.0 to 3.0.0
{ | ||
"name": "paillier-bigint", | ||
"version": "2.0.0", | ||
"description": "An implementation of the Paillier cryptosystem using native JS (stage 3) implementation of BigInt", | ||
"version": "3.0.0", | ||
"description": "An implementation of the Paillier cryptosystem using native JS (ECMA 2020) implementation of BigInt", | ||
"keywords": [ | ||
@@ -9,3 +9,4 @@ "paillier", | ||
"crypto", | ||
"cryptosystem" | ||
"cryptosystem", | ||
"bigint" | ||
], | ||
@@ -19,33 +20,52 @@ "license": "MIT", | ||
"repository": "github:juanelas/paillier-bigint", | ||
"main": "./dist/paillier-bigint-latest.node.js", | ||
"browser": "./dist/paillier-bigint-latest.browser.mod.js", | ||
"main": "./lib/index.node.js", | ||
"browser": "./lib/index.browser.mod.js", | ||
"types": "./types/index.d.ts", | ||
"directories": { | ||
"build": "./build", | ||
"dist": "./dist", | ||
"lib": "./lib", | ||
"src": "./src", | ||
"test": "./test" | ||
"test": "./test", | ||
"types": "./types" | ||
}, | ||
"scripts": { | ||
"test": "node --experimental-worker node_modules/mocha/bin/_mocha --timeout 600000", | ||
"build": "node build/build.rollup.js", | ||
"build:browserTests": "node build/build.browser.tests.js", | ||
"build:docs": "jsdoc2md --template=README.hbs --files ./src/main.js > README.md", | ||
"build:all": "npm run build && npm run build:browserTests && npm run build:docs", | ||
"prepublishOnly": "npm run build && npm run build:docs" | ||
"test": "mocha", | ||
"build:js": "rollup -c build/rollup.config.js", | ||
"build:standard": "standard --fix", | ||
"build:browserTests": "rollup -c build/rollup.tests.config.js", | ||
"build:docs": "jsdoc2md --template=./src/doc/readme-template.md --files ./src/js/index.js > README.md", | ||
"build:dts": "node build/build.dts.js", | ||
"build": "run-s build:**", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"standard": { | ||
"env": [ | ||
"mocha" | ||
], | ||
"globals": [ | ||
"BigInt" | ||
], | ||
"ignore": [ | ||
"/test/browser/", | ||
"/lib/index.browser.bundle.js", | ||
"/lib/index.browser.bundle.mod.js" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@rollup/plugin-commonjs": "^11.0.2", | ||
"@rollup/plugin-multi-entry": "^3.0.0", | ||
"@rollup/plugin-node-resolve": "^7.1.1", | ||
"@rollup/plugin-replace": "^2.3.1", | ||
"chai": "^4.2.0", | ||
"eslint": "^6.8.0", | ||
"jsdoc-to-markdown": "^5.0.3", | ||
"mocha": "^7", | ||
"rollup": "^1.29.1", | ||
"rollup-plugin-babel-minify": "^9.1.1", | ||
"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" | ||
"mocha": "^7.1.1", | ||
"npm-run-all": "^4.1.5", | ||
"rollup": "^2.2.0", | ||
"rollup-plugin-terser": "^5.3.0", | ||
"standard": "^14.3.3", | ||
"typescript": "^3.8.3" | ||
}, | ||
"dependencies": { | ||
"bigint-crypto-utils": "^2.4.2" | ||
"bigint-crypto-utils": "^2.5.2" | ||
} | ||
} |
132
README.md
@@ -0,1 +1,3 @@ | ||
[![JavaScript Style Guide](https://cdn.rawgit.com/standard/standard/master/badge.svg)](https://github.com/standard/standard) | ||
# paillier-bigint | ||
@@ -7,4 +9,3 @@ | ||
The Paillier cryptosystem, named after and invented by Pascal Paillier in 1999, is a probabilistic asymmetric algorithm | ||
for public key cryptography. A notable feature of the Paillier cryptosystem is its homomorphic properties. | ||
The Paillier cryptosystem, named after and invented by Pascal Paillier in 1999, is a probabilistic asymmetric algorithm for public key cryptography. A notable feature of the Paillier cryptosystem is its homomorphic properties. | ||
@@ -78,72 +79,39 @@ ## Homomorphic properties | ||
For web browsers, you can also directly download the minimised version of the [IIFE file](https://aw.githubusercontent.com/juanelas/paillier-bigint/master/dist/paillier-bigint-latest.browser.min.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/paillier-bigint/master/dist/paillier-bigint-latest.browser.mod.min.js) from GitHub. | ||
For web browsers, you can also directly download the minimized version of the [IIFE file](https://aw.githubusercontent.com/juanelas/paillier-bigint/master/dist/index.browser.bundle.js) or the [ES6 module](https://raw.githubusercontent.com/juanelas/paillier-bigint/master/dist/index.browser.bundle.mod.js) from GitHub. | ||
## Usage | ||
Every input number should be a string in base 10, an integer, or a bigint. All the output numbers are of type `bigint`. | ||
An example with Node.js: | ||
```javascript | ||
// import paillier | ||
const paillier = require('paillier-bigint.js'); | ||
// import paillier in node.js | ||
const paillier = require('paillier-bigint.js') | ||
// import paillier in native JS | ||
import * as paillier from 'paillier-bigint' | ||
// (asynchronous) creation of a random private, public key pair for the Paillier cryptosystem | ||
const {publicKey, privateKey} = await paillier.generateRandomKeys(3072); | ||
const {publicKey, privateKey} = await paillier.generateRandomKeys(3072) | ||
// optionally, you can create your public/private keys from known parameters | ||
const publicKey = new paillier.PublicKey(n, g); | ||
const privateKey = new paillier.PrivateKey(lambda, mu, publicKey); | ||
const publicKey = new paillier.PublicKey(n, g) | ||
const privateKey = new paillier.PrivateKey(lambda, mu, publicKey) | ||
// encrypt m | ||
let c = publicKey.encrypt(m); | ||
let c = publicKey.encrypt(m) | ||
// decrypt c | ||
let d = privateKey.decrypt(c); | ||
let d = privateKey.decrypt(c) | ||
// homomorphic addition of two ciphertexts (encrypted numbers) | ||
let c1 = publicKey.encrypt(m1); | ||
let c2 = publicKey.encrypt(m2); | ||
let encryptedSum = publicKey.addition(c1, c2); | ||
let sum = privateKey.decrypt(encryptedSum); // m1 + m2 | ||
let c1 = publicKey.encrypt(m1) | ||
let c2 = publicKey.encrypt(m2) | ||
let encryptedSum = publicKey.addition(c1, c2) | ||
let sum = privateKey.decrypt(encryptedSum) // m1 + m2 | ||
// multiplication by k | ||
let c1 = publicKey.encrypt(m1); | ||
let encryptedMul = publicKey.multiply(c1, k); | ||
let mul = privateKey.decrypt(encryptedMul); // k · m1 | ||
let c1 = publicKey.encrypt(m1) | ||
let encryptedMul = publicKey.multiply(c1, k) | ||
let mul = privateKey.decrypt(encryptedMul) // k · m1 | ||
``` | ||
From a browser, you can just load the module in a html page as: | ||
```html | ||
<script type="module"> | ||
import * as paillier from 'paillier-bigint-latest.browser.mod.min.js'; | ||
# JS Doc | ||
// (asynchronous) creation of a random private, public key pair for the Paillier cryptosystem | ||
paillier.generateRandomKeys(3072).then((keyPair) => { | ||
const publicKey = keyPair.publicKey; | ||
const privateKey = keyPair.privateKey; | ||
// ... | ||
}); | ||
// You can also create your public/private keys from known parameters | ||
const publicKey = new paillier.PublicKey(n, g); | ||
const privateKey = new paillier.PrivateKey(lambda, mu, publicKey); | ||
// encrypt m is just | ||
let c = publicKey.encrypt(m); | ||
// decrypt c | ||
let d = privateKey.decrypt(c); | ||
// homomorphic addition of two ciphertexts (encrypted numbers) | ||
let c1 = publicKey.encrypt(m1); | ||
let c2 = publicKey.encrypt(m2); | ||
let encryptedSum = publicKey.addition(c1, c2); | ||
let sum = privateKey.decrypt(encryptedSum); // m1 + m2 | ||
// multiplication by k | ||
let c1 = publicKey.encrypt(m1); | ||
let encryptedMul = publicKey.multiply(c1, k); | ||
let mul = privateKey.decrypt(encryptedMul); // k · m1 | ||
</script> | ||
``` | ||
## Classes | ||
@@ -161,7 +129,7 @@ | ||
<dl> | ||
<dt><a href="#generateRandomKeys">generateRandomKeys</a> ⇒ <code>Promise</code></dt> | ||
<dt><a href="#generateRandomKeys">generateRandomKeys</a> ⇒ <code><a href="#KeyPair">Promise.<KeyPair></a></code></dt> | ||
<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. | ||
<dt><a href="#generateRandomKeysSync">generateRandomKeysSync</a> ⇒ <code><a href="#KeyPair">KeyPair</a></code></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> | ||
@@ -204,4 +172,4 @@ </dd> | ||
| --- | --- | --- | | ||
| n | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | the public modulo | | ||
| g | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | the public generator | | ||
| n | <code>bigint</code> | the public modulo | | ||
| g | <code>bigint</code> \| <code>number</code> | the public generator | | ||
@@ -225,3 +193,3 @@ <a name="PublicKey+bitLength"></a> | ||
| --- | --- | --- | | ||
| m | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | a cleartext number | | ||
| m | <code>bigint</code> | a bigint representation of a cleartext message | | ||
@@ -238,3 +206,3 @@ <a name="PublicKey+addition"></a> | ||
| --- | --- | --- | | ||
| ...ciphertexts | <code>bigint</code> \| <code>number</code> | n >= 2 ciphertexts (c_1,..., c_n) that are the encryption of (m_1, ..., m_n) with this public key | | ||
| ...ciphertexts | <code>bigint</code> | n >= 2 ciphertexts (c_1,..., c_n) that are the encryption of (m_1, ..., m_n) with this public key | | ||
@@ -252,3 +220,3 @@ <a name="PublicKey+multiply"></a> | ||
| c | <code>bigint</code> | a number m encrypted with this public key | | ||
| k | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | either a cleartext message (number) or a scalar | | ||
| k | <code>bigint</code> \| <code>number</code> | either a bigint or a number | | ||
@@ -274,7 +242,7 @@ <a name="PrivateKey"></a> | ||
| --- | --- | --- | --- | | ||
| lambda | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | | | | ||
| mu | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | | | | ||
| lambda | <code>bigint</code> | | | | ||
| mu | <code>bigint</code> | | | | ||
| publicKey | <code>PaillierPublicKey</code> | | | | ||
| [p] | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | <code></code> | a big prime | | ||
| [q] | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | <code></code> | a big prime | | ||
| [p] | <code>bigint</code> | <code></code> | a big prime | | ||
| [q] | <code>bigint</code> | <code></code> | a big prime | | ||
@@ -305,11 +273,11 @@ <a name="PrivateKey+bitLength"></a> | ||
| --- | --- | --- | | ||
| c | <code>bigint</code> \| <code>stringBase10</code> | a (big) number encrypted with the public key | | ||
| c | <code>bigint</code> | a bigint encrypted with the public key | | ||
<a name="generateRandomKeys"></a> | ||
## generateRandomKeys ⇒ <code>Promise</code> | ||
## generateRandomKeys ⇒ [<code>Promise.<KeyPair></code>](#KeyPair) | ||
Generates a pair private, public key for the Paillier cryptosystem. | ||
**Kind**: global constant | ||
**Returns**: <code>Promise</code> - - a promise that resolves to a [KeyPair](#KeyPair) of public, private keys | ||
**Returns**: [<code>Promise.<KeyPair></code>](#KeyPair) - - a promise that resolves to a [KeyPair](#KeyPair) of public, private keys | ||
@@ -323,8 +291,8 @@ | Param | Type | Default | Description | | ||
## generateRandomKeysSync ⇒ | ||
Generates a pair private, public key for the Paillier cryptosystem in synchronous mode. | ||
## generateRandomKeysSync ⇒ [<code>KeyPair</code>](#KeyPair) | ||
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 | ||
**Returns**: [<code>KeyPair</code>](#KeyPair) - - a [KeyPair](#KeyPair) of public, private keys | ||
@@ -358,4 +326,4 @@ | Param | Type | Default | Description | | ||
| --- | --- | --- | | ||
| n | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | the public modulo | | ||
| g | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | the public generator | | ||
| n | <code>bigint</code> | the public modulo | | ||
| g | <code>bigint</code> \| <code>number</code> | the public generator | | ||
@@ -379,3 +347,3 @@ <a name="PublicKey+bitLength"></a> | ||
| --- | --- | --- | | ||
| m | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | a cleartext number | | ||
| m | <code>bigint</code> | a bigint representation of a cleartext message | | ||
@@ -392,3 +360,3 @@ <a name="PublicKey+addition"></a> | ||
| --- | --- | --- | | ||
| ...ciphertexts | <code>bigint</code> \| <code>number</code> | n >= 2 ciphertexts (c_1,..., c_n) that are the encryption of (m_1, ..., m_n) with this public key | | ||
| ...ciphertexts | <code>bigint</code> | n >= 2 ciphertexts (c_1,..., c_n) that are the encryption of (m_1, ..., m_n) with this public key | | ||
@@ -406,3 +374,3 @@ <a name="PublicKey+multiply"></a> | ||
| c | <code>bigint</code> | a number m encrypted with this public key | | ||
| k | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | either a cleartext message (number) or a scalar | | ||
| k | <code>bigint</code> \| <code>number</code> | either a bigint or a number | | ||
@@ -430,7 +398,7 @@ <a name="PrivateKey"></a> | ||
| --- | --- | --- | --- | | ||
| lambda | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | | | | ||
| mu | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | | | | ||
| lambda | <code>bigint</code> | | | | ||
| mu | <code>bigint</code> | | | | ||
| publicKey | <code>PaillierPublicKey</code> | | | | ||
| [p] | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | <code></code> | a big prime | | ||
| [q] | <code>bigint</code> \| <code>stringBase10</code> \| <code>number</code> | <code></code> | a big prime | | ||
| [p] | <code>bigint</code> | <code></code> | a big prime | | ||
| [q] | <code>bigint</code> | <code></code> | a big prime | | ||
@@ -461,3 +429,3 @@ <a name="PrivateKey+bitLength"></a> | ||
| --- | --- | --- | | ||
| c | <code>bigint</code> \| <code>stringBase10</code> | a (big) number encrypted with the public key | | ||
| c | <code>bigint</code> | a bigint encrypted with the public key | | ||
@@ -475,3 +443,1 @@ <a name="KeyPair"></a> | ||
* * * |
@@ -8,3 +8,3 @@ const _ZERO = BigInt(0); | ||
* | ||
* @param {number|bigint} a | ||
* @param {number | bigint} a | ||
* | ||
@@ -124,3 +124,3 @@ * @returns {bigint} the absolute value of a | ||
* | ||
* @return {Promise} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite) | ||
* @returns {Promise<boolean>} A promise that resolves to a boolean that is either true (a probably prime number) or false (definitely composite) | ||
*/ | ||
@@ -260,3 +260,3 @@ async function isProbablyPrime(w, iterations = 16) { | ||
* | ||
* @returns {Promise} A promise that resolves to a bigint probable prime of bitLength bits. | ||
* @returns {Promise<bigint>} A promise that resolves to a bigint probable prime of bitLength bits. | ||
*/ | ||
@@ -363,7 +363,10 @@ function prime(bitLength, iterations = 16) { | ||
const byteLength = Math.ceil(bitLength / 8); | ||
let rndBytes = randBytesSync(byteLength, false); | ||
// Fill with 0's the extra bits | ||
rndBytes[0] = rndBytes[0] & (2 ** (bitLength % 8) - 1); | ||
const rndBytes = randBytesSync(byteLength, false); | ||
const bitLengthMod8 = bitLength % 8; | ||
if (bitLengthMod8) { | ||
// Fill with 0's the extra bits | ||
rndBytes[0] = rndBytes[0] & (2 ** bitLengthMod8 - 1); | ||
} | ||
if (forceLength) { | ||
let mask = (bitLength % 8) ? 2 ** ((bitLength % 8) - 1) : 128; | ||
const mask = bitLengthMod8 ? 2 ** (bitLengthMod8 - 1) : 128; | ||
rndBytes[0] = rndBytes[0] | mask; | ||
@@ -380,3 +383,3 @@ } | ||
* | ||
* @returns {Promise} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes | ||
* @returns {Promise<Buffer|Uint8Array>} A promise that resolves to a Buffer/UInt8Array (Node.js/Browser) filled with cryptographically secure random bytes | ||
*/ | ||
@@ -817,76 +820,78 @@ function randBytes(byteLength, forceLength = false) { | ||
// For the browser test builder to work you MUST import them module in a variable that | ||
// is the camelised version of the package name. | ||
// Every test file (you can create as many as you want) should start like this | ||
// Please, do NOT touch. They will be automatically removed for browser tests --> | ||
// <-- | ||
const bitLengths = [1024, 2048, 3072]; | ||
for (const bitLength of bitLengths) { | ||
describe(`Testing Paillier with keys of ${bitLength} bits`, function () { | ||
let keyPair; | ||
const tests = 32; | ||
let numbers = []; | ||
let ciphertexts = []; | ||
describe(`Testing Paillier with keys of ${bitLength} bits`, function () { | ||
this.timeout(90000); | ||
let keyPair; | ||
const tests = 32; | ||
const numbers = []; | ||
const ciphertexts = []; | ||
describe(`generateRandomKeys(${bitLength})`, function () { | ||
it(`it should return a publicKey and a privateKey with public modulus of ${bitLength} bits`, async function () { | ||
keyPair = await paillierBigint.generateRandomKeys(bitLength); | ||
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(bitLength); | ||
}); | ||
}); | ||
describe(`generateRandomKeys(${bitLength})`, function () { | ||
it(`it should return a publicKey and a privateKey with public modulus of ${bitLength} bits`, async function () { | ||
keyPair = await _pkg.generateRandomKeys(bitLength); | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(_pkg.PublicKey); | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(_pkg.PrivateKey); | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(bitLength); | ||
}); | ||
}); | ||
describe(`Correctness. For ${tests} random r in (1,n), encrypt r with publicKey and then decrypt with privateKey: D(E(r))`, function () { | ||
it('all should return r', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < tests; i++) { | ||
numbers[i] = bigintCryptoUtilsLatest_browser_mod.randBetween(keyPair.publicKey.n); | ||
ciphertexts[i] = keyPair.publicKey.encrypt(numbers[i]); | ||
const decrypted = keyPair.privateKey.decrypt(ciphertexts[i]); | ||
if (numbers[i] !== decrypted) { | ||
testPassed = false; | ||
break; | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
describe(`Correctness. For ${tests} random r in (1,n), encrypt r with publicKey and then decrypt with privateKey: D(E(r))`, function () { | ||
it('all should return r', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < tests; i++) { | ||
numbers[i] = bigintCryptoUtilsLatest_browser_mod.randBetween(keyPair.publicKey.n); | ||
ciphertexts[i] = keyPair.publicKey.encrypt(numbers[i]); | ||
const decrypted = keyPair.privateKey.decrypt(ciphertexts[i]); | ||
if (numbers[i] !== decrypted) { | ||
testPassed = false; | ||
break | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
describe('Homomorphic properties', function () { | ||
describe(`Homomorphic addtion: D( E(m1)·...·E(m${tests})) mod n^2 )`, function () { | ||
it(`should return m1+...+m${tests} mod n`, function () { | ||
const encSum = keyPair.publicKey.addition(...ciphertexts); | ||
let d = keyPair.privateKey.decrypt(encSum); | ||
const sumNumbers = numbers.reduce((sum, next) => (sum + next) % keyPair.publicKey.n); | ||
chai.expect(d === sumNumbers); | ||
}); | ||
}); | ||
describe(`For all the ${tests} random r, the (pseudo-)homomorphic multiplication: D( E(r)^r mod n^2 )`, function () { | ||
it('should return r^2 mod n', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < numbers.length; i++) { | ||
const encMul = keyPair.publicKey.multiply(ciphertexts[i], numbers[i]); | ||
const d = keyPair.privateKey.decrypt(encMul); | ||
if (d !== bigintCryptoUtilsLatest_browser_mod.modPow(numbers[i], 2, keyPair.publicKey.n)) { | ||
testPassed = false; | ||
break; | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
describe('Homomorphic properties', function () { | ||
describe(`Homomorphic addtion: D( E(m1)·...·E(m${tests})) mod n^2 )`, function () { | ||
it(`should return m1+...+m${tests} mod n`, function () { | ||
const encSum = keyPair.publicKey.addition(...ciphertexts); | ||
const d = keyPair.privateKey.decrypt(encSum); | ||
const sumNumbers = numbers.reduce((sum, next) => (sum + next) % keyPair.publicKey.n); | ||
chai.expect(d === sumNumbers); | ||
}); | ||
}); | ||
describe(`For all the ${tests} random r, the (pseudo-)homomorphic multiplication: D( E(r)^r mod n^2 )`, function () { | ||
it('should return r^2 mod n', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < numbers.length; i++) { | ||
const encMul = keyPair.publicKey.multiply(ciphertexts[i], numbers[i]); | ||
const d = keyPair.privateKey.decrypt(encMul); | ||
if (d !== bigintCryptoUtilsLatest_browser_mod.modPow(numbers[i], 2, keyPair.publicKey.n)) { | ||
testPassed = false; | ||
break | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
}); | ||
}); | ||
} | ||
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); | ||
}); | ||
this.timeout(90000); | ||
it('it should return a publicKey and a privateKey with public modulus of 2048 bits', function () { | ||
const keyPair = _pkg.generateRandomKeysSync(2048); | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(_pkg.PublicKey); | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(_pkg.PrivateKey); | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(2048); | ||
}); | ||
}); |
@@ -1,77 +0,79 @@ | ||
'use strict'; | ||
'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 paillierBigint = require('../dist/paillier-bigint-latest.node'); | ||
const chai = require('chai'); | ||
// Every test file (you can create as many as you want) should start like this | ||
// Please, do NOT touch. They will be automatically removed for browser tests --> | ||
const _pkg = require('../lib/index.node') | ||
const chai = require('chai') | ||
// <-- | ||
const bcu = require('bigint-crypto-utils'); | ||
const bcu = require('bigint-crypto-utils') | ||
const bitLengths = [1024, 2048, 3072]; | ||
const bitLengths = [1024, 2048, 3072] | ||
for (const bitLength of bitLengths) { | ||
describe(`Testing Paillier with keys of ${bitLength} bits`, function () { | ||
let keyPair; | ||
const tests = 32; | ||
let numbers = []; | ||
let ciphertexts = []; | ||
describe(`Testing Paillier with keys of ${bitLength} bits`, function () { | ||
this.timeout(90000) | ||
let keyPair | ||
const tests = 32 | ||
const numbers = [] | ||
const ciphertexts = [] | ||
describe(`generateRandomKeys(${bitLength})`, function () { | ||
it(`it should return a publicKey and a privateKey with public modulus of ${bitLength} bits`, async function () { | ||
keyPair = await paillierBigint.generateRandomKeys(bitLength); | ||
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(bitLength); | ||
}); | ||
}); | ||
describe(`generateRandomKeys(${bitLength})`, function () { | ||
it(`it should return a publicKey and a privateKey with public modulus of ${bitLength} bits`, async function () { | ||
keyPair = await _pkg.generateRandomKeys(bitLength) | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(_pkg.PublicKey) | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(_pkg.PrivateKey) | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(bitLength) | ||
}) | ||
}) | ||
describe(`Correctness. For ${tests} random r in (1,n), encrypt r with publicKey and then decrypt with privateKey: D(E(r))`, function () { | ||
it('all should return r', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < tests; i++) { | ||
numbers[i] = bcu.randBetween(keyPair.publicKey.n); | ||
ciphertexts[i] = keyPair.publicKey.encrypt(numbers[i]); | ||
const decrypted = keyPair.privateKey.decrypt(ciphertexts[i]); | ||
if (numbers[i] !== decrypted) { | ||
testPassed = false; | ||
break; | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
describe(`Correctness. For ${tests} random r in (1,n), encrypt r with publicKey and then decrypt with privateKey: D(E(r))`, function () { | ||
it('all should return r', function () { | ||
let testPassed = true | ||
for (let i = 0; i < tests; i++) { | ||
numbers[i] = bcu.randBetween(keyPair.publicKey.n) | ||
ciphertexts[i] = keyPair.publicKey.encrypt(numbers[i]) | ||
const decrypted = keyPair.privateKey.decrypt(ciphertexts[i]) | ||
if (numbers[i] !== decrypted) { | ||
testPassed = false | ||
break | ||
} | ||
} | ||
chai.expect(testPassed).equals(true) | ||
}) | ||
}) | ||
describe('Homomorphic properties', function () { | ||
describe(`Homomorphic addtion: D( E(m1)·...·E(m${tests})) mod n^2 )`, function () { | ||
it(`should return m1+...+m${tests} mod n`, function () { | ||
const encSum = keyPair.publicKey.addition(...ciphertexts); | ||
let d = keyPair.privateKey.decrypt(encSum); | ||
const sumNumbers = numbers.reduce((sum, next) => (sum + next) % keyPair.publicKey.n); | ||
chai.expect(d === sumNumbers); | ||
}); | ||
}); | ||
describe(`For all the ${tests} random r, the (pseudo-)homomorphic multiplication: D( E(r)^r mod n^2 )`, function () { | ||
it('should return r^2 mod n', function () { | ||
let testPassed = true; | ||
for (let i = 0; i < numbers.length; i++) { | ||
const encMul = keyPair.publicKey.multiply(ciphertexts[i], numbers[i]); | ||
const d = keyPair.privateKey.decrypt(encMul); | ||
if (d !== bcu.modPow(numbers[i], 2, keyPair.publicKey.n)) { | ||
testPassed = false; | ||
break; | ||
} | ||
} | ||
chai.expect(testPassed).equals(true); | ||
}); | ||
}); | ||
}); | ||
}); | ||
describe('Homomorphic properties', function () { | ||
describe(`Homomorphic addtion: D( E(m1)·...·E(m${tests})) mod n^2 )`, function () { | ||
it(`should return m1+...+m${tests} mod n`, function () { | ||
const encSum = keyPair.publicKey.addition(...ciphertexts) | ||
const d = keyPair.privateKey.decrypt(encSum) | ||
const sumNumbers = numbers.reduce((sum, next) => (sum + next) % keyPair.publicKey.n) | ||
chai.expect(d === sumNumbers) | ||
}) | ||
}) | ||
describe(`For all the ${tests} random r, the (pseudo-)homomorphic multiplication: D( E(r)^r mod n^2 )`, function () { | ||
it('should return r^2 mod n', function () { | ||
let testPassed = true | ||
for (let i = 0; i < numbers.length; i++) { | ||
const encMul = keyPair.publicKey.multiply(ciphertexts[i], numbers[i]) | ||
const d = keyPair.privateKey.decrypt(encMul) | ||
if (d !== bcu.modPow(numbers[i], 2, keyPair.publicKey.n)) { | ||
testPassed = false | ||
break | ||
} | ||
} | ||
chai.expect(testPassed).equals(true) | ||
}) | ||
}) | ||
}) | ||
}) | ||
} | ||
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); | ||
}); | ||
}); | ||
this.timeout(90000) | ||
it('it should return a publicKey and a privateKey with public modulus of 2048 bits', function () { | ||
const keyPair = _pkg.generateRandomKeysSync(2048) | ||
chai.expect(keyPair.publicKey).to.be.an.instanceOf(_pkg.PublicKey) | ||
chai.expect(keyPair.privateKey).to.be.an.instanceOf(_pkg.PrivateKey) | ||
chai.expect(keyPair.publicKey.bitLength).to.equal(2048) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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
97505
12
1820
427
1
Updatedbigint-crypto-utils@^2.5.2