SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
paillier.cpp
Go to the documentation of this file.
1 /*
2 SeComLib
3 Copyright 2012-2013 TU Delft, Information Security & Privacy Lab (http://isplab.tudelft.nl/)
4 
5 Contributors:
6 Inald Lagendijk (R.L.Lagendijk@TUDelft.nl)
7 Mihai Todor (todormihai@gmail.com)
8 Thijs Veugen (P.J.M.Veugen@tudelft.nl)
9 Zekeriya Erkin (z.erkin@tudelft.nl)
10 
11 Licensed under the Apache License, Version 2.0 (the "License");
12 you may not use this file except in compliance with the License.
13 You may obtain a copy of the License at
14 
15 http://www.apache.org/licenses/LICENSE-2.0
16 
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
30 #include "paillier.h"
31 
32 namespace SeComLib {
33 namespace Core {
39  }
40 
45  PaillierCiphertext::PaillierCiphertext (const std::shared_ptr<BigInteger> &encryptionModulus) :
46  CiphertextBase<PaillierCiphertext> (encryptionModulus) {
47  }
48 
54  PaillierCiphertext::PaillierCiphertext (const BigInteger &data, const std::shared_ptr<BigInteger> &encryptionModulus) :
55  CiphertextBase<PaillierCiphertext> (data, encryptionModulus) {
56  }
57 
61  }
62 
67  PaillierRandomizer::PaillierRandomizer (const BigInteger &data) : RandomizerBase(data) {
68  }
69 
73  Paillier::Paillier () : CryptoProvider<PaillierPublicKey, PaillierPrivateKey, PaillierCiphertext, PaillierRandomizer>(Utils::Config::GetInstance().GetParameter("Core.Paillier.keySize", 1024)) {
74  }
75 
81  Paillier::Paillier (const PaillierPublicKey &publicKey) : CryptoProvider<PaillierPublicKey, PaillierPrivateKey, PaillierCiphertext, PaillierRandomizer>(publicKey, Utils::Config::GetInstance().GetParameter("Core.Paillier.keySize", 1024)) {
82  //C++ doesn't allow us to call a virtual method in the constructor of the base class
83  this->doPrecomputations();
84  }
85 
92  Paillier::Paillier (const PaillierPublicKey &publicKey, const PaillierPrivateKey &privateKey) :
93  CryptoProvider<PaillierPublicKey, PaillierPrivateKey, PaillierCiphertext, PaillierRandomizer>(publicKey, privateKey, Utils::Config::GetInstance().GetParameter("Core.Paillier.keySize", 1024)) {
94  //C++ doesn't allow us to call a virtual method in the constructor of the base class
95  this->doPrecomputations();
96  }
97 
107  unsigned int primeLength = (unsigned int)(this->keyLength / 2);
108 
109  do {
110  this->privateKey.p = RandomProvider::GetInstance().GetMaxLengthRandomPrime(primeLength);
111  this->privateKey.q = RandomProvider::GetInstance().GetMaxLengthRandomPrime(primeLength);
112 
113  //std::cout << this->privateKey.p.GetSize() << std::endl;
114  //std::cout << this->privateKey.q.GetSize() << std::endl;
115 
117  while (this->privateKey.p == this->privateKey.q) {
118  this->privateKey.p = RandomProvider::GetInstance().GetMaxLengthRandomPrime(primeLength);
119  }
120 
122  this->publicKey.n = this->privateKey.p * this->privateKey.q;
123 
124  this->nMinusOne = this->publicKey.n - 1;
125  this->nSquared = this->publicKey.n.GetPow(2);
126 
127  //std::cout << this->n.GetSize() << std::endl;
128  }
129  while (this->publicKey.n.GetSize() != this->keyLength);
130 
131  //std::cout << this->publicKey.n.GetSize() << std::endl;
132 
133  #ifdef USE_STANDARD_PAILLIER_ALGORITHM
134 
137  this->privateKey.lambda = BigInteger::Lcm(this->privateKey.p - 1, this->privateKey.q - 1);
138 
140  this->publicKey.g = RandomProvider::GetInstance().GetRandomInteger(this->keyLength * this->keyLength);
141 
143  this->privateKey.mu = this->L(this->publicKey.g.GetPowModN(this->privateKey.lambda, this->nSquared), this->publicKey.n).InvertModN(this->publicKey.n);
144 
145  #else
146 
149  this->publicKey.g = this->publicKey.n + 1;
150 
152  /*
154  BigInteger phi = (this->privateKey.p - 1) * (this->privateKey.q - 1);
156  this->privateKey.lambda = phi;
158  this->privateKey.mu = phi.InvertModN(this->publicKey.n);
159  */
160 
161  #endif
162 
163  //precompute values for optimization purposes
164  this->doPrecomputations();
165 
166  return true;
167  }
168 
176  BigInteger Paillier::DecryptInteger (const Paillier::Ciphertext &ciphertext) const {
177  if (!this->hasPrivateKey) {
178  throw std::runtime_error("This operation requires the private key.");
179  }
180 
181  #ifdef USE_STANDARD_PAILLIER_ALGORITHM
182  BigInteger output = (this->L(ciphertext.data.GetPowModN(this->privateKey.lambda, this->nSquared), this->publicKey.n) * this->privateKey.mu) % this->publicKey.n;
186  #else
187 
195  BigInteger mp = (this->L(ciphertext.data.GetPowModN(this->pMinusOne, this->pSquared), this->privateKey.p) * this->hp) % this->privateKey.p;
196  BigInteger mq = (this->L(ciphertext.data.GetPowModN(this->qMinusOne, this->qSquared), this->privateKey.q) * this->hq) % this->privateKey.q;
197  BigInteger output = (mp * this->qTimesQInvModP + mq * this->pTimesPInvModQ) % this->publicKey.n;
198  #endif
199 
201  if (output > this->positiveNegativeBoundary) {
202  output -= this->GetMessageSpaceUpperBound();
203  }
204 
205  return output;
206  }
207 
214  Paillier::Ciphertext Paillier::EncryptIntegerNonrandom (const BigInteger &plaintext) const {
223  Ciphertext output(this->encryptionModulus);
224 
226 
227  #ifdef USE_STANDARD_PAILLIER_ALGORITHM
228 
230  //compute c = g^m (mod n^2)
231  if (plaintext < 0) {
232  output.data = this->publicKey.g.GetPowModN(this->GetMessageSpaceUpperBound() + plaintext, this->nSquared);
233  }
234  else {
235  output.data = this->publicKey.g.GetPowModN(plaintext, this->nSquared);
236  }
237  #else
238 
240  //compute c = n * m + 1 (we skip the modulo operation, since it's done in RandomizeCiphertext)
241  if (plaintext < 0) {
242  output.data = this->publicKey.n * (this->GetMessageSpaceUpperBound() + plaintext) + 1;
243  }
244  else {
245  output.data = this->publicKey.n * plaintext + 1;
246  }
247  #endif
248 
249  return output;
250  }
251 
260  return Randomizer((RandomProvider::GetInstance().GetRandomInteger(this->nMinusOne) + 1).GetPowModN(this->publicKey.n, this->nSquared));
261  }
262 
270  return Ciphertext((ciphertext.data * this->randomizerCache->Pop().randomizer.data) % this->GetEncryptionModulus(), this->encryptionModulus);
271  }
272 
276  const BigInteger &Paillier::GetMessageSpaceUpperBound () const {
277  return this->publicKey.n;
278  }
279 
284  return this->publicKey.n.GetSize();
285  }
286 
294  BigInteger Paillier::L (const BigInteger &input, const BigInteger &d) const {
295  BigInteger output;
296 
297  output = (input - 1) / d;
298 
299  return output;
300  }
301 
305  if (this->precomputeSpeedupValues) {
306  this->nSquared = this->publicKey.n.GetPow(2);
307  this->nMinusOne = this->publicKey.n - 1;
308  }
309 
310  if (this->hasPrivateKey) {
312  this->pMinusOne = this->privateKey.p - 1;
313  this->qMinusOne = this->privateKey.q - 1;
314  this->pSquared = this->privateKey.p * this->privateKey.p;
315  this->qSquared = this->privateKey.q * this->privateKey.q;
316  this->hp = this->L(this->publicKey.g.GetPowModN(this->pMinusOne, this->pSquared), this->privateKey.p).InvertModN(this->privateKey.p);
317  this->hq = this->L(this->publicKey.g.GetPowModN(this->qMinusOne, this->qSquared), this->privateKey.q).InvertModN(this->privateKey.q);
318 
320  try {
321  this->pTimesPInvModQ = this->privateKey.p * this->privateKey.p.GetInverseModN(this->privateKey.q);
322  this->qTimesQInvModP = this->privateKey.q * this->privateKey.q.GetInverseModN(this->privateKey.p);
323  }
325  catch (std::runtime_error) {
326  //if gcd(p, q) != 1, throw an error
327  throw std::runtime_error("p and q are not coprime.");
328  }
329  }
330 
331  //set the encryption modulus, @f$ n^2 @f$
332  this->encryptionModulus = std::make_shared<BigInteger>(this->nSquared);
333 
334  //precompute the limit between positive and negative values in the message space
336 
338  this->randomizerCache = std::unique_ptr<RandomizerCacheType>(new RandomizerCacheType(*this, "Core.RandomizerCache"));
339 
340  this->encryptedZero = this->EncryptInteger(BigInteger(0));
341 
342  this->encryptedOne = this->EncryptInteger(BigInteger(1));
343  }
344 
345 }//namespace Core
346 }//namespace SeComLib
BigInteger pSquared
Definition: paillier.h:154
BigInteger qTimesQInvModP
Definition: paillier.h:166
BigInteger pMinusOne
Definition: paillier.h:145
RandomizerCache< RandomizerContainer< CryptoProvider< PaillierPublicKey, PaillierPrivateKey, PaillierCiphertext, PaillierRandomizer >, RandomizerCacheParameters > > RandomizerCacheType
Data type of the randomizer cache.
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
Definition: paillier.cpp:176
BigInteger L(const BigInteger &input, const BigInteger &d) const
L function evaluator.
Definition: paillier.cpp:294
virtual const BigInteger & GetMessageSpaceUpperBound() const
Returns the message space upper bound.
Definition: paillier.cpp:276
RandomizerBase struct.
virtual bool GenerateKeys()
Definition: paillier.cpp:105
BigInteger qMinusOne
Definition: paillier.h:148
virtual PaillierCiphertext EncryptInteger(const BigInteger &plaintext) const
Encrypt an integer and apply randomization.
BigInteger nMinusOne
Contains .
Definition: paillier.h:151
Paillier()
Default constructor.
Definition: paillier.cpp:73
PaillierCiphertext()
Default constructor.
Definition: paillier.cpp:37
BigInteger qSquared
Definition: paillier.h:157
PaillierCiphertext encryptedZero
Contains [0] used as initializer for homomorphic addition accumulators. Precompute it for optimizatio...
virtual Ciphertext RandomizeCiphertext(const Ciphertext &ciphertext) const
Randomize encrypted number with a self-generated random value.
Definition: paillier.cpp:269
BigInteger pTimesPInvModQ
Definition: paillier.h:163
virtual size_t GetMessageSpaceSize() const
Returns the message space bit size.
Definition: paillier.cpp:283
virtual Ciphertext EncryptIntegerNonrandom(const BigInteger &plaintext) const
Encrypt number without randomization.
Definition: paillier.cpp:214
BigInteger nSquared
Contains .
Definition: paillier.h:160
virtual Randomizer GetRandomizer() const
Compute the random factor required for the encryption operation.
Definition: paillier.cpp:259
BigInteger data
The ciphertext data.
Paillier cipertext.
Definition: paillier.h:77
bool precomputeSpeedupValues
Boolean flag that indicates wether doPrecomputations() should precompute certain values.
CiphertextBase template class.
PaillierRandomizer()
Default constructor.
Definition: paillier.cpp:60
Definition of class Paillier.
The randomizer type for Paillier.
Definition: paillier.h:92
BigInteger positiveNegativeBoundary
Contains the delimiter between positive and negative values in the message space (usually ) ...
const BigInteger & GetEncryptionModulus() const
Returns the modulus required for reducing the encryption after randomization.
Template abstract base class for homomorphic encryption primitives.
bool hasPrivateKey
Boolean flag that enables decryption if the private key is present.
virtual void doPrecomputations()
Precompute values for speedups.
Definition: paillier.cpp:304
The private key container structure for the Paillier cryptosystem.
Definition: paillier.h:60
The public key container structure for the Paillier cryptosystem.
Definition: paillier.h:49