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