This is a node.js implementation relying on the node-bignum library by Stephan Thomas. Bignum is an arbitrary precision integral arithmetic for Node.js using OpenSSL. For a pure javascript implementation that can be used on browsers, please visit paillier-bigint.
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 product of two ciphertexts will decrypt to the sum of their corresponding plaintexts,
D( E(m1) · E(m2) ) mod n^2 = m1 + m2 mod n
The product of a ciphertext with a plaintext raising g will decrypt to the sum of the corresponding plaintexts,
D( E(m1) · g^(m2) ) mod n^2 = m1 + m2 mod n
An encrypted plaintext raised to the power of another plaintext will decrypt to the product of the two plaintexts,
D( E(m1)^(m2) mod n^2 ) = m1 · m2 mod n,
D( E(m2)^(m1) mod n^2 ) = m1 · m2 mod n.
More generally, an encrypted plaintext raised to a constant k will decrypt to the product of the plaintext and the constant,
D( E(m1)^k mod n^2 ) = k · m1 mod n.
However, given the Paillier encryptions of two messages there is no known way to compute an encryption of the product of these messages without knowing the private key.
- Define the bit length of the modulus
n
, orkeyLength
in bits. - Choose two large prime numbers
p
andq
randomly and independently of each other such thatgcd( p·q, (p-1)(q-1) )=1
andn=p·q
has a key length of keyLength. For instance:- Generate a random prime
p
with a bit length ofkeyLength/2 + 1
. - Generate a random prime
q
with a bit length ofkeyLength/2
. - Repeat until the bitlength of
n=p·q
iskeyLength
.
- Generate a random prime
- Compute
λ = lcm(p-1, q-1)
withlcm(a, b) = a·b / gcd(a, b)
. - Select a generator
g
inZ*
ofn^2
.g
can be computed as follows (there are other ways):- Generate randoms
α
andβ
inZ*
ofn
. - Compute
g=( α·n + 1 ) β^n mod n^2
.
- Generate randoms
- Compute
μ=( L( g^λ mod n^2 ) )^(-1) mod n
whereL(x)=(x-1)/n
.
The public (encryption) key is (n, g).
The private (decryption) key is (λ, μ).
Let m
in Z*
of n
be the clear-text message,
-
Select random integer
r
in(1, n^2)
. -
Compute ciphertext as:
c = g^m · r^n mod n^2
Let c
be the ciphertext to decrypt, where c
in (0, n^2)
.
- Compute the plaintext message as:
m = L( c^λ mod n^2 ) · μ mod n
Every input number should be a string in base 10, an integer, or a BigNum. All the output numbers are instances of BigNum.
// import paillier
const paillier = require('paillier.js');
// synchronous creation of a random private, public key pair for the Paillier cyrptosystem
const {publicKey, privateKey} = paillier.generateRandomKeys(3072);
// asynchronous creation of a random private, public key pair for the Paillier cyrptosystem (ONLY from async function)
const {publicKey, privateKey} = await paillier.generateRandomKeysAsync(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, p, q, publicKey);
// encrypt m
let c = publicKey.encrypt(m);
// decrypt c
let d = privateKey.decrypt(c);
// homomorphic addition of two chipertexts (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
See usage examples in example.js.
- PaillierPublicKey
Class for a Paillier public key
- PaillierPrivateKey
Class for Paillier private keys.
- generateRandomKeys(bitLength, simplevariant) ⇒
KeyPair
Generates a pair private, public key for the Paillier cryptosystem in synchronous mode
- generateRandomKeysAsync(bitLength, simplevariant) ⇒
Promise.<KeyPair>
Generates a pair private, public key for the Paillier cryptosystem in asynchronous mode
- KeyPair :
Object
Class for a Paillier public key
Kind: global class
- PaillierPublicKey
- new PaillierPublicKey(n, g)
- .bitLength ⇒
number
- .encrypt(m) ⇒
bignum
- .addition(...ciphertexts) ⇒
bignum
- .multiply(c, k) ⇒
bignum
Creates an instance of class PaillierPublicKey
Param | Type | Description |
---|---|---|
n | bignum | string | number |
the public modulo |
g | bignum | string | number |
the public generator |
Get the bit length of the public modulo
Kind: instance property of PaillierPublicKey
Returns: number
- - bit length of the public modulo
Paillier public-key encryption
Kind: instance method of PaillierPublicKey
Returns: bignum
- - the encryption of m with this public key
Param | Type | Description |
---|---|---|
m | bignum | string | number |
a cleartext number |
Homomorphic addition
Kind: instance method of PaillierPublicKey
Returns: bignum
- - the encryption of (m_1 + ... + m_2) with this public key
Param | Type | Description |
---|---|---|
...ciphertexts | bignums |
2 or more (big) numbers (m_1,..., m_n) encrypted with this public key |
Pseudo-homomorphic paillier multiplication
Kind: instance method of PaillierPublicKey
Returns: bignum
- - the ecnryption of k·m with this public key
Param | Type | Description |
---|---|---|
c | bignum |
a number m encrypted with this public key |
k | bignum | string | number |
either a cleartext message (number) or a scalar |
Class for Paillier private keys.
Kind: global class
- PaillierPrivateKey
- new PaillierPrivateKey(lambda, mu, publicKey, [p], [q])
- .bitLength ⇒
number
- .n ⇒
bignum
- .decrypt(c) ⇒
bignum
Creates an instance of class PaillierPrivateKey
Param | Type | Default | Description |
---|---|---|---|
lambda | bignum | string | number |
||
mu | bignum | string | number |
||
publicKey | PaillierPublicKey |
||
[p] | bignum | string | number |
|
a big prime |
[q] | bignum | string | number |
|
a big prime |
Get the bit length of the public modulo
Kind: instance property of PaillierPrivateKey
Returns: number
- - bit length of the public modulo
Get the public modulo n=p·q
Kind: instance property of PaillierPrivateKey
Returns: bignum
- - the public modulo n=p·q
Paillier private-key decryption
Kind: instance method of PaillierPrivateKey
Returns: bignum
- - the decryption of c with this private key
Param | Type | Description |
---|---|---|
c | bignum | string |
a (big) number encrypted with the public key |
generateRandomKeys(bitLength, simplevariant) ⇒ KeyPair
Generates a pair private, public key for the Paillier cryptosystem in synchronous mode
Kind: global function
Returns: KeyPair
- - a pair of public, private keys
Param | Type | Default | Description |
---|---|---|---|
bitLength | number |
4096 |
the bit lenght of the public modulo |
simplevariant | boolean |
false |
use the simple variant to compute the generator |
generateRandomKeysAsync(bitLength, simplevariant) ⇒ Promise.<KeyPair>
Generates a pair private, public key for the Paillier cryptosystem in asynchronous mode
Kind: global function
Returns: Promise.<KeyPair>
- - a promise that returns a KeyPair if resolve
Param | Type | Default | Description |
---|---|---|---|
bitLength | number |
4096 |
the bit lenght of the public modulo |
simplevariant | boolean |
false |
use the simple variant to compute the generator |
Kind: global typedef
Properties
Name | Type | Description |
---|---|---|
publicKey | PaillierPublicKey |
a Paillier's public key |
privateKey | PaillierPrivateKey |
the associated Paillier's private key |