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 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);
373 gcry_mpi_release (cmum1);
375 /* m = mod * mu mod n */
376 gcry_mpi_mulm (m, mod, mu, n);
377 gcry_mpi_release (mod);
378 gcry_mpi_release (mu);
379 gcry_mpi_release (n);
384 * Compute a ciphertext that represents the sum of the plaintext in @a
387 * Note that this operation can only be done a finite number of times
388 * before an overflow occurs.
390 * @param public_key Public key to use for encryption.
391 * @param c1 Paillier cipher text.
392 * @param c2 Paillier cipher text.
393 * @param[out] result Result of the homomorphic operation.
394 * @return #GNUNET_OK if the result could be computed,
395 * #GNUNET_SYSERR if no more homomorphic operations are remaining.
398 GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
399 const struct GNUNET_CRYPTO_PaillierCiphertext *c1,
400 const struct GNUNET_CRYPTO_PaillierCiphertext *c2,
401 struct GNUNET_CRYPTO_PaillierCiphertext *result)
411 o1 = (int32_t) ntohl (c1->remaining_ops);
412 o2 = (int32_t) ntohl (c2->remaining_ops);
413 if ( (0 >= o1) || (0 >= o2) )
416 return GNUNET_SYSERR;
419 GNUNET_CRYPTO_mpi_scan_unsigned (&a,
422 GNUNET_CRYPTO_mpi_scan_unsigned (&b,
425 GNUNET_CRYPTO_mpi_scan_unsigned (&n,
427 sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
429 /* n_square = n * n */
430 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
431 gcry_mpi_mul (n_square, n, n);
432 gcry_mpi_release (n);
434 /* c = a * b mod n_square */
435 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
436 gcry_mpi_mulm (c, a, b, n_square);
437 gcry_mpi_release (n_square);
438 gcry_mpi_release (a);
439 gcry_mpi_release (b);
441 result->remaining_ops = htonl (GNUNET_MIN (o1, o2) - 1);
442 GNUNET_CRYPTO_mpi_print_unsigned (result->bits,
443 sizeof (result->bits),
445 gcry_mpi_release (c);
446 return ntohl (result->remaining_ops);
451 * Get the number of remaining supported homomorphic operations.
453 * @param c Paillier cipher text.
454 * @return the number of remaining homomorphic operations
457 GNUNET_CRYPTO_paillier_hom_get_remaining (const struct GNUNET_CRYPTO_PaillierCiphertext *c)
459 GNUNET_assert (NULL != c);
460 return ntohl (c->remaining_ops);
463 /* end of crypto_paillier.c */