2 This file is part of GNUnet.
3 Copyright (C) 2014 GNUnet e.V.
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
22 * @file util/crypto_paillier.c
23 * @brief implementation of the paillier crypto system with libgcrypt
24 * @author Florian Dold
25 * @author Christian Fuchs
29 #include "gnunet_util_lib.h"
33 * Create a freshly generated paillier public key.
35 * @param[out] public_key Where to store the public key?
36 * @param[out] private_key Where to store the private key?
39 GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
40 struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
48 /* Generate two distinct primes. The probability that the loop body
49 is executed more than once is very very low... */
58 gcry_prime_generate (&p,
59 GNUNET_CRYPTO_PAILLIER_BITS / 2,
61 GCRY_STRONG_RANDOM, 0));
63 gcry_prime_generate (&q,
64 GNUNET_CRYPTO_PAILLIER_BITS / 2,
66 GCRY_STRONG_RANDOM, 0));
68 while (0 == gcry_mpi_cmp (p, q));
70 GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
74 GNUNET_CRYPTO_mpi_print_unsigned (public_key,
75 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey),
78 /* compute phi(n) = (p-1)(q-1) */
79 GNUNET_assert (NULL != (phi = gcry_mpi_new (0)));
80 gcry_mpi_sub_ui (p, p, 1);
81 gcry_mpi_sub_ui (q, q, 1);
82 gcry_mpi_mul (phi, p, q);
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,
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,
95 gcry_mpi_release (phi);
97 GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu,
98 GNUNET_CRYPTO_PAILLIER_BITS / 8,
100 gcry_mpi_release (mu);
105 * Encrypt a plaintext with a paillier public key.
107 * @param public_key Public key to use.
108 * @param m Plaintext to encrypt.
109 * @param desired_ops How many homomorphic ops the caller intends to use
110 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
111 * @return guaranteed number of supported homomorphic operations >= 1,
112 * or desired_ops, in case that is lower,
113 * or -1 if less than one homomorphic operation is possible
116 GNUNET_CRYPTO_paillier_encrypt1 (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
119 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
128 unsigned int highbit;
130 /* determine how many operations we could allow, if the other number
131 has the same length. */
132 GNUNET_assert (NULL != (tmp1 = gcry_mpi_set_ui (NULL, 1)));
133 GNUNET_assert (NULL != (tmp2 = gcry_mpi_set_ui (NULL, 2)));
134 gcry_mpi_mul_2exp (tmp1, tmp1, GNUNET_CRYPTO_PAILLIER_BITS);
136 /* count number of possible operations
137 this would be nicer with gcry_mpi_get_nbits, however it does not return
138 the BITLENGTH of the given MPI's value, but the bits required
139 to represent the number as MPI. */
140 for (possible_opts = -2; gcry_mpi_cmp (tmp1, m) > 0; possible_opts++)
141 gcry_mpi_div (tmp1, NULL, tmp1, tmp2, 0);
142 gcry_mpi_release (tmp1);
143 gcry_mpi_release (tmp2);
145 if (possible_opts < 1)
147 /* soft-cap by caller */
148 possible_opts = (desired_ops < possible_opts)? desired_ops : possible_opts;
150 ciphertext->remaining_ops = htonl (possible_opts);
152 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
154 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
155 highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1;
156 while ( (! gcry_mpi_test_bit (n, highbit)) &&
161 /* invalid public key */
163 gcry_mpi_release (n);
164 return GNUNET_SYSERR;
166 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
167 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
168 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
169 gcry_mpi_mul (n_square, n, n);
171 /* generate r < n (without bias) */
173 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
175 while (gcry_mpi_cmp (r, n) >= 0);
177 /* c = (n+1)^m mod n^2 */
179 gcry_mpi_add_ui (c, n, 1);
180 /* c = (n+1)^m mod n^2 */
181 gcry_mpi_powm (c, c, m, n_square);
182 /* r <- r^n mod n^2 */
183 gcry_mpi_powm (r, r, n, n_square);
184 /* c <- r*c mod n^2 */
185 gcry_mpi_mulm (c, r, c, n_square);
187 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
188 sizeof ciphertext->bits,
191 gcry_mpi_release (n_square);
192 gcry_mpi_release (n);
193 gcry_mpi_release (r);
194 gcry_mpi_release (c);
196 return possible_opts;
201 * Encrypt a plaintext with a paillier public key.
203 * @param public_key Public key to use.
204 * @param m Plaintext to encrypt.
205 * @param desired_ops How many homomorphic ops the caller intends to use
206 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
207 * @return guaranteed number of supported homomorphic operations >= 1,
208 * or desired_ops, in case that is lower,
209 * or -1 if less than one homomorphic operation is possible
212 GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
215 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
226 unsigned int highbit;
228 /* set max_num = 2^{GNUNET_CRYPTO_PAILLIER_BITS}, the largest
229 number we can have as a result */
230 GNUNET_assert (NULL != (max_num = gcry_mpi_set_ui (NULL, 1)));
231 gcry_mpi_mul_2exp (max_num,
233 GNUNET_CRYPTO_PAILLIER_BITS);
235 /* Determine how many operations we could allow, assuming the other
236 number has the same length (or is smaller), by counting the
237 number of possible operations. We essentially divide max_num by
238 2 until the result is no longer larger than 'm', incrementing the
239 maximum number of operations in each round, starting at -2 */
240 for (possible_opts = -2; gcry_mpi_cmp (max_num, m) > 0; possible_opts++)
241 gcry_mpi_div (max_num,
246 gcry_mpi_release (max_num);
248 if (possible_opts < 1)
250 /* Enforce soft-cap by caller */
251 possible_opts = GNUNET_MIN (desired_ops, possible_opts);
252 ciphertext->remaining_ops = htonl (possible_opts);
254 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
256 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
258 /* check public key for number of bits, bail out if key is all zeros */
259 highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1;
260 while ( (! gcry_mpi_test_bit (n, highbit)) &&
265 /* invalid public key */
267 gcry_mpi_release (n);
268 return GNUNET_SYSERR;
271 /* generate r < n (without bias) */
272 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
274 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
276 while (gcry_mpi_cmp (r, n) >= 0);
279 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
280 gcry_mpi_add_ui (g, n, 1);
283 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
284 gcry_mpi_mul (n_square,
288 /* gm = g^m mod n^2 */
289 GNUNET_assert (0 != (gm = gcry_mpi_new (0)));
290 gcry_mpi_powm (gm, g, m, n_square);
291 gcry_mpi_release (g);
293 /* rn <- r^n mod n^2 */
294 GNUNET_assert (0 != (rn = gcry_mpi_new (0)));
295 gcry_mpi_powm (rn, r, n, n_square);
296 gcry_mpi_release (r);
297 gcry_mpi_release (n);
299 /* c <- rn * gm mod n^2 */
300 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
301 gcry_mpi_mulm (c, rn, gm, n_square);
302 gcry_mpi_release (n_square);
303 gcry_mpi_release (gm);
304 gcry_mpi_release (rn);
306 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
307 sizeof (ciphertext->bits),
309 gcry_mpi_release (c);
311 return possible_opts;
316 * Decrypt a paillier ciphertext with a private key.
318 * @param private_key Private key to use for decryption.
319 * @param public_key Public key to use for encryption.
320 * @param ciphertext Ciphertext to decrypt.
321 * @param[out] m Decryption of @a ciphertext with @private_key.
324 GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key,
325 const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
326 const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext,
338 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda,
340 sizeof (private_key->lambda));
341 GNUNET_CRYPTO_mpi_scan_unsigned (&mu,
343 sizeof (private_key->mu));
344 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
346 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
347 GNUNET_CRYPTO_mpi_scan_unsigned (&c,
349 sizeof (ciphertext->bits));
351 /* n_square = n * n */
352 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
353 gcry_mpi_mul (n_square, n, n);
355 /* cmu = c^lambda mod n^2 */
356 GNUNET_assert (0 != (cmu = gcry_mpi_new (0)));
361 gcry_mpi_release (n_square);
362 gcry_mpi_release (lambda);
363 gcry_mpi_release (c);
365 /* cmum1 = cmu - 1 */
366 GNUNET_assert (0 != (cmum1 = gcry_mpi_new (0)));
367 gcry_mpi_sub_ui (cmum1, cmu, 1);
368 gcry_mpi_release (cmu);
370 /* mod = cmum1 / n (mod n) */
371 GNUNET_assert (0 != (mod = gcry_mpi_new (0)));
372 gcry_mpi_div (mod, NULL, cmum1, n, 0);
374 /* m = mod * mu mod n */
375 gcry_mpi_mulm (m, mod, mu, n);
376 gcry_mpi_release (mu);
377 gcry_mpi_release (n);
382 * Compute a ciphertext that represents the sum of the plaintext in @a
385 * Note that this operation can only be done a finite number of times
386 * before an overflow occurs.
388 * @param public_key Public key to use for encryption.
389 * @param c1 Paillier cipher text.
390 * @param c2 Paillier cipher text.
391 * @param[out] result Result of the homomorphic operation.
392 * @return #GNUNET_OK if the result could be computed,
393 * #GNUNET_SYSERR if no more homomorphic operations are remaining.
396 GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
397 const struct GNUNET_CRYPTO_PaillierCiphertext *c1,
398 const struct GNUNET_CRYPTO_PaillierCiphertext *c2,
399 struct GNUNET_CRYPTO_PaillierCiphertext *result)
409 o1 = (int32_t) ntohl (c1->remaining_ops);
410 o2 = (int32_t) ntohl (c2->remaining_ops);
411 if ( (0 >= o1) || (0 >= o2) )
414 return GNUNET_SYSERR;
417 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
420 GNUNET_CRYPTO_mpi_scan_unsigned (&b,
423 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
425 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
427 /* n_square = n * n */
428 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
429 gcry_mpi_mul (n_square, n, n);
430 gcry_mpi_release (n);
432 /* c = a * b mod n_square */
433 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
434 gcry_mpi_mulm (c, a, b, n_square);
435 gcry_mpi_release (n_square);
436 gcry_mpi_release (a);
437 gcry_mpi_release (b);
439 result->remaining_ops = htonl (GNUNET_MIN (o1, o2) - 1);
440 GNUNET_CRYPTO_mpi_print_unsigned (result->bits,
441 sizeof (result->bits),
443 gcry_mpi_release (c);
444 return ntohl (result->remaining_ops);
449 * Get the number of remaining supported homomorphic operations.
451 * @param c Paillier cipher text.
452 * @return the number of remaining homomorphic operations
455 GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c)
457 GNUNET_assert (NULL != c);
458 return ntohl (c->remaining_ops);
461 /* end of crypto_paillier.c */