diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/util/crypto_paillier.c | 275 | ||||
-rw-r--r-- | src/util/test_crypto_paillier.c | 178 |
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 | */ |
103 | int | 115 | int |
104 | GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key, | 116 | GNUNET_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 | */ | ||
209 | int | ||
210 | GNUNET_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 | ||
32 | int | 32 | static int |
33 | test_crypto () | 33 | test_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); | 74 | static int |
75 | test_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 | ||
63 | int | 127 | |
64 | test_hom() | 128 | static int |
129 | test_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 | ||
119 | int | 212 | int |
120 | main (int argc, char *argv[]) | 213 | main (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 | } |