SeComLib
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Macros Pages
test/main.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 */
29 #include "main.h"
30 
40 int main (int argc, char *argv[]) {
41  try {
42  //the first command line parameter always contains the name of the application
43  if (argc > 1) {
44  //a custom configuration file was specified
45  Utils::Config::SetConfigFile(std::string(argv[1]));
46  }
47 
48  Paillier paillierCryptoProvider;
49  OkamotoUchiyama okamotoUchiyamaCryptoProvider;
50  Dgk dgkCryptoProvider(true);//pre-compute decryption map (keep Dgk.l reasonably small for this test)
51  ElGamal elGamalCryptoProvider(true);//pre-compute decryption map (keep ElGamal.messageSpaceThresholdBitSize reasonably small for this test)
52 
53  std::cout << "Generating keys for every crypto provider." << std::endl;
54  paillierCryptoProvider.GenerateKeys();
55  okamotoUchiyamaCryptoProvider.GenerateKeys();
56  dgkCryptoProvider.GenerateKeys();
57  elGamalCryptoProvider.GenerateKeys();
58 
59  //encryption does not require the private key, so, if required, we can initialize new crypto providers, passing the public keys to the constructors
60 
61  std::cout << "Testing encryption / decryption of 0." << std::endl;
62  assert(paillierCryptoProvider.DecryptInteger(paillierCryptoProvider.GetEncryptedZero()) == 0);
63  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(okamotoUchiyamaCryptoProvider.GetEncryptedZero()) == 0);
64  assert(dgkCryptoProvider.DecryptInteger(dgkCryptoProvider.GetEncryptedZero()) == 0);
65  assert(elGamalCryptoProvider.DecryptInteger(elGamalCryptoProvider.GetEncryptedZero()) == 0);
66 
67  std::cout << "Testing encryption / decryption of 1." << std::endl;
68  assert(paillierCryptoProvider.DecryptInteger(paillierCryptoProvider.GetEncryptedOne()) == 1);
69  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(okamotoUchiyamaCryptoProvider.GetEncryptedOne()) == 1);
70  assert(dgkCryptoProvider.DecryptInteger(dgkCryptoProvider.GetEncryptedOne()) == 1);
71  assert(elGamalCryptoProvider.DecryptInteger(elGamalCryptoProvider.GetEncryptedOne()) == 1);
72 
73  std::cout << "Testing encryption / decryption of -1." << std::endl;
74  assert(paillierCryptoProvider.DecryptInteger(paillierCryptoProvider.EncryptInteger(-1)) == -1);
75  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(okamotoUchiyamaCryptoProvider.EncryptInteger(-1)) == -1);
76  assert(dgkCryptoProvider.DecryptInteger(dgkCryptoProvider.EncryptInteger(-1)) == -1);
77  assert(elGamalCryptoProvider.DecryptInteger(elGamalCryptoProvider.EncryptInteger(-1)) == -1);
78 
79  std::cout << "Testing encryption / decryption of the positive / negative interval boundaries." << std::endl;
80  assert(paillierCryptoProvider.DecryptInteger(paillierCryptoProvider.EncryptInteger(paillierCryptoProvider.GetPositiveNegativeBoundary())) == paillierCryptoProvider.GetPositiveNegativeBoundary());
81  assert(paillierCryptoProvider.DecryptInteger(paillierCryptoProvider.EncryptInteger(paillierCryptoProvider.GetPositiveNegativeBoundary() + 1)) == -paillierCryptoProvider.GetPositiveNegativeBoundary());
82  //Okamoto-Uchiyama does not allow us to publish the real upper bound of the message space, so this works only if we have the private key. See the note in OkamotoUchiyama::doPrecomputations()
83  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(okamotoUchiyamaCryptoProvider.EncryptInteger(okamotoUchiyamaCryptoProvider.GetPositiveNegativeBoundary())) == okamotoUchiyamaCryptoProvider.GetPositiveNegativeBoundary());
84  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(okamotoUchiyamaCryptoProvider.EncryptInteger(okamotoUchiyamaCryptoProvider.GetPositiveNegativeBoundary() + 1)) == -okamotoUchiyamaCryptoProvider.GetPositiveNegativeBoundary());
85  assert(dgkCryptoProvider.DecryptInteger(dgkCryptoProvider.EncryptInteger(dgkCryptoProvider.GetPositiveNegativeBoundary())) == dgkCryptoProvider.GetPositiveNegativeBoundary());
86  assert(dgkCryptoProvider.DecryptInteger(dgkCryptoProvider.EncryptInteger(dgkCryptoProvider.GetPositiveNegativeBoundary() + 1)) == -dgkCryptoProvider.GetPositiveNegativeBoundary());
87  //ElGamal has a gap in the middle of the message space. We assign the left part to the positives and the right side the negatives
88  assert(elGamalCryptoProvider.DecryptInteger(elGamalCryptoProvider.EncryptInteger(elGamalCryptoProvider.GetPositiveNegativeBoundary() - 1)) == elGamalCryptoProvider.GetPositiveNegativeBoundary() - 1);
89  assert(elGamalCryptoProvider.DecryptInteger(elGamalCryptoProvider.EncryptInteger(elGamalCryptoProvider.GetMessageSpaceUpperBound() - elGamalCryptoProvider.GetPositiveNegativeBoundary() + 1)) == -elGamalCryptoProvider.GetPositiveNegativeBoundary() + 1);
90 
91  std::cout << "Testing DGK decryption of 0 without decryption map." << std::endl;
92  Dgk dgkCryptoProviderNoDecryptionMap;
93  dgkCryptoProviderNoDecryptionMap.GenerateKeys();
94  assert(dgkCryptoProviderNoDecryptionMap.IsEncryptedZero(dgkCryptoProviderNoDecryptionMap.GetEncryptedZero()) == true);
95  assert(dgkCryptoProviderNoDecryptionMap.IsEncryptedZero(dgkCryptoProviderNoDecryptionMap.GetEncryptedOne()) == false);
96 
97  std::cout << "Testing ElGamal decryption of 0 without decryption map." << std::endl;
98  ElGamal elGamalCryptoProviderNoDecryptionMap;
99  elGamalCryptoProviderNoDecryptionMap.GenerateKeys();
100  assert(elGamalCryptoProviderNoDecryptionMap.IsEncryptedZero(elGamalCryptoProviderNoDecryptionMap.GetEncryptedZero()) == true);
101  assert(elGamalCryptoProviderNoDecryptionMap.IsEncryptedZero(elGamalCryptoProviderNoDecryptionMap.GetEncryptedOne()) == false);
102 
103  BigInteger x = 2;
104  BigInteger y = -1;
105  std::cout << "Testing homomorphic addition, inverse, subtraction and multiplication." << std::endl;
106  //Paillier
107  {
108  Paillier::Ciphertext encX = paillierCryptoProvider.EncryptInteger(x);
109  Paillier::Ciphertext encY = paillierCryptoProvider.EncryptInteger(y);
110  Paillier::Ciphertext sum = encX + encY;
111  Paillier::Ciphertext inv = -encX;
112  Paillier::Ciphertext dif = encX - encY;
113  Paillier::Ciphertext prod = encX * y;
114  assert(paillierCryptoProvider.DecryptInteger(sum) == x + y);
115  assert(paillierCryptoProvider.DecryptInteger(inv) == -x);
116  assert(paillierCryptoProvider.DecryptInteger(dif) == x - y);
117  assert(paillierCryptoProvider.DecryptInteger(prod) == x * y);
118  }
119  //Okamoto-Uchiyama
120  {
121  OkamotoUchiyama::Ciphertext encX = okamotoUchiyamaCryptoProvider.EncryptInteger(x);
122  OkamotoUchiyama::Ciphertext encY = okamotoUchiyamaCryptoProvider.EncryptInteger(y);
123  OkamotoUchiyama::Ciphertext sum = encX + encY;
124  OkamotoUchiyama::Ciphertext inv = -encX;
125  OkamotoUchiyama::Ciphertext dif = encX - encY;
126  OkamotoUchiyama::Ciphertext prod = encX * y;
127  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(sum) == x + y);
128  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(inv) == -x);
129  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(dif) == x - y);
130  assert(okamotoUchiyamaCryptoProvider.DecryptInteger(prod) == x * y);
131  }
132  //DGK
133  {
134  Dgk::Ciphertext encX = dgkCryptoProvider.EncryptInteger(x);
135  Dgk::Ciphertext encY = dgkCryptoProvider.EncryptInteger(y);
136  Dgk::Ciphertext sum = encX + encY;
137  Dgk::Ciphertext inv = -encX;
138  Dgk::Ciphertext dif = encX - encY;
139  Dgk::Ciphertext prod = encX * y;
140  assert(dgkCryptoProvider.DecryptInteger(sum) == x + y);
141  assert(dgkCryptoProvider.DecryptInteger(inv) == -x);
142  assert(dgkCryptoProvider.DecryptInteger(dif) == x - y);
143  assert(dgkCryptoProvider.DecryptInteger(prod) == x * y);
144  }
145  //ElGamal
146  {
147  ElGamal::Ciphertext encX = elGamalCryptoProvider.EncryptInteger(x);
148  ElGamal::Ciphertext encY = elGamalCryptoProvider.EncryptInteger(y);
149  ElGamal::Ciphertext sum = encX + encY;
150  ElGamal::Ciphertext inv = -encX;
151  ElGamal::Ciphertext dif = encX - encY;
152  ElGamal::Ciphertext prod = encX * y;
153  assert(elGamalCryptoProvider.DecryptInteger(sum) == x + y);
154  assert(elGamalCryptoProvider.DecryptInteger(inv) == -x);
155  assert(elGamalCryptoProvider.DecryptInteger(dif) == x - y);
156  assert(elGamalCryptoProvider.DecryptInteger(prod) == x * y);
157  }
158 
159  std::cout << "Testing Data Packing with Paillier." << std::endl;
160  {
161  //initialize the data packer
162  DataPacker<Paillier> dataPacker(paillierCryptoProvider, 4, 1, 1);
163 
164  //generate some dummy vectors of data
165  size_t bucketCount = 30;
167  for (size_t i = 0; i < bucketCount; ++i)
168  {
170 
171  bucket.frontPadding = 1;
172  bucket.data = BigInteger(2);
173  bucket.backPadding = 1;
174  lhs.emplace_back(bucket);
175 
176  bucket.frontPadding = 0;
177  bucket.data = BigInteger(3);
178  bucket.backPadding = 0;
179  rhs.emplace_back(bucket);
180  }
181 
182  //pack data vectors
183  DataPacker<Paillier>::PackedData packedLhs = dataPacker.Pack(lhs);
184  DataPacker<Paillier>::PackedData packedRhs = dataPacker.Pack(rhs);
185 
186  //perform homomorphic operations on the packed vectors
187  DataPacker<Paillier>::PackedData sum = dataPacker.HomomorphicAdd(packedLhs, packedRhs);
188  DataPacker<Paillier>::PackedData prod = dataPacker.HomomorphicMultiply(packedRhs, 2);
189 
190  //unpack data
191  DataPacker<Paillier>::UnpackedData unpackedSum = dataPacker.Unpack(sum, bucketCount);
192  DataPacker<Paillier>::UnpackedData unpackedProd = dataPacker.Unpack(prod, bucketCount);
193  for (size_t i = 0; i < bucketCount; ++i)
194  {
195  assert(unpackedSum[i].frontPadding == 1);
196  assert(unpackedSum[i].data == 5);
197  assert(unpackedSum[i].backPadding == 1);
198 
199  assert(unpackedProd[i].frontPadding == 0);
200  assert(unpackedProd[i].data == 6);
201  assert(unpackedProd[i].backPadding == 0);
202  }
203  }
204 
205  std::cout << "Testing Paillier cryptoprovider construction from public and private key pairs." << std::endl;
206  {
207  PaillierPublicKey publicKeyClone;
208  publicKeyClone.g = paillierCryptoProvider.GetPublicKey().g;
209  publicKeyClone.n = paillierCryptoProvider.GetPublicKey().n;
210 
211  PaillierPrivateKey privateKeyClone;
212  privateKeyClone.p = paillierCryptoProvider.GetPrivateKey().p;
213  privateKeyClone.q = paillierCryptoProvider.GetPrivateKey().q;
214 
215  Paillier cryptoProviderClone(publicKeyClone, privateKeyClone);
216 
217  BigInteger plaintext = RandomProvider::GetInstance().GetRandomInteger(cryptoProviderClone.GetPositiveNegativeBoundary());
218  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(plaintext)) == plaintext);
219  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(-plaintext)) == -plaintext);
220  }
221 
222  std::cout << "Testing Okamoto-Uchiyama cryptoprovider construction from public and private key pairs." << std::endl;
223  {
224  OkamotoUchiyamaPublicKey publicKeyClone;
225  publicKeyClone.G = okamotoUchiyamaCryptoProvider.GetPublicKey().G;
226  publicKeyClone.H = okamotoUchiyamaCryptoProvider.GetPublicKey().H;
227  publicKeyClone.n = okamotoUchiyamaCryptoProvider.GetPublicKey().n;
228 
229  OkamotoUchiyamaPrivateKey privateKeyClone;
230  privateKeyClone.p = okamotoUchiyamaCryptoProvider.GetPrivateKey().p;
231  privateKeyClone.q = okamotoUchiyamaCryptoProvider.GetPrivateKey().q;
232  privateKeyClone.gp = okamotoUchiyamaCryptoProvider.GetPrivateKey().gp;
233  privateKeyClone.t = okamotoUchiyamaCryptoProvider.GetPrivateKey().t;
234 
235  OkamotoUchiyama cryptoProviderClone(publicKeyClone, privateKeyClone);
236 
237  BigInteger plaintext = RandomProvider::GetInstance().GetRandomInteger(cryptoProviderClone.GetPositiveNegativeBoundary());
238  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(plaintext)) == plaintext);
239  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(-plaintext)) == -plaintext);
240  }
241 
242  std::cout << "Testing DGK cryptoprovider construction from public and private key pairs." << std::endl;
243  {
244  DgkPublicKey publicKeyClone;
245  publicKeyClone.g = dgkCryptoProvider.GetPublicKey().g;
246  publicKeyClone.h = dgkCryptoProvider.GetPublicKey().h;
247  publicKeyClone.n = dgkCryptoProvider.GetPublicKey().n;
248  publicKeyClone.u = dgkCryptoProvider.GetPublicKey().u;
249 
250  DgkPrivateKey privateKeyClone;
251  privateKeyClone.p = dgkCryptoProvider.GetPrivateKey().p;
252  privateKeyClone.q = dgkCryptoProvider.GetPrivateKey().q;
253  privateKeyClone.vp = dgkCryptoProvider.GetPrivateKey().vp;
254  privateKeyClone.vq = dgkCryptoProvider.GetPrivateKey().vq;
255 
256  Dgk cryptoProviderClone(publicKeyClone, privateKeyClone, true);//pre-compute decryption map (keep Dgk.l reasonably small for this test)
257 
258  BigInteger plaintext = RandomProvider::GetInstance().GetRandomInteger(cryptoProviderClone.GetPositiveNegativeBoundary());
259  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(plaintext)) == plaintext);
260  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(-plaintext)) == -plaintext);
261  }
262 
263  std::cout << "Testing ElGamal cryptoprovider construction from public and private key pairs." << std::endl;
264  {
265  ElGamalPublicKey publicKeyClone;
266  publicKeyClone.gq = elGamalCryptoProvider.GetPublicKey().gq;
267  publicKeyClone.h = elGamalCryptoProvider.GetPublicKey().h;
268  publicKeyClone.p = elGamalCryptoProvider.GetPublicKey().p;
269  publicKeyClone.q = elGamalCryptoProvider.GetPublicKey().q;
270 
271  ElGamalPrivateKey privateKeyClone;
272  privateKeyClone.s = elGamalCryptoProvider.GetPrivateKey().s;
273 
274  ElGamal cryptoProviderClone(publicKeyClone, privateKeyClone, true);//pre-compute decryption map (keep ElGamal.messageSpaceThresholdBitSize reasonably small for this test)
275 
276  BigInteger plaintext = RandomProvider::GetInstance().GetRandomInteger(cryptoProviderClone.GetPositiveNegativeBoundary());
277  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(plaintext)) == plaintext);
278  assert(cryptoProviderClone.DecryptInteger(cryptoProviderClone.EncryptInteger(-plaintext)) == -plaintext);
279  }
280  }
281  catch (const std::runtime_error &exception) {
282  std::cout << exception.what() << std::endl;
283  }
284  catch (const std::exception &exception) {
285  std::cout << exception.what() << std::endl;
286  }
287  //it won't catch low level exceptions, like division by 0, produced by GMP...
288  catch (...) {
289  std::cout << "Unexpected exception occured." << std::endl;
290  }
291  return 0;
292 }
Implementation of the public-key DGK Cryptosystem.
Definition: dgk.h:104
Ciphertext GetEncryptedOne(const bool randomized=true) const
Returns [1].
Ciphertext GetEncryptedZero(const bool randomized=true) const
Returns [0].
const T_PublicKey & GetPublicKey() const
Public key getter.
BigInteger backPadding
The back padding ( )
Definition: data_packer.h:61
Container for data buckets.
Definition: data_packer.h:52
PackedData Pack(const UnpackedData &input) const
Pack data.
Definition: data_packer.hpp:59
virtual bool GenerateKeys()
Generate the public and private keys.
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
Definition: paillier.cpp:176
The private key container structure for the ElGamal cryptosystem.
Definition: el_gamal.h:62
BigInteger data
The data ( )
Definition: data_packer.h:58
virtual bool GenerateKeys()
Definition: paillier.cpp:105
The public key container structure for the Dgk cryptosystem.
Definition: dgk.h:47
virtual T_Ciphertext EncryptInteger(const BigInteger &plaintext) const
Encrypt an integer and apply randomization.
virtual const BigInteger & GetMessageSpaceUpperBound() const
Returns the message space upper bound.
Definition: el_gamal.cpp:334
virtual const BigInteger & GetPositiveNegativeBoundary() const
Returns the biggest positive number that can be encrypted without overflowing.
const T_PrivateKey & GetPrivateKey() const
Private key getter.
UnpackedData Unpack(const PackedData &input, const size_t totalBucketCount) const
Unpack data.
std::deque< typename DataPacker< T_CryptoProvider >::DataBucket > UnpackedData
Define a vector template specialization for vectors of unpacked data.
Definition: data_packer.h:65
Implementation of the public-key ElGamal Cryptosystem.
Definition: el_gamal.h:88
Template class which implements the data packing functionality.
Definition: data_packer.h:46
BigInteger t
, the prime factor of
BigInteger frontPadding
The front padding ( )
Definition: data_packer.h:55
bool IsEncryptedZero(const Ciphertext &ciphertext) const
Determines if ciphertext contains an encryption of 0 or not.
Definition: dgk.cpp:463
Implementation of the public-key Paillier Cryptosystem.
Definition: paillier.h:103
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
Definition: el_gamal.cpp:174
Implementation of the public-key Okamoto-Uchiyama Cryptosystem.
The private key container structure for the Okamoto-Uchiyama cryptosystem.
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Definition: dgk.cpp:309
virtual bool GenerateKeys()
Definition: el_gamal.cpp:104
virtual bool GenerateKeys()
Generate the public and private keys.
Definition: dgk.cpp:161
PackedData HomomorphicAdd(const PackedData &lhs, const PackedData &rhs)
Add two vectors of packed data.
int main(int argc, char *argv[])
Definition: test/main.cpp:40
std::deque< typename T_CryptoProvider::Ciphertext > PackedData
Define a vector template specialization for vectors of packed data.
Definition: data_packer.h:68
The private key container structure for the Dgk cryptosystem.
Definition: dgk.h:62
BigInteger u
- The message space upper bound
Definition: dgk.h:56
PackedData HomomorphicMultiply(const PackedData &lhs, const BigInteger &rhs)
Multiply a vector of packed data with a constant plaintext term.
virtual BigInteger DecryptInteger(const Ciphertext &ciphertext) const
Decrypt number.
The public key container structure for the Okamoto-Uchiyama cryptosystem.
The public key container structure for the ElGamal cryptosystem.
Definition: el_gamal.h:47
The private key container structure for the Paillier cryptosystem.
Definition: paillier.h:60
bool IsEncryptedZero(const Ciphertext &ciphertext) const
Determines if ciphertext contains an encryption of 0 or not.
Definition: el_gamal.cpp:353
The public key container structure for the Paillier cryptosystem.
Definition: paillier.h:49
Test main header.