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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
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
40 GNUNET_CRYPTO_PaillierPublicKey *public_key,
41 struct GNUNET_CRYPTO_PaillierPrivateKey *
50 /* Generate two distinct primes. The probability that the loop body
51 is executed more than once is very very low... */
61 gcry_prime_generate (&p,
62 GNUNET_CRYPTO_PAILLIER_BITS / 2,
64 GCRY_STRONG_RANDOM, 0));
66 gcry_prime_generate (&q,
67 GNUNET_CRYPTO_PAILLIER_BITS / 2,
69 GCRY_STRONG_RANDOM, 0));
71 while (0 == gcry_mpi_cmp (p, q));
73 GNUNET_assert (NULL != (n = gcry_mpi_new (0)));
77 GNUNET_CRYPTO_mpi_print_unsigned (public_key,
79 GNUNET_CRYPTO_PaillierPublicKey),
82 /* compute phi(n) = (p-1)(q-1) */
83 GNUNET_assert (NULL != (phi = gcry_mpi_new (0)));
84 gcry_mpi_sub_ui (p, p, 1);
85 gcry_mpi_sub_ui (q, q, 1);
86 gcry_mpi_mul (phi, p, q);
90 /* lambda equals phi(n) in the simplified key generation */
91 GNUNET_CRYPTO_mpi_print_unsigned (private_key->lambda,
92 GNUNET_CRYPTO_PAILLIER_BITS / 8,
94 /* mu = phi^{-1} mod n, as we use g = n + 1 */
95 GNUNET_assert (NULL != (mu = gcry_mpi_new (0)));
96 GNUNET_assert (0 != gcry_mpi_invm (mu,
99 gcry_mpi_release (phi);
100 gcry_mpi_release (n);
101 GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu,
102 GNUNET_CRYPTO_PAILLIER_BITS / 8,
104 gcry_mpi_release (mu);
109 * Encrypt a plaintext with a paillier public key.
111 * @param public_key Public key to use.
112 * @param m Plaintext to encrypt.
113 * @param desired_ops How many homomorphic ops the caller intends to use
114 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
115 * @return guaranteed number of supported homomorphic operations >= 1,
116 * or desired_ops, in case that is lower,
117 * or -1 if less than one homomorphic operation is possible
120 GNUNET_CRYPTO_paillier_encrypt1 (const struct
121 GNUNET_CRYPTO_PaillierPublicKey *public_key,
124 struct GNUNET_CRYPTO_PaillierCiphertext *
134 unsigned int highbit;
136 /* determine how many operations we could allow, if the other number
137 has the same length. */
138 GNUNET_assert (NULL != (tmp1 = gcry_mpi_set_ui (NULL, 1)));
139 GNUNET_assert (NULL != (tmp2 = gcry_mpi_set_ui (NULL, 2)));
140 gcry_mpi_mul_2exp (tmp1, tmp1, GNUNET_CRYPTO_PAILLIER_BITS);
142 /* count number of possible operations
143 this would be nicer with gcry_mpi_get_nbits, however it does not return
144 the BITLENGTH of the given MPI's value, but the bits required
145 to represent the number as MPI. */
146 for (possible_opts = -2; gcry_mpi_cmp (tmp1, m) > 0; possible_opts++)
147 gcry_mpi_div (tmp1, NULL, tmp1, tmp2, 0);
148 gcry_mpi_release (tmp1);
149 gcry_mpi_release (tmp2);
151 if (possible_opts < 1)
153 /* soft-cap by caller */
154 possible_opts = (desired_ops < possible_opts) ? desired_ops : possible_opts;
156 ciphertext->remaining_ops = htonl (possible_opts);
158 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
161 GNUNET_CRYPTO_PaillierPublicKey));
162 highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1;
163 while ((! gcry_mpi_test_bit (n, highbit)) &&
168 /* invalid public key */
170 gcry_mpi_release (n);
171 return GNUNET_SYSERR;
173 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
174 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
175 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
176 gcry_mpi_mul (n_square, n, n);
178 /* generate r < n (without bias) */
181 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
183 while (gcry_mpi_cmp (r, n) >= 0);
185 /* c = (n+1)^m mod n^2 */
187 gcry_mpi_add_ui (c, n, 1);
188 /* c = (n+1)^m mod n^2 */
189 gcry_mpi_powm (c, c, m, n_square);
190 /* r <- r^n mod n^2 */
191 gcry_mpi_powm (r, r, n, n_square);
192 /* c <- r*c mod n^2 */
193 gcry_mpi_mulm (c, r, c, n_square);
195 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
196 sizeof ciphertext->bits,
199 gcry_mpi_release (n_square);
200 gcry_mpi_release (n);
201 gcry_mpi_release (r);
202 gcry_mpi_release (c);
204 return possible_opts;
209 * Encrypt a plaintext with a paillier public key.
211 * @param public_key Public key to use.
212 * @param m Plaintext to encrypt.
213 * @param desired_ops How many homomorphic ops the caller intends to use
214 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
215 * @return guaranteed number of supported homomorphic operations >= 1,
216 * or desired_ops, in case that is lower,
217 * or -1 if less than one homomorphic operation is possible
220 GNUNET_CRYPTO_paillier_encrypt (const struct
221 GNUNET_CRYPTO_PaillierPublicKey *public_key,
224 struct GNUNET_CRYPTO_PaillierCiphertext *
236 unsigned int highbit;
238 /* set max_num = 2^{GNUNET_CRYPTO_PAILLIER_BITS}, the largest
239 number we can have as a result */
240 GNUNET_assert (NULL != (max_num = gcry_mpi_set_ui (NULL, 1)));
241 gcry_mpi_mul_2exp (max_num,
243 GNUNET_CRYPTO_PAILLIER_BITS);
245 /* Determine how many operations we could allow, assuming the other
246 number has the same length (or is smaller), by counting the
247 number of possible operations. We essentially divide max_num by
248 2 until the result is no longer larger than 'm', incrementing the
249 maximum number of operations in each round, starting at -2 */
250 for (possible_opts = -2; gcry_mpi_cmp (max_num, m) > 0; possible_opts++)
251 gcry_mpi_div (max_num,
256 gcry_mpi_release (max_num);
258 if (possible_opts < 1)
260 /* Enforce soft-cap by caller */
261 possible_opts = GNUNET_MIN (desired_ops, possible_opts);
262 ciphertext->remaining_ops = htonl (possible_opts);
264 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
267 GNUNET_CRYPTO_PaillierPublicKey));
269 /* check public key for number of bits, bail out if key is all zeros */
270 highbit = GNUNET_CRYPTO_PAILLIER_BITS - 1;
271 while ((! gcry_mpi_test_bit (n, highbit)) &&
276 /* invalid public key */
278 gcry_mpi_release (n);
279 return GNUNET_SYSERR;
282 /* generate r < n (without bias) */
283 GNUNET_assert (NULL != (r = gcry_mpi_new (0)));
286 gcry_mpi_randomize (r, highbit + 1, GCRY_STRONG_RANDOM);
288 while (gcry_mpi_cmp (r, n) >= 0);
291 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
292 gcry_mpi_add_ui (g, n, 1);
295 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
296 gcry_mpi_mul (n_square,
300 /* gm = g^m mod n^2 */
301 GNUNET_assert (0 != (gm = gcry_mpi_new (0)));
302 gcry_mpi_powm (gm, g, m, n_square);
303 gcry_mpi_release (g);
305 /* rn <- r^n mod n^2 */
306 GNUNET_assert (0 != (rn = gcry_mpi_new (0)));
307 gcry_mpi_powm (rn, r, n, n_square);
308 gcry_mpi_release (r);
309 gcry_mpi_release (n);
311 /* c <- rn * gm mod n^2 */
312 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
313 gcry_mpi_mulm (c, rn, gm, n_square);
314 gcry_mpi_release (n_square);
315 gcry_mpi_release (gm);
316 gcry_mpi_release (rn);
318 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext->bits,
319 sizeof(ciphertext->bits),
321 gcry_mpi_release (c);
323 return possible_opts;
328 * Decrypt a paillier ciphertext with a private key.
330 * @param private_key Private key to use for decryption.
331 * @param public_key Public key to use for encryption.
332 * @param ciphertext Ciphertext to decrypt.
333 * @param[out] m Decryption of @a ciphertext with @private_key.
336 GNUNET_CRYPTO_paillier_decrypt (const struct
337 GNUNET_CRYPTO_PaillierPrivateKey *private_key,
339 GNUNET_CRYPTO_PaillierPublicKey *public_key,
341 GNUNET_CRYPTO_PaillierCiphertext *ciphertext,
353 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda,
355 sizeof(private_key->lambda));
356 GNUNET_CRYPTO_mpi_scan_unsigned (&mu,
358 sizeof(private_key->mu));
359 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
362 GNUNET_CRYPTO_PaillierPublicKey));
363 GNUNET_CRYPTO_mpi_scan_unsigned (&c,
365 sizeof(ciphertext->bits));
367 /* n_square = n * n */
368 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
369 gcry_mpi_mul (n_square, n, n);
371 /* cmu = c^lambda mod n^2 */
372 GNUNET_assert (0 != (cmu = gcry_mpi_new (0)));
377 gcry_mpi_release (n_square);
378 gcry_mpi_release (lambda);
379 gcry_mpi_release (c);
381 /* cmum1 = cmu - 1 */
382 GNUNET_assert (0 != (cmum1 = gcry_mpi_new (0)));
383 gcry_mpi_sub_ui (cmum1, cmu, 1);
384 gcry_mpi_release (cmu);
386 /* mod = cmum1 / n (mod n) */
387 GNUNET_assert (0 != (mod = gcry_mpi_new (0)));
388 gcry_mpi_div (mod, NULL, cmum1, n, 0);
389 gcry_mpi_release (cmum1);
391 /* m = mod * mu mod n */
392 gcry_mpi_mulm (m, mod, mu, n);
393 gcry_mpi_release (mod);
394 gcry_mpi_release (mu);
395 gcry_mpi_release (n);
400 * Compute a ciphertext that represents the sum of the plaintext in @a
403 * Note that this operation can only be done a finite number of times
404 * before an overflow occurs.
406 * @param public_key Public key to use for encryption.
407 * @param c1 Paillier cipher text.
408 * @param c2 Paillier cipher text.
409 * @param[out] result Result of the homomorphic operation.
410 * @return #GNUNET_OK if the result could be computed,
411 * #GNUNET_SYSERR if no more homomorphic operations are remaining.
414 GNUNET_CRYPTO_paillier_hom_add (const struct
415 GNUNET_CRYPTO_PaillierPublicKey *public_key,
417 GNUNET_CRYPTO_PaillierCiphertext *c1,
419 GNUNET_CRYPTO_PaillierCiphertext *c2,
420 struct GNUNET_CRYPTO_PaillierCiphertext *result)
430 o1 = (int32_t) ntohl (c1->remaining_ops);
431 o2 = (int32_t) ntohl (c2->remaining_ops);
432 if ((0 >= o1) || (0 >= o2))
435 return GNUNET_SYSERR;
438 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
441 GNUNET_CRYPTO_mpi_scan_unsigned (&b,
444 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
447 GNUNET_CRYPTO_PaillierPublicKey));
449 /* n_square = n * n */
450 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
451 gcry_mpi_mul (n_square, n, n);
452 gcry_mpi_release (n);
454 /* c = a * b mod n_square */
455 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
456 gcry_mpi_mulm (c, a, b, n_square);
457 gcry_mpi_release (n_square);
458 gcry_mpi_release (a);
459 gcry_mpi_release (b);
461 result->remaining_ops = htonl (GNUNET_MIN (o1, o2) - 1);
462 GNUNET_CRYPTO_mpi_print_unsigned (result->bits,
463 sizeof(result->bits),
465 gcry_mpi_release (c);
466 return ntohl (result->remaining_ops);
471 * Get the number of remaining supported homomorphic operations.
473 * @param c Paillier cipher text.
474 * @return the number of remaining homomorphic operations
477 GNUNET_CRYPTO_paillier_hom_get_remaining (const struct
478 GNUNET_CRYPTO_PaillierCiphertext *c)
480 GNUNET_assert (NULL != c);
481 return ntohl (c->remaining_ops);
484 /* end of crypto_paillier.c */