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