Implement a Full Domain Hash (FDH) for RSA signatures and blind signatures
[oweals/gnunet.git] / src / util / test_crypto_rsa.c
1 /*
2   This file is part of GNUnet
3   Copyright (C) 2014,2015 GNUnet e.V.
4
5   GNUnet is free software; you can redistribute it and/or modify it under the
6   terms of the GNU General Public License as published by the Free Software
7   Foundation; either version 3, or (at your option) any later version.
8
9   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
13   You should have received a copy of the GNU General Public License along with
14   TALER; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
15 */
16
17 /**
18  * @file util/test_crypto_rsa.c
19  * @brief testcase for utility functions for RSA cryptography
20  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21  */
22 #include "platform.h"
23 #include <gcrypt.h>
24 #include "gnunet_util_lib.h"
25
26 #define KEY_SIZE 1024
27
28
29 gcry_error_t
30 rsa_full_domain_hash (gcry_mpi_t *r,
31                       const struct GNUNET_HashCode *hash,
32                       const struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
33                       size_t *rsize);
34
35
36 int
37 main (int argc,
38       char *argv[])
39 {
40 #define RND_BLK_SIZE 4096
41   unsigned char rnd_blk[RND_BLK_SIZE];
42   struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
43   struct GNUNET_CRYPTO_rsa_PrivateKey *priv_copy;
44   struct GNUNET_CRYPTO_rsa_PublicKey *pub;
45   struct GNUNET_CRYPTO_rsa_PublicKey *pub_copy;
46   struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
47   struct GNUNET_CRYPTO_rsa_Signature *sig;
48   struct GNUNET_CRYPTO_rsa_Signature *sig_copy;
49   struct GNUNET_CRYPTO_rsa_Signature *bsig;
50   struct GNUNET_HashCode hash;
51   char *blind_buf;
52   size_t bsize;
53   gcry_mpi_t v;
54
55   GNUNET_log_setup ("test-rsa", "WARNING", NULL);
56   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
57                               rnd_blk,
58                               RND_BLK_SIZE);
59   GNUNET_CRYPTO_hash (rnd_blk,
60                       RND_BLK_SIZE,
61                       &hash);
62   priv = GNUNET_CRYPTO_rsa_private_key_create (KEY_SIZE);
63   priv_copy = GNUNET_CRYPTO_rsa_private_key_dup (priv);
64   GNUNET_assert (NULL != priv_copy);
65   GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv, priv_copy));
66   pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
67
68   /* Encoding */
69   size_t size;
70   char *enc;
71   enc = NULL;
72   size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &enc);
73
74   /* Decoding */
75   GNUNET_CRYPTO_rsa_private_key_free (priv);
76   priv = NULL;
77   priv = GNUNET_CRYPTO_rsa_private_key_decode (enc, size);
78   GNUNET_assert (NULL != priv);
79   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
80                               enc, size);
81   GNUNET_assert (NULL == GNUNET_CRYPTO_rsa_private_key_decode (enc, size));
82   (void) fprintf (stderr, "The above warning is expected.\n");
83   GNUNET_free (enc);
84
85   /* test full domain hash size */
86   GNUNET_assert (0 == rsa_full_domain_hash (&v, &hash, pub, NULL));
87   GNUNET_assert (gcry_mpi_get_nbits(v) < KEY_SIZE);
88   gcry_mpi_clear_highbit (v, gcry_mpi_get_nbits(v)-1); /* clear the set high bit */
89   GNUNET_assert (gcry_mpi_get_nbits(v) > 3*KEY_SIZE/4);
90   /* This test necessarily randomly fails with probability 2^(3 - KEY_SIZE/4) */
91   gcry_mpi_release(v);
92
93   /* try ordinary sig first */
94   sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
95                                     &hash);
96   sig_copy = GNUNET_CRYPTO_rsa_signature_dup (sig);
97   GNUNET_assert (NULL != sig);
98   GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig_copy));
99   pub_copy = GNUNET_CRYPTO_rsa_public_key_dup (pub);
100   GNUNET_assert (NULL != pub_copy);
101   GNUNET_assert (GNUNET_OK ==
102                  GNUNET_CRYPTO_rsa_verify (&hash, sig, pub_copy));
103   /* corrupt our hash and see if the signature is still valid */
104   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &hash,
105                               sizeof (struct GNUNET_HashCode));
106   GNUNET_assert (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&hash,
107                                                         sig,
108                                                         pub));
109   (void) fprintf (stderr, "The above warning is expected.\n");
110   GNUNET_CRYPTO_rsa_signature_free (sig);
111
112   /* test blind signing */
113   bkey = GNUNET_CRYPTO_rsa_blinding_key_create (KEY_SIZE);
114   bsize = GNUNET_CRYPTO_rsa_blind (&hash,
115                            bkey,
116                            pub,
117                            &blind_buf);
118   GNUNET_assert (0 != bsize);
119   bsig = GNUNET_CRYPTO_rsa_sign_blinded (priv,
120                                          blind_buf,
121                                          bsize);
122   GNUNET_free (blind_buf);
123   sig = GNUNET_CRYPTO_rsa_unblind (bsig,
124                            bkey,
125                            pub);
126   GNUNET_CRYPTO_rsa_signature_free (bsig);
127   GNUNET_assert (GNUNET_OK ==
128                  GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));  
129   GNUNET_CRYPTO_rsa_signature_free (sig);
130   GNUNET_CRYPTO_rsa_signature_free (sig_copy);
131   GNUNET_CRYPTO_rsa_private_key_free (priv);
132   GNUNET_CRYPTO_rsa_private_key_free (priv_copy);
133   GNUNET_CRYPTO_rsa_public_key_free (pub);
134   GNUNET_CRYPTO_rsa_public_key_free (pub_copy);
135   GNUNET_CRYPTO_rsa_blinding_key_free (bkey);
136   return 0;
137 }