2 This file is part of GNUnet.
3 (C) 2014 Christian Grothoff (and other contributing authors)
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., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, 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)
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
178 gcry_mpi_add_ui (c, n, 1); // c = n + 1
179 gcry_mpi_powm (c, c, m, n_square); // c = (n+1)^m mod n^2
181 gcry_mpi_powm (r, r, n, n_square); // r = r^n mod n^2
183 gcry_mpi_mulm (c, r, c, n_square); // c = r*c mod n^2
185 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
186 sizeof ciphertext->bits,
189 gcry_mpi_release (n_square);
190 gcry_mpi_release (n);
191 gcry_mpi_release (r);
192 gcry_mpi_release (c);
194 return possible_opts;
199 * Encrypt a plaintext with a paillier public key.
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
210 GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
213 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
224 unsigned int highbit;
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,
231 GNUNET_CRYPTO_PAILLIER_BITS);
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,
244 gcry_mpi_release (max_num);
246 if (possible_opts < 1)
248 /* Enforce soft-cap by caller */
249 possible_opts = GNUNET_MIN (desired_ops, possible_opts);
250 ciphertext->remaining_ops = htonl (possible_opts);
252 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
254 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
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)) &&
263 /* invalid public key */
265 gcry_mpi_release (n);
266 return GNUNET_SYSERR;
269 /* generate r < n (without bias) */
270 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
272 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
274 while (gcry_mpi_cmp (r, n) >= 0);
277 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
278 gcry_mpi_add_ui (g, n, 1);
281 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
282 gcry_mpi_mul (n_square,
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);
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);
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);
304 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
305 sizeof (ciphertext->bits),
307 gcry_mpi_release (c);
309 return possible_opts;
314 * Decrypt a paillier ciphertext with a private key.
316 * @param private_key Private key to use for decryption.
317 * @param public_key Public key to use for encryption.
318 * @param ciphertext Ciphertext to decrypt.
319 * @param[out] m Decryption of @a ciphertext with @private_key.
322 GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key,
323 const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
324 const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext,
336 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda,
338 sizeof (private_key->lambda));
339 GNUNET_CRYPTO_mpi_scan_unsigned (&mu,
341 sizeof (private_key->mu));
342 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
344 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
345 GNUNET_CRYPTO_mpi_scan_unsigned (&c,
347 sizeof (ciphertext->bits));
349 /* n_square = n * n */
350 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
351 gcry_mpi_mul (n_square, n, n);
353 /* cmu = c^lambda mod n^2 */
354 GNUNET_assert (0 != (cmu = gcry_mpi_new (0)));
359 gcry_mpi_release (n_square);
360 gcry_mpi_release (lambda);
361 gcry_mpi_release (c);
363 /* cmum1 = cmu - 1 */
364 GNUNET_assert (0 != (cmum1 = gcry_mpi_new (0)));
365 gcry_mpi_sub_ui (cmum1, cmu, 1);
366 gcry_mpi_release (cmu);
368 /* mod = cmum1 / n (mod n) */
369 GNUNET_assert (0 != (mod = gcry_mpi_new (0)));
370 gcry_mpi_div (mod, NULL, cmum1, n, 0);
372 /* m = mod * mu mod n */
373 gcry_mpi_mulm (m, mod, mu, n);
374 gcry_mpi_release (mu);
375 gcry_mpi_release (n);
380 * Compute a ciphertext that represents the sum of the plaintext in @a
383 * Note that this operation can only be done a finite number of times
384 * before an overflow occurs.
386 * @param public_key Public key to use for encryption.
387 * @param c1 Paillier cipher text.
388 * @param c2 Paillier cipher text.
389 * @param[out] result Result of the homomorphic operation.
390 * @return #GNUNET_OK if the result could be computed,
391 * #GNUNET_SYSERR if no more homomorphic operations are remaining.
394 GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
395 const struct GNUNET_CRYPTO_PaillierCiphertext *c1,
396 const struct GNUNET_CRYPTO_PaillierCiphertext *c2,
397 struct GNUNET_CRYPTO_PaillierCiphertext *result)
407 o1 = (int32_t) ntohl (c1->remaining_ops);
408 o2 = (int32_t) ntohl (c2->remaining_ops);
409 if ( (0 >= o1) || (0 >= o2) )
412 return GNUNET_SYSERR;
415 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
418 GNUNET_CRYPTO_mpi_scan_unsigned (&b,
421 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
423 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
425 /* n_square = n * n */
426 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
427 gcry_mpi_mul (n_square, n, n);
428 gcry_mpi_release (n);
430 /* c = a * b mod n_square */
431 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
432 gcry_mpi_mulm (c, a, b, n_square);
433 gcry_mpi_release (n_square);
434 gcry_mpi_release (a);
435 gcry_mpi_release (b);
437 result->remaining_ops = htonl (GNUNET_MIN (o1, o2) - 1);
438 GNUNET_CRYPTO_mpi_print_unsigned (result->bits,
439 sizeof (result->bits),
441 gcry_mpi_release (c);
442 return ntohl (result->remaining_ops);
447 * Get the number of remaining supported homomorphic operations.
449 * @param c Paillier cipher text.
450 * @return the number of remaining homomorphic operations
453 GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c)
455 GNUNET_assert (NULL != c);
456 return ntohl (c->remaining_ops);
459 /* end of crypto_paillier.c */