-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathpaillier.cpp
70 lines (62 loc) · 2.11 KB
/
paillier.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include "paillier.h"
NTL::ZZ generateCoprimeNumber(const NTL::ZZ& n) {
NTL::ZZ ret;
while (true) {
ret = RandomBnd(n);
if (NTL::GCD(ret, n) == 1) { return ret; }
}
}
Paillier::Paillier() {
/* Length in bits. */
long keyLength = 512;
NTL::ZZ p, q;
GenPrimePair(p, q, keyLength);
modulus = p * q;
generator = modulus + 1;
NTL::ZZ phi = (p - 1) * (q - 1);
// LCM(p, q) = p * q / GCD(p, q);
lambda = phi / NTL::GCD(p - 1, q - 1);
lambdaInverse = NTL::InvMod(lambda, modulus);
}
Paillier::Paillier(const NTL::ZZ& modulus, const NTL::ZZ& lambda) {
this->modulus = modulus;
generator = this->modulus + 1;
this->lambda = lambda;
lambdaInverse = NTL::InvMod(this->lambda, this->modulus);
}
void Paillier::GenPrimePair(NTL::ZZ& p, NTL::ZZ& q,
long keyLength) {
while (true) {
long err = 80;
p = NTL::GenPrime_ZZ(keyLength/2, err);
NTL::ZZ q = NTL::GenPrime_ZZ(keyLength/2, err);
while (p != q) {
q = NTL::GenPrime_ZZ(keyLength/2, err);
}
NTL::ZZ n = p * q;
NTL::ZZ phi = (p - 1) * (q - 1);
if (NTL::GCD(n, phi) == 1) return;
}
}
NTL::ZZ Paillier::encrypt(const NTL::ZZ& message) {
NTL::ZZ random = generateCoprimeNumber(modulus);
NTL::ZZ ciphertext =
NTL::PowerMod(generator, message, modulus * modulus) *
NTL::PowerMod(random, modulus, modulus * modulus);
return ciphertext % (modulus * modulus);
}
NTL::ZZ Paillier::encrypt(const NTL::ZZ& message, const NTL::ZZ& random) {
NTL::ZZ ciphertext =
NTL::PowerMod(generator, message, modulus * modulus) *
NTL::PowerMod(random, modulus, modulus * modulus);
return ciphertext % (modulus * modulus);
}
NTL::ZZ Paillier::decrypt(const NTL::ZZ& ciphertext) {
/* NOTE: NTL::PowerMod will fail if the first input is too large
* (which I assume means larger than modulus).
*/
NTL::ZZ deMasked = NTL::PowerMod(
ciphertext, lambda, modulus * modulus);
NTL::ZZ power = L_function(deMasked);
return (power * lambdaInverse) % modulus;
}