paragraph for gnunet devs that don't know how to use the web
[oweals/gnunet.git] / src / util / test_crypto_paillier.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2014 GNUnet e.V.
4
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.
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      Affero General Public License for more details.
14     
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/>.
17
18 */
19 /**
20  * @file util/test_crypto_paillier.c
21  * @brief testcase paillier crypto
22  * @author Christian Fuchs
23  * @author Florian Dold
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include <gcrypt.h>
28
29
30 static int
31 test_crypto ()
32 {
33   gcry_mpi_t plaintext;
34   gcry_mpi_t plaintext_result;
35   struct GNUNET_CRYPTO_PaillierCiphertext ciphertext;
36   struct GNUNET_CRYPTO_PaillierPublicKey public_key;
37   struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
38   int ret = 0;
39
40   GNUNET_CRYPTO_paillier_create (&public_key,
41                                  &private_key);
42   GNUNET_assert (NULL != (plaintext = gcry_mpi_new (0)));
43   GNUNET_assert (NULL != (plaintext_result = gcry_mpi_new (0)));
44   gcry_mpi_randomize (plaintext,
45                       GNUNET_CRYPTO_PAILLIER_BITS / 2,
46                       GCRY_WEAK_RANDOM);
47
48   GNUNET_CRYPTO_paillier_encrypt (&public_key,
49                                   plaintext,
50                                   0 /* 0 hom ops */,
51                                   &ciphertext);
52   GNUNET_CRYPTO_paillier_decrypt (&private_key,
53                                   &public_key,
54                                   &ciphertext,
55                                   plaintext_result);
56   if (0 != gcry_mpi_cmp (plaintext,
57                          plaintext_result))
58   {
59     fprintf (stderr,
60              "Paillier decryption failed with plaintext of size %u\n",
61              gcry_mpi_get_nbits (plaintext));
62     gcry_log_debugmpi ("\n",
63                        plaintext);
64     gcry_log_debugmpi ("\n",
65                        plaintext_result);
66     ret = 1;
67   }
68   gcry_mpi_release (plaintext);
69   gcry_mpi_release (plaintext_result);
70   return ret;
71 }
72
73
74 static int
75 test_hom_simple (unsigned int a,
76                  unsigned int b)
77 {
78   gcry_mpi_t m1;
79   gcry_mpi_t m2;
80   gcry_mpi_t result;
81   gcry_mpi_t hom_result;
82   struct GNUNET_CRYPTO_PaillierCiphertext c1;
83   struct GNUNET_CRYPTO_PaillierCiphertext c2;
84   struct GNUNET_CRYPTO_PaillierCiphertext c_result;
85   struct GNUNET_CRYPTO_PaillierPublicKey public_key;
86   struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
87   int ret = 0;
88
89   GNUNET_CRYPTO_paillier_create (&public_key,
90                                  &private_key);
91
92   GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
93   GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
94   GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
95   GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
96   m1 = gcry_mpi_set_ui (m1, a);
97   m2 = gcry_mpi_set_ui (m2, b);
98   gcry_mpi_add (result,
99                 m1,
100                 m2);
101   GNUNET_CRYPTO_paillier_encrypt (&public_key,
102                                   m1,
103                                   2,
104                                   &c1);
105   GNUNET_CRYPTO_paillier_encrypt (&public_key,
106                                   m2,
107                                   2,
108                                   &c2);
109   GNUNET_CRYPTO_paillier_hom_add (&public_key,
110                                   &c1,
111                                   &c2,
112                                   &c_result);
113   GNUNET_CRYPTO_paillier_decrypt (&private_key,
114                                   &public_key,
115                                   &c_result,
116                                   hom_result);
117   if (0 != gcry_mpi_cmp (result, hom_result))
118   {
119     fprintf (stderr,
120              "GNUNET_CRYPTO_paillier failed simple math!\n");
121     gcry_log_debugmpi ("got ", hom_result);
122     gcry_log_debugmpi ("wanted ", result);
123     ret = 1;
124   }
125   gcry_mpi_release (m1);
126   gcry_mpi_release (m2);
127   gcry_mpi_release (result);
128   gcry_mpi_release (hom_result);
129   return ret;
130 }
131
132
133 static int
134 test_hom ()
135 {
136   int ret;
137   gcry_mpi_t m1;
138   gcry_mpi_t m2;
139   gcry_mpi_t result;
140   gcry_mpi_t hom_result;
141   struct GNUNET_CRYPTO_PaillierCiphertext c1;
142   struct GNUNET_CRYPTO_PaillierCiphertext c2;
143   struct GNUNET_CRYPTO_PaillierCiphertext c_result;
144   struct GNUNET_CRYPTO_PaillierPublicKey public_key;
145   struct GNUNET_CRYPTO_PaillierPrivateKey private_key;
146
147   GNUNET_CRYPTO_paillier_create (&public_key,
148                                  &private_key);
149
150   GNUNET_assert (NULL != (m1 = gcry_mpi_new (0)));
151   GNUNET_assert (NULL != (m2 = gcry_mpi_new (0)));
152   GNUNET_assert (NULL != (result = gcry_mpi_new (0)));
153   GNUNET_assert (NULL != (hom_result = gcry_mpi_new (0)));
154   m1 = gcry_mpi_set_ui (m1, 1);
155   /* m1 = m1 * 2 ^ (GCPB - 3) */
156   gcry_mpi_mul_2exp (m1,
157                      m1,
158                      GNUNET_CRYPTO_PAILLIER_BITS - 3);
159   m2 = gcry_mpi_set_ui (m2, 15);
160   /* m1 = m1 * 2 ^ (GCPB / 2) */
161   gcry_mpi_mul_2exp (m2,
162                      m2,
163                      GNUNET_CRYPTO_PAILLIER_BITS / 2);
164   gcry_mpi_add (result,
165                 m1,
166                 m2);
167
168   if (1 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
169                                                   m1,
170                                                   2,
171                                                   &c1)))
172   {
173     fprintf (stderr,
174              "GNUNET_CRYPTO_paillier_encrypt 1 failed, should return 1 allowed operation, got %d!\n",
175              ret);
176     ret = 1;
177     goto out;
178   }
179   if (2 != (ret = GNUNET_CRYPTO_paillier_encrypt (&public_key,
180                                                   m2,
181                                                   2,
182                                                   &c2)))
183   {
184     fprintf (stderr,
185              "GNUNET_CRYPTO_paillier_encrypt 2 failed, should return 2 allowed operation, got %d!\n",
186              ret);
187     ret = 1;
188     goto out;
189   }
190
191   if (0 != (ret = GNUNET_CRYPTO_paillier_hom_add (&public_key,
192                                                   &c1,
193                                                   &c2,
194                                                   &c_result)))
195   {
196     fprintf (stderr,
197              "GNUNET_CRYPTO_paillier_hom_add failed, expected 0 remaining operations, got %d!\n",
198              ret);
199     ret = 1;
200     goto out;
201   }
202
203   GNUNET_CRYPTO_paillier_decrypt (&private_key,
204                                   &public_key,
205                                   &c_result,
206                                   hom_result);
207
208   if (0 != gcry_mpi_cmp (result, hom_result))
209   {
210     fprintf (stderr,
211              "GNUNET_CRYPTO_paillier miscalculated with large numbers!\n");
212     gcry_log_debugmpi ("got", hom_result);
213     gcry_log_debugmpi ("wanted", result);
214     ret = 1;
215   }
216 out:
217   gcry_mpi_release (m1);
218   gcry_mpi_release (m2);
219   gcry_mpi_release (result);
220   gcry_mpi_release (hom_result);
221   return ret;
222 }
223
224
225 int
226 main (int argc,
227       char *argv[])
228 {
229   int ret;
230   ret = test_crypto ();
231   if (0 != ret)
232     return ret;
233   ret = test_hom_simple (2,4);
234   if (0 != ret)
235     return ret;
236   ret = test_hom_simple (13,17);
237   if (0 != ret)
238     return ret;
239   ret = test_hom ();
240   return ret;
241 }
242
243 /* end of test_crypto_paillier.c */