aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2014-01-20 23:45:10 +0000
committerFlorian Dold <florian.dold@gmail.com>2014-01-20 23:45:10 +0000
commit6c403a7e4bffbd1e46f75f05190a145bb87de833 (patch)
tree92fca7368b6e3a4c1b88a0bb4a57698a77c60250 /src
parentbcc39cb537deecab2c3e577d67bf2b0f724bbbd7 (diff)
downloadgnunet-6c403a7e4bffbd1e46f75f05190a145bb87de833.tar.gz
gnunet-6c403a7e4bffbd1e46f75f05190a145bb87de833.zip
- paillier implementation and test
Diffstat (limited to 'src')
-rw-r--r--src/util/Makefile.am6
-rw-r--r--src/util/crypto_paillier.c185
-rw-r--r--src/util/test_crypto_paillier.c55
3 files changed, 246 insertions, 0 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index 4fb80285b..dd85f2c09 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -245,6 +245,7 @@ check_PROGRAMS = \
245 test_crypto_ecdhe \ 245 test_crypto_ecdhe \
246 test_crypto_hash \ 246 test_crypto_hash \
247 test_crypto_hkdf \ 247 test_crypto_hkdf \
248 test_crypto_paillier \
248 test_crypto_random \ 249 test_crypto_random \
249 test_disk \ 250 test_disk \
250 test_getopt \ 251 test_getopt \
@@ -397,6 +398,11 @@ test_crypto_hkdf_SOURCES = \
397test_crypto_hkdf_LDADD = \ 398test_crypto_hkdf_LDADD = \
398 $(top_builddir)/src/util/libgnunetutil.la 399 $(top_builddir)/src/util/libgnunetutil.la
399 400
401test_crypto_paillier_SOURCES = \
402 test_crypto_paillier.c
403test_crypto_paillier_LDADD = \
404 $(top_builddir)/src/util/libgnunetutil.la
405
400test_crypto_random_SOURCES = \ 406test_crypto_random_SOURCES = \
401 test_crypto_random.c 407 test_crypto_random.c
402test_crypto_random_LDADD = \ 408test_crypto_random_LDADD = \
diff --git a/src/util/crypto_paillier.c b/src/util/crypto_paillier.c
index b4c2df9b8..4697f14c3 100644
--- a/src/util/crypto_paillier.c
+++ b/src/util/crypto_paillier.c
@@ -28,4 +28,189 @@
28#include <gcrypt.h> 28#include <gcrypt.h>
29#include "gnunet_util_lib.h" 29#include "gnunet_util_lib.h"
30 30
31
32/**
33 * Create a freshly generated paillier public key.
34 *
35 * @param[out] public_key Where to store the public key?
36 * @param[out] private_key Where to store the private key?
37 */
38void
39GNUNET_CRYPTO_paillier_create (struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
40 struct GNUNET_CRYPTO_PaillierPrivateKey *private_key)
41{
42 gcry_mpi_t p;
43 gcry_mpi_t q;
44
45 gcry_mpi_t phi;
46 gcry_mpi_t n;
47
48 GNUNET_assert (NULL != (phi = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS)));
49 GNUNET_assert (NULL != (n = gcry_mpi_new (GNUNET_CRYPTO_PAILLIER_BITS)));
50
51 p = 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 {
57 if (NULL != p)
58 gcry_mpi_release (p);
59 if (NULL != q)
60 gcry_mpi_release (q);
61 // generate rsa modulus
62 GNUNET_assert (0 == gcry_prime_generate (&p, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
63 GCRY_WEAK_RANDOM, 0));
64 GNUNET_assert (0 == gcry_prime_generate (&q, GNUNET_CRYPTO_PAILLIER_BITS / 2, 0, NULL, NULL, NULL,
65 GCRY_WEAK_RANDOM, 0));
66 } while (0 == gcry_mpi_cmp (p, q));
67 gcry_mpi_mul (n, p, q);
68 GNUNET_CRYPTO_mpi_print_unsigned (public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey), n);
69
70 // compute phi(n) = (p-1)(q-1)
71 gcry_mpi_sub_ui (p, p, 1);
72 gcry_mpi_sub_ui (q, q, 1);
73 gcry_mpi_mul (phi, p, q);
74
75 // lambda equals phi(n) in the simplified key generation
76 GNUNET_CRYPTO_mpi_print_unsigned (private_key->lambda, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi);
77
78 // invert phi and abuse the phi mpi to store the result ...
79 GNUNET_assert (0 != gcry_mpi_invm (phi, phi, n));
80 GNUNET_CRYPTO_mpi_print_unsigned (private_key->mu, GNUNET_CRYPTO_PAILLIER_BITS / 8, phi);
81
82 gcry_mpi_release (p);
83 gcry_mpi_release (q);
84 gcry_mpi_release (phi);
85 gcry_mpi_release (n);
86}
87
88
89/**
90 * Encrypt a plaintext with a paillier public key.
91 *
92 * @param public_key Public key to use.
93 * @param plaintext Plaintext to encrypt.
94 * @param[out] ciphertext Encrytion of @a plaintext with @a public_key.
95 */
96void
97GNUNET_CRYPTO_paillier_encrypt (const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
98 const struct GNUNET_CRYPTO_PaillierPlaintext *plaintext,
99 struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext)
100{
101 gcry_mpi_t n_square;
102 gcry_mpi_t r;
103 gcry_mpi_t g;
104 gcry_mpi_t c;
105
106 gcry_mpi_t n;
107 gcry_mpi_t m;
108
109
110 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
111 GNUNET_assert (0 != (r = gcry_mpi_new (0)));
112 GNUNET_assert (0 != (g = gcry_mpi_new (0)));
113 GNUNET_assert (0 != (c = gcry_mpi_new (0)));
114
115 GNUNET_CRYPTO_mpi_scan_unsigned (&m, plaintext, sizeof (struct GNUNET_CRYPTO_PaillierPlaintext));
116 GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof (struct GNUNET_CRYPTO_PaillierPublicKey));
117
118 gcry_mpi_mul (n_square, n, n);
119
120 // generate r < n
121 do
122 {
123 gcry_mpi_randomize (r, GNUNET_CRYPTO_PAILLIER_BITS, GCRY_WEAK_RANDOM);
124 }
125 while (gcry_mpi_cmp (r, n) >= 0);
126
127 // c = (n+1)^m mod n^2
128 gcry_mpi_add_ui (c, n, 1);
129 gcry_mpi_powm (c, c, m, n_square);
130 // r <- r^n mod n^2
131 gcry_mpi_powm (r, r, n, n_square);
132 // c <- r*c mod n^2
133 gcry_mpi_mulm (c, r, c, n_square);
134
135 GNUNET_CRYPTO_mpi_print_unsigned (ciphertext, sizeof *ciphertext, c);
136
137 gcry_mpi_release (n_square);
138 gcry_mpi_release (r);
139 gcry_mpi_release (m);
140 gcry_mpi_release (c);
141}
142
143
144/**
145 * Decrypt a paillier ciphertext with a private key.
146 *
147 * @param private_key Private key to use for decryption.
148 * @param public_key Public key to use for decryption.
149 * @param ciphertext Ciphertext to decrypt.
150 * @param[out] plaintext Decryption of @a ciphertext with @private_key.
151 */
152void
153GNUNET_CRYPTO_paillier_decrypt (const struct GNUNET_CRYPTO_PaillierPrivateKey *private_key,
154 const struct GNUNET_CRYPTO_PaillierPublicKey *public_key,
155 const struct GNUNET_CRYPTO_PaillierCiphertext *ciphertext,
156 struct GNUNET_CRYPTO_PaillierPlaintext *plaintext)
157{
158 gcry_mpi_t m;
159 gcry_mpi_t mu;
160 gcry_mpi_t lambda;
161 gcry_mpi_t n;
162 gcry_mpi_t n_square;
163 gcry_mpi_t c;
164
165 GNUNET_assert (0 != (n_square = gcry_mpi_new (0)));
166 GNUNET_assert (0 != (m = gcry_mpi_new (0)));
167
168 GNUNET_CRYPTO_mpi_scan_unsigned (&lambda, private_key->lambda, sizeof private_key->lambda);
169 GNUNET_CRYPTO_mpi_scan_unsigned (&mu, private_key->mu, sizeof private_key->mu);
170 GNUNET_CRYPTO_mpi_scan_unsigned (&n, public_key, sizeof *public_key);
171 GNUNET_CRYPTO_mpi_scan_unsigned (&c, ciphertext, sizeof *ciphertext);
172
173 gcry_mpi_mul (n_square, n, n);
174 // m = c^lambda mod n^2
175 gcry_mpi_powm (m, c, lambda, n_square);
176 // m = m - 1
177 gcry_mpi_sub_ui (m, m, 1);
178 // m <- m/n
179 gcry_mpi_div (m, NULL, m, n, 0);
180 gcry_mpi_mulm (m, m, mu, n);
181
182 GNUNET_CRYPTO_mpi_print_unsigned (plaintext, sizeof *plaintext, m);
183
184 gcry_mpi_release (m);
185 gcry_mpi_release (mu);
186 gcry_mpi_release (lambda);
187 gcry_mpi_release (n);
188 gcry_mpi_release (n_square);
189 gcry_mpi_release (c);
190}
191
192
193/**
194 * Compute a ciphertext that represents the sum of the plaintext in @a x1 and @a x2
195 *
196 * Note that this operation can only be done a finite number of times
197 * before an overflow occurs.
198 *
199 * @param x1 Paillier cipher text.
200 * @param x2 Paillier cipher text.
201 * @param[out] result Result of the homomorphic operation.
202 * @return #GNUNET_OK if the result could be computed,
203 * #GNUNET_SYSERR if no more homomorphic operations are remaining.
204 */
205int
206GNUNET_CRYPTO_paillier_hom_add (const struct GNUNET_CRYPTO_PaillierCiphertext *x1,
207 const struct GNUNET_CRYPTO_PaillierCiphertext *x2,
208 const struct GNUNET_CRYPTO_PaillierCiphertext *result)
209{
210 // not implemented yet
211 GNUNET_assert (0);
212 return GNUNET_SYSERR;
213}
214
215
31/* end of crypto_paillier.c */ 216/* end of crypto_paillier.c */
diff --git a/src/util/test_crypto_paillier.c b/src/util/test_crypto_paillier.c
new file mode 100644
index 000000000..f380b56f0
--- /dev/null
+++ b/src/util/test_crypto_paillier.c
@@ -0,0 +1,55 @@
1/*
2 This file is part of GNUnet.
3 (C) 2014 Christian Grothoff (and other contributing authors)
4
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.
9
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.
14
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.
19
20*/
21/**
22 * @file util/test_crypto_paillier.c
23 * @brief testcase paillier crypto
24 * @author Florian Dold
25 */
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include <gcrypt.h>
29
30
31int
32main (int argc, char *argv[])
33{
34 struct GNUNET_CRYPTO_PaillierPlaintext plaintext;
35 struct GNUNET_CRYPTO_PaillierPlaintext plaintext_result;
36 struct GNUNET_CRYPTO_PaillierCiphertext ciphertext;
37 struct GNUNET_CRYPTO_PaillierPublicKey public_key;
38 struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
39
40 GNUNET_CRYPTO_paillier_create (&public_key, &private_key);
41
42 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &plaintext, sizeof plaintext);
43 plaintext.bits[0] = 0;
44
45 GNUNET_CRYPTO_paillier_encrypt (&public_key, &plaintext, &ciphertext);
46
47 GNUNET_CRYPTO_paillier_decrypt (&private_key, &public_key,
48 &ciphertext, &plaintext_result);
49
50 if (0 != memcmp (&plaintext, &plaintext_result, sizeof plaintext))
51 return 1;
52 return 0;
53}
54
55/* end of test_crypto_paillier.c */