aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2014-12-09 20:57:07 +0000
committerChristian Grothoff <christian@grothoff.org>2014-12-09 20:57:07 +0000
commite613b7acfde2427b5ea48f2ac866489f2d9b6589 (patch)
treed00d04e4a8a10473505156ffea7f38a591413084 /src
parent82bedb216e21147473795fb43be9cfd48414e7ca (diff)
downloadgnunet-e613b7acfde2427b5ea48f2ac866489f2d9b6589.tar.gz
gnunet-e613b7acfde2427b5ea48f2ac866489f2d9b6589.zip
-fixing paillier bug, improving testcase
Diffstat (limited to 'src')
-rw-r--r--src/util/crypto_paillier.c275
-rw-r--r--src/util/test_crypto_paillier.c178
2 files changed, 358 insertions, 95 deletions
diff --git a/src/util/crypto_paillier.c b/src/util/crypto_paillier.c
index c16706dcb..1104aee62 100644
--- a/src/util/crypto_paillier.c
+++ b/src/util/crypto_paillier.c
@@ -41,51 +41,63 @@ GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_ke
41{ 41{
42 gcry_mpi_t p; 42 gcry_mpi_t p;
43 gcry_mpi_t q; 43 gcry_mpi_t q;
44
45 gcry_mpi_t phi; 44 gcry_mpi_t phi;
45 gcry_mpi_t mu;
46 gcry_mpi_t n; 46 gcry_mpi_t n;
47 47
48 GNUNET_assert (NULL != (phi = gcry_mpi_new (0))); 48 /* Generate two distinct primes. The probability that the loop body
49 GNUNET_assert (NULL != (n = gcry_mpi_new (0))); 49 is executed more than once is very very low... */
50 50 p = NULL;
51 p = q = NULL; 51 q = NULL;
52
53 // Generate two distinct primes.
54 // The probability that the loop body
55 // is executed more than once is very low.
56 do { 52 do {
57 if (NULL != p) 53 if (NULL != p)
58 gcry_mpi_release (p); 54 gcry_mpi_release (p);
59 if (NULL != q) 55 if (NULL != q)
60 gcry_mpi_release (q); 56 gcry_mpi_release (q);
61 // generate rsa modulus 57 GNUNET_assert (0 ==
62 GNUNET_assert (0 == gcry_prime_generate (&p, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, 58 gcry_prime_generate (&p,
63 GCRY_STRONG_RANDOM, 0)); 59 GNUNET_CRYPTO_PAILLIER_BITS / 2,
64 GNUNET_assert (0 == gcry_prime_generate (&q, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL, 60 0, NULL, NULL, NULL,
65 GCRY_STRONG_RANDOM, 0)); 61 GCRY_STRONG_RANDOM, 0));
62 GNUNET_assert (0 ==
63 gcry_prime_generate (&q,
64 GNUNET_CRYPTO_PAILLIER_BITS / 2,
65 0, NULL, NULL, NULL,
66 GCRY_STRONG_RANDOM, 0));
66 } 67 }
67 while (0 == gcry_mpi_cmp (p, q)); 68 while (0 == gcry_mpi_cmp (p, q));
68 gcry_mpi_mul (n, p, q); 69 /* n = p * q */
70 GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
71 gcry_mpi_mul (n,
72 p,
73 q);
69 GNUNET_CRYPTO_mpi_print_unsigned (public_key, 74 GNUNET_CRYPTO_mpi_print_unsigned (public_key,
70 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey), 75 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey),
71 n); 76 n);
72 77
73 // compute phi(n) = (p-1)(q-1) 78 /* compute phi(n) = (p-1)(q-1) */
79 GNUNET_assert (NULL != (phi = gcry_mpi_new (0)));
74 gcry_mpi_sub_ui (p, p, 1); 80 gcry_mpi_sub_ui (p, p, 1);
75 gcry_mpi_sub_ui (q, q, 1); 81 gcry_mpi_sub_ui (q, q, 1);
76 gcry_mpi_mul (phi, p, q); 82 gcry_mpi_mul (phi, p, q);
77
78 // lambda equals phi(n) in the simplified key generation
79 GNUNET_CRYPTO_mpi_print_unsigned (private_key->lambda, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi);
80
81 // invert phi and abuse the phi mpi to store the result ...
82 GNUNET_assert (0 != gcry_mpi_invm (phi, phi, n));
83 GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi);
84
85 gcry_mpi_release (p); 83 gcry_mpi_release (p);
86 gcry_mpi_release (q); 84 gcry_mpi_release (q);
85
86 /* lambda equals phi(n) in the simplified key generation */
87 GNUNET_CRYPTO_mpi_print_unsigned (private_key->lambda,
88 GNUNET_CRYPTO_PAILLIER_BITS / 8,
89 phi);
90 /* mu = phi^{-1} mod n, as we use g = n + 1 */
91 GNUNET_assert (NULL != (mu = gcry_mpi_new (0)));
92 GNUNET_assert (0 != gcry_mpi_invm (mu,
93 phi,
94 n));
87 gcry_mpi_release (phi); 95 gcry_mpi_release (phi);
88 gcry_mpi_release (n); 96 gcry_mpi_release (n);
97 GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu,
98 GNUNET_CRYPTO_PAILLIER_BITS / 8,
99 mu);
100 gcry_mpi_release (mu);
89} 101}
90 102
91 103
@@ -101,7 +113,7 @@ GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_ke
101 * or -1 if less than one homomorphic operation is possible 113 * or -1 if less than one homomorphic operation is possible
102 */ 114 */
103int 115int
104GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, 116GNUNET_CRYPTO_paillier_encrypt1 (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
105 const gcry_mpi_t m, 117 const gcry_mpi_t m,
106 int desired_ops, 118 int desired_ops,
107 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext) 119 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
@@ -163,12 +175,12 @@ GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *pu
163 while (gcry_mpi_cmp (r, n) >= 0); 175 while (gcry_mpi_cmp (r, n) >= 0);
164 176
165 // c = (n+1)^m mod n^2 177 // c = (n+1)^m mod n^2
166 gcry_mpi_add_ui (c, n, 1); 178 gcry_mpi_add_ui (c, n, 1); // c = n + 1
167 gcry_mpi_powm (c, c, m, n_square); 179 gcry_mpi_powm (c, c, m, n_square); // c = (n+1)^m mod n^2
168 // r <- r^n mod n^2 180 // r <- r^n mod n^2
169 gcry_mpi_powm (r, r, n, n_square); 181 gcry_mpi_powm (r, r, n, n_square); // r = r^n mod n^2
170 // c <- r*c mod n^2 182 // c <- r*c mod n^2
171 gcry_mpi_mulm (c, r, c, n_square); 183 gcry_mpi_mulm (c, r, c, n_square); // c = r*c mod n^2
172 184
173 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits, 185 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
174 sizeof ciphertext->bits, 186 sizeof ciphertext->bits,
@@ -184,6 +196,121 @@ GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *pu
184 196
185 197
186/** 198/**
199 * Encrypt a plaintext with a paillier public key.
200 *
201 * @param public_key Public key to use.
202 * @param m Plaintext to encrypt.
203 * @param desired_ops How many homomorphic ops the caller intends to use
204 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
205 * @return guaranteed number of supported homomorphic operations >= 1,
206 * or desired_ops, in case that is lower,
207 * or -1 if less than one homomorphic operation is possible
208 */
209int
210GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
211 const gcry_mpi_t m,
212 int desired_ops,
213 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
214{
215 int possible_opts;
216 gcry_mpi_t n_square;
217 gcry_mpi_t r;
218 gcry_mpi_t rn;
219 gcry_mpi_t g;
220 gcry_mpi_t gm;
221 gcry_mpi_t c;
222 gcry_mpi_t n;
223 gcry_mpi_t max_num;
224 unsigned int highbit;
225
226 /* set max_num = 2^{GNUNET_CRYPTO_PAILLIER_BITS}, the largest
227 number we can have as a result */
228 GNUNET_assert (NULL != (max_num = gcry_mpi_set_ui (NULL, 1)));
229 gcry_mpi_mul_2exp (max_num,
230 max_num,
231 GNUNET_CRYPTO_PAILLIER_BITS);
232
233 /* Determine how many operations we could allow, assuming the other
234 number has the same length (or is smaller), by counting the
235 number of possible operations. We essentially divide max_num by
236 2 until the result is no longer larger than 'm', incrementing the
237 maximum number of operations in each round, starting at -2 */
238 for (possible_opts = -2; gcry_mpi_cmp (max_num, m) > 0; possible_opts++)
239 gcry_mpi_div (max_num,
240 NULL,
241 max_num,
242 GCRYMPI_CONST_TWO,
243 0);
244 gcry_mpi_release (max_num);
245
246 if (possible_opts < 1)
247 possible_opts = 0;
248 /* Enforce soft-cap by caller */
249 possible_opts = GNUNET_MIN (desired_ops, possible_opts);
250 ciphertext->remaining_ops = htonl (possible_opts);
251
252 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
253 public_key,
254 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
255
256 /* check public key for number of bits, bail out if key is all zeros */
257 highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1;
258 while ( (! gcry_mpi_test_bit (n, highbit)) &&
259 (0 != highbit) )
260 highbit--;
261 if (0 == highbit)
262 {
263 /* invalid public key */
264 GNUNET_break_op (0);
265 gcry_mpi_release (n);
266 return GNUNET_SYSERR;
267 }
268
269 /* generate r < n (without bias) */
270 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
271 do {
272 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
273 }
274 while (gcry_mpi_cmp (r, n) >= 0);
275
276 /* g = n + 1 */
277 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
278 gcry_mpi_add_ui (g, n, 1);
279
280 /* n_square = n^2 */
281 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
282 gcry_mpi_mul (n_square,
283 n,
284 n);
285
286 /* gm = g^m mod n^2 */
287 GNUNET_assert (0 != (gm = gcry_mpi_new (0)));
288 gcry_mpi_powm (gm, g, m, n_square);
289 gcry_mpi_release (g);
290
291 /* rn <- r^n mod n^2 */
292 GNUNET_assert (0 != (rn = gcry_mpi_new (0)));
293 gcry_mpi_powm (rn, r, n, n_square);
294 gcry_mpi_release (r);
295 gcry_mpi_release (n);
296
297 /* c <- rn * gm mod n^2 */
298 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
299 gcry_mpi_mulm (c, rn, gm, n_square);
300 gcry_mpi_release (n_square);
301 gcry_mpi_release (gm);
302 gcry_mpi_release (rn);
303
304 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
305 sizeof (ciphertext->bits),
306 c);
307 gcry_mpi_release (c);
308
309 return possible_opts;
310}
311
312
313/**
187 * Decrypt a paillier ciphertext with a private key. 314 * Decrypt a paillier ciphertext with a private key.
188 * 315 *
189 * @param private_key Private key to use for decryption. 316 * @param private_key Private key to use for decryption.
@@ -202,33 +329,56 @@ GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *p
202 gcry_mpi_t n; 329 gcry_mpi_t n;
203 gcry_mpi_t n_square; 330 gcry_mpi_t n_square;
204 gcry_mpi_t c; 331 gcry_mpi_t c;
332 gcry_mpi_t cmu;
333 gcry_mpi_t cmum1;
334 gcry_mpi_t mod;
335
336 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda,
337 private_key->lambda,
338 sizeof (private_key->lambda));
339 GNUNET_CRYPTO_mpi_scan_unsigned (&mu,
340 private_key->mu,
341 sizeof (private_key->mu));
342 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
343 public_key,
344 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
345 GNUNET_CRYPTO_mpi_scan_unsigned (&c,
346 ciphertext->bits,
347 sizeof (ciphertext->bits));
205 348
349 /* n_square = n * n */
206 GNUNET_assert (0 != (n_square = gcry_mpi_new (0))); 350 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
351 gcry_mpi_mul (n_square, n, n);
207 352
208 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda, private_key->lambda, sizeof private_key->lambda); 353 /* cmu = c^lambda mod n^2 */
209 GNUNET_CRYPTO_mpi_scan_unsigned (&mu, private_key->mu, sizeof private_key->mu); 354 GNUNET_assert (0 != (cmu = gcry_mpi_new (0)));
210 GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof *public_key); 355 gcry_mpi_powm (cmu,
211 GNUNET_CRYPTO_mpi_scan_unsigned (&c, ciphertext->bits, sizeof ciphertext->bits); 356 c,
357 lambda,
358 n_square);
359 gcry_mpi_release (n_square);
360 gcry_mpi_release (lambda);
361 gcry_mpi_release (c);
212 362
213 gcry_mpi_mul (n_square, n, n); 363 /* cmum1 = cmu - 1 */
214 // m = c^lambda mod n^2 364 GNUNET_assert (0 != (cmum1 = gcry_mpi_new (0)));
215 gcry_mpi_powm (m, c, lambda, n_square); 365 gcry_mpi_sub_ui (cmum1, cmu, 1);
216 // m = m - 1 366 gcry_mpi_release (cmu);
217 gcry_mpi_sub_ui (m, m, 1); 367
218 // m <- m/n 368 /* mod = cmum1 / n (mod n) */
219 gcry_mpi_div (m, NULL, m, n, 0); 369 GNUNET_assert (0 != (mod = gcry_mpi_new (0)));
220 gcry_mpi_mulm (m, m, mu, n); 370 gcry_mpi_div (mod, NULL, cmum1, n, 0);
221 371
372 /* m = mod * mu mod n */
373 gcry_mpi_mulm (m, mod, mu, n);
222 gcry_mpi_release (mu); 374 gcry_mpi_release (mu);
223 gcry_mpi_release (lambda);
224 gcry_mpi_release (n); 375 gcry_mpi_release (n);
225 gcry_mpi_release (n_square);
226 gcry_mpi_release (c);
227} 376}
228 377
229 378
230/** 379/**
231 * Compute a ciphertext that represents the sum of the plaintext in @a x1 and @a x2 380 * Compute a ciphertext that represents the sum of the plaintext in @a
381 * c1 and @a c2.
232 * 382 *
233 * Note that this operation can only be done a finite number of times 383 * Note that this operation can only be done a finite number of times
234 * before an overflow occurs. 384 * before an overflow occurs.
@@ -249,31 +399,43 @@ GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *pu
249 gcry_mpi_t a; 399 gcry_mpi_t a;
250 gcry_mpi_t b; 400 gcry_mpi_t b;
251 gcry_mpi_t c; 401 gcry_mpi_t c;
402 gcry_mpi_t n;
252 gcry_mpi_t n_square; 403 gcry_mpi_t n_square;
253 int32_t o1; 404 int32_t o1;
254 int32_t o2; 405 int32_t o2;
255 406
256 o1 = ntohl (c1->remaining_ops); 407 o1 = ntohl (c1->remaining_ops);
257 o2 = ntohl (c2->remaining_ops); 408 o2 = ntohl (c2->remaining_ops);
258 if (0 >= o1 || 0 >= o2) 409 if ( (0 >= o1) || (0 >= o2) )
259 return GNUNET_SYSERR; 410 return GNUNET_SYSERR;
260 411
261 GNUNET_assert (0 != (c = gcry_mpi_new (0))); 412 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
413 c1->bits,
414 sizeof (c1->bits));
415 GNUNET_CRYPTO_mpi_scan_unsigned (&b,
416 c2->bits,
417 sizeof (c2->bits));
418 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
419 public_key,
420 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
262 421
263 GNUNET_CRYPTO_mpi_scan_unsigned (&a, c1->bits, sizeof c1->bits); 422 /* n_square = n * n */
264 GNUNET_CRYPTO_mpi_scan_unsigned (&b, c1->bits, sizeof c2->bits); 423 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
265 GNUNET_CRYPTO_mpi_scan_unsigned (&n_square, public_key, sizeof *public_key); 424 gcry_mpi_mul (n_square, n, n);
266 gcry_mpi_mul (n_square, n_square, n_square); 425 gcry_mpi_release (n);
426
427 /* c = a * b mod n_square */
428 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
267 gcry_mpi_mulm (c, a, b, n_square); 429 gcry_mpi_mulm (c, a, b, n_square);
430 gcry_mpi_release (n_square);
431 gcry_mpi_release (a);
432 gcry_mpi_release (b);
268 433
269 result->remaining_ops = htonl (((o2 > o1) ? o1 : o2) - 1); 434 result->remaining_ops = htonl (GNUNET_MIN (o1, o2) - 1);
270 GNUNET_CRYPTO_mpi_print_unsigned (result->bits, 435 GNUNET_CRYPTO_mpi_print_unsigned (result->bits,
271 sizeof result->bits, 436 sizeof (result->bits),
272 c); 437 c);
273 gcry_mpi_release (a);
274 gcry_mpi_release (b);
275 gcry_mpi_release (c); 438 gcry_mpi_release (c);
276 gcry_mpi_release (n_square);
277 return ntohl (result->remaining_ops); 439 return ntohl (result->remaining_ops);
278} 440}
279 441
@@ -292,3 +454,4 @@ GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCip
292} 454}
293 455
294/* end of crypto_paillier.c */ 456/* end of crypto_paillier.c */
457
diff --git a/src/util/test_crypto_paillier.c b/src/util/test_crypto_paillier.c
index cd8c77e5e..750eeece1 100644
--- a/src/util/test_crypto_paillier.c
+++ b/src/util/test_crypto_paillier.c
@@ -29,7 +29,7 @@
29#include <gcrypt.h> 29#include <gcrypt.h>
30 30
31 31
32int 32static int
33test_crypto () 33test_crypto ()
34{ 34{
35 gcry_mpi_t plaintext; 35 gcry_mpi_t plaintext;
@@ -38,30 +38,95 @@ test_crypto ()
38 struct GNUNET_CRYPTO_PaillierPublicKey public_key; 38 struct GNUNET_CRYPTO_PaillierPublicKey public_key;
39 struct GNUNET_CRYPTO_PaillierPrivateKey private_key; 39 struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
40 40
41 GNUNET_CRYPTO_paillier_create (&public_key, &private_key); 41 GNUNET_CRYPTO_paillier_create (&public_key,
42 42 &private_key);
43 GNUNET_assert (NULL != (plaintext = gcry_mpi_new (0))); 43 GNUNET_assert (NULL != (plaintext = gcry_mpi_new (0)));
44 GNUNET_assert (NULL != (plaintext_result = gcry_mpi_new (0))); 44 GNUNET_assert (NULL != (plaintext_result = gcry_mpi_new (0)));
45 gcry_mpi_randomize (plaintext,
46 GNUNET_CRYPTO_PAILLIER_BITS / 2,
47 GCRY_WEAK_RANDOM);
48
49 GNUNET_CRYPTO_paillier_encrypt (&public_key,
50 plaintext,
51 0 /* 0 hom ops */,
52 &ciphertext);
53 GNUNET_CRYPTO_paillier_decrypt (&private_key,
54 &public_key,
55 &ciphertext,
56 plaintext_result);
57
58 if (0 != gcry_mpi_cmp (plaintext,
59 plaintext_result))
60 {
61 fprintf (stderr,
62 "Paillier decryption failed with plaintext of size %u\n",
63 gcry_mpi_get_nbits (plaintext));
64 gcry_log_debugmpi ("\n",
65 plaintext);
66 gcry_log_debugmpi ("\n",
67 plaintext_result);
68 return 1;
69 }
70 return 0;
71}
45 72
46 gcry_mpi_randomize (plaintext, GNUNET_CRYPTO_PAILLIER_BITS / 2, GCRY_WEAK_RANDOM);
47 73
48 GNUNET_CRYPTO_paillier_encrypt (&public_key, plaintext, 0, &ciphertext); 74static int
75test_hom_simple (unsigned int a,
76 unsigned int b)
77{
78 gcry_mpi_t m1;
79 gcry_mpi_t m2;
80 gcry_mpi_t result;
81 gcry_mpi_t hom_result;
82 struct GNUNET_CRYPTO_PaillierCiphertext c1;
83 struct GNUNET_CRYPTO_PaillierCiphertext c2;
84 struct GNUNET_CRYPTO_PaillierCiphertext c_result;
85 struct GNUNET_CRYPTO_PaillierPublicKey public_key;
86 struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
49 87
50 GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key, 88 GNUNET_CRYPTO_paillier_create (&public_key,
51 &ciphertext, plaintext_result); 89 &private_key);
52 90
53 if (0 != gcry_mpi_cmp (plaintext, plaintext_result)) 91 GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
92 GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
93 GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
94 GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
95 m1 = gcry_mpi_set_ui (m1, a);
96 m2 = gcry_mpi_set_ui (m2, b);
97 gcry_mpi_add (result,
98 m1,
99 m2);
100 GNUNET_CRYPTO_paillier_encrypt (&public_key,
101 m1,
102 2,
103 &c1);
104 GNUNET_CRYPTO_paillier_encrypt (&public_key,
105 m2,
106 2,
107 &c2);
108 GNUNET_CRYPTO_paillier_hom_add (&public_key,
109 &c1,
110 &c2,
111 &c_result);
112 GNUNET_CRYPTO_paillier_decrypt (&private_key,
113 &public_key,
114 &c_result,
115 hom_result);
116 if (0 != gcry_mpi_cmp (result, hom_result))
54 { 117 {
55 printf ("paillier failed with plaintext of size %u\n", gcry_mpi_get_nbits (plaintext)); 118 fprintf (stderr,
56 gcry_log_debugmpi("\n", plaintext); 119 "GNUNET_CRYPTO_paillier failed simple math!\n");
57 gcry_log_debugmpi("\n", plaintext_result); 120 gcry_log_debugmpi ("got ", hom_result);
121 gcry_log_debugmpi ("wanted ", result);
58 return 1; 122 return 1;
59 } 123 }
60 return 0; 124 return 0;
61} 125}
62 126
63int 127
64test_hom() 128static int
129test_hom ()
65{ 130{
66 int ret; 131 int ret;
67 gcry_mpi_t m1; 132 gcry_mpi_t m1;
@@ -73,56 +138,91 @@ test_hom()
73 struct GNUNET_CRYPTO_PaillierCiphertext c_result; 138 struct GNUNET_CRYPTO_PaillierCiphertext c_result;
74 struct GNUNET_CRYPTO_PaillierPublicKey public_key; 139 struct GNUNET_CRYPTO_PaillierPublicKey public_key;
75 struct GNUNET_CRYPTO_PaillierPrivateKey private_key; 140 struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
76 141
77 GNUNET_CRYPTO_paillier_create (&public_key, &private_key); 142 GNUNET_CRYPTO_paillier_create (&public_key,
143 &private_key);
78 144
79 GNUNET_assert (NULL != (m1 = gcry_mpi_new (0))); 145 GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
80 GNUNET_assert (NULL != (m2 = gcry_mpi_new (0))); 146 GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
81 GNUNET_assert (NULL != (result = gcry_mpi_new (0))); 147 GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
82 GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0))); 148 GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
83 //gcry_mpi_randomize (m1, GNUNET_CRYPTO_PAILLIER_BITS-2, GCRY_WEAK_RANDOM); 149 m1 = gcry_mpi_set_ui (m1, 1);
84 m1 = gcry_mpi_set_ui(m1,1); 150 /* m1 = m1 * 2 ^ (GCPB - 3) */
85 gcry_mpi_mul_2exp(m1,m1,GNUNET_CRYPTO_PAILLIER_BITS-3); 151 gcry_mpi_mul_2exp (m1,
86 //gcry_mpi_randomize (m2, GNUNET_CRYPTO_PAILLIER_BITS-2, GCRY_WEAK_RANDOM); 152 m1,
87 m2 = gcry_mpi_set_ui(m2,1); 153 GNUNET_CRYPTO_PAILLIER_BITS - 3);
88 gcry_mpi_mul_2exp(m2,m2,GNUNET_CRYPTO_PAILLIER_BITS-3); 154 m2 = gcry_mpi_set_ui (m2, 15);
89 gcry_mpi_add(result,m1,m2); 155 /* m1 = m1 * 2 ^ (GCPB / 2) */
90 156 gcry_mpi_mul_2exp (m2,
91 if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key, m1, 2, &c1))){ 157 m2,
92 printf ("GNUNET_CRYPTO_paillier_encrypt 1 failed, should return 1 allowed operation, got %d!\n", ret); 158 GNUNET_CRYPTO_PAILLIER_BITS / 2);
159 gcry_mpi_add (result,
160 m1,
161 m2);
162
163 if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
164 m1,
165 2,
166 &c1)))
167 {
168 fprintf (stderr,
169 "GNUNET_CRYPTO_paillier_encrypt 1 failed, should return 1 allowed operation, got %d!\n",
170 ret);
93 return 1; 171 return 1;
94 } 172 }
95 if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key, m2, 2, &c2))){ 173 if (2 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
96 printf ("GNUNET_CRYPTO_paillier_encrypt 2 failed, should return 1 allowed operation, got %d!\n", ret); 174 m2,
175 2,
176 &c2)))
177 {
178 fprintf (stderr,
179 "GNUNET_CRYPTO_paillier_encrypt 2 failed, should return 2 allowed operation, got %d!\n",
180 ret);
97 return 1; 181 return 1;
98 } 182 }
99 183
100 if (0 != (ret = GNUNET_CRYPTO_paillier_hom_add (&public_key, &c1,&c2, &c_result))){ 184 if (0 != (ret = GNUNET_CRYPTO_paillier_hom_add (&public_key,
101 printf ("GNUNET_CRYPTO_paillier_hom_add failed, expected 0 remaining operations, got %d!\n", ret); 185 &c1,
186 &c2,
187 &c_result)))
188 {
189 fprintf (stderr,
190 "GNUNET_CRYPTO_paillier_hom_add failed, expected 0 remaining operations, got %d!\n",
191 ret);
102 return 1; 192 return 1;
103 } 193 }
104 194
105 GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key, 195 GNUNET_CRYPTO_paillier_decrypt (&private_key,
106 &c_result, hom_result); 196 &public_key,
107 197 &c_result,
108 gcry_log_debugmpi("\n", hom_result); 198 hom_result);
109 gcry_log_debugmpi("\n", result); 199
110 if (0 != gcry_mpi_cmp(result, hom_result)){ 200 if (0 != gcry_mpi_cmp (result, hom_result))
111 printf ("GNUNET_CRYPTO_paillier miscalculated!\n"); 201 {
202 fprintf (stderr,
203 "GNUNET_CRYPTO_paillier miscalculated with large numbers!\n");
204 gcry_log_debugmpi ("got", hom_result);
205 gcry_log_debugmpi ("wanted", result);
112 return 1; 206 return 1;
113 } 207 }
114
115 return 0; 208 return 0;
116} 209}
117 210
118 211
119int 212int
120main (int argc, char *argv[]) 213main (int argc,
214 char *argv[])
121{ 215{
122 int ret; 216 int ret;
123 ret = test_crypto (); 217 ret = test_crypto ();
124 if (0 != ret) 218 if (0 != ret)
125 return ret; 219 return ret;
220 ret = test_hom_simple (2,4);
221 if (0 != ret)
222 return ret;
223 ret = test_hom_simple (13,17);
224 if (0 != ret)
225 return ret;
126 ret = test_hom (); 226 ret = test_hom ();
127 return ret; 227 return ret;
128} 228}