aboutsummaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-01-09 15:51:57 +0000
committerChristian Grothoff <christian@grothoff.org>2015-01-09 15:51:57 +0000
commitefd634ccf636b870b2dbd79f8969f8999c5573fa (patch)
tree4492353a28bf7add22f9ea7a42233a6bd679ca44 /src/util
parent8215376b2d1b4a3d95a0cf1ba474cf4be437c1b0 (diff)
downloadgnunet-efd634ccf636b870b2dbd79f8969f8999c5573fa.tar.gz
gnunet-efd634ccf636b870b2dbd79f8969f8999c5573fa.zip
adding support for blind signatures (modernized version of Taler logic, with variable key length)
Diffstat (limited to 'src/util')
-rw-r--r--src/util/Makefile.am7
-rw-r--r--src/util/crypto_rsa.c796
-rw-r--r--src/util/test_crypto_rsa.c82
3 files changed, 885 insertions, 0 deletions
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index a71dd76df..87651e620 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -88,6 +88,7 @@ libgnunetutil_la_SOURCES = \
88 crypto_mpi.c \ 88 crypto_mpi.c \
89 crypto_paillier.c \ 89 crypto_paillier.c \
90 crypto_random.c \ 90 crypto_random.c \
91 crypto_rsa.c \
91 disk.c \ 92 disk.c \
92 disk.h \ 93 disk.h \
93 getopt.c \ 94 getopt.c \
@@ -229,6 +230,7 @@ check_PROGRAMS = \
229 test_crypto_hkdf \ 230 test_crypto_hkdf \
230 test_crypto_paillier \ 231 test_crypto_paillier \
231 test_crypto_random \ 232 test_crypto_random \
233 test_crypto_rsa \
232 test_disk \ 234 test_disk \
233 test_getopt \ 235 test_getopt \
234 test_connection.nc \ 236 test_connection.nc \
@@ -404,6 +406,11 @@ test_crypto_random_SOURCES = \
404test_crypto_random_LDADD = \ 406test_crypto_random_LDADD = \
405 libgnunetutil.la 407 libgnunetutil.la
406 408
409test_crypto_rsa_SOURCES = \
410 test_crypto_rsa.c
411test_crypto_rsa_LDADD = \
412 libgnunetutil.la
413
407test_disk_SOURCES = \ 414test_disk_SOURCES = \
408 test_disk.c 415 test_disk.c
409test_disk_LDADD = \ 416test_disk_LDADD = \
diff --git a/src/util/crypto_rsa.c b/src/util/crypto_rsa.c
new file mode 100644
index 000000000..c14e6b9b1
--- /dev/null
+++ b/src/util/crypto_rsa.c
@@ -0,0 +1,796 @@
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 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 GNUnet; see the file COPYING. If not, If not, see <http://www.gnu.org/licenses/>
15*/
16
17/**
18 * @file util/crypto_rsa.c
19 * @brief Chaum-style Blind signatures based on RSA
20 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
21 * @author Christian Grothoff
22 */
23#include "platform.h"
24#include <gcrypt.h>
25#include "gnunet_util_lib.h"
26
27#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
28
29
30/**
31 * The private information of an RSA key pair.
32 */
33struct GNUNET_CRYPTO_rsa_PrivateKey
34{
35 /**
36 * Libgcrypt S-expression for the RSA private key.
37 */
38 gcry_sexp_t sexp;
39};
40
41
42/**
43 * The public information of an RSA key pair.
44 */
45struct GNUNET_CRYPTO_rsa_PublicKey
46{
47 /**
48 * Libgcrypt S-expression for the RSA public key.
49 */
50 gcry_sexp_t sexp;
51};
52
53
54/**
55 * @brief an RSA signature
56 */
57struct GNUNET_CRYPTO_rsa_Signature
58{
59 /**
60 * Libgcrypt S-expression for the RSA signature.
61 */
62 gcry_sexp_t sexp;
63};
64
65
66/**
67 * @brief RSA blinding key
68 */
69struct GNUNET_CRYPTO_rsa_BlindingKey
70{
71 /**
72 * Random value used for blinding.
73 */
74 gcry_mpi_t r;
75};
76
77
78/**
79 * Extract values from an S-expression.
80 *
81 * @param array where to store the result(s)
82 * @param sexp S-expression to parse
83 * @param topname top-level name in the S-expression that is of interest
84 * @param elems names of the elements to extract
85 * @return 0 on success
86 */
87static int
88key_from_sexp (gcry_mpi_t *array,
89 gcry_sexp_t sexp,
90 const char *topname,
91 const char *elems)
92{
93 gcry_sexp_t list;
94 gcry_sexp_t l2;
95 const char *s;
96 unsigned int i;
97 unsigned int idx;
98
99 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
100 return 1;
101 l2 = gcry_sexp_cadr (list);
102 gcry_sexp_release (list);
103 list = l2;
104 if (! list)
105 return 2;
106 idx = 0;
107 for (s = elems; *s; s++, idx++)
108 {
109 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
110 {
111 for (i = 0; i < idx; i++)
112 {
113 gcry_free (array[i]);
114 array[i] = NULL;
115 }
116 gcry_sexp_release (list);
117 return 3; /* required parameter not found */
118 }
119 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
120 gcry_sexp_release (l2);
121 if (! array[idx])
122 {
123 for (i = 0; i < idx; i++)
124 {
125 gcry_free (array[i]);
126 array[i] = NULL;
127 }
128 gcry_sexp_release (list);
129 return 4; /* required parameter is invalid */
130 }
131 }
132 gcry_sexp_release (list);
133 return 0;
134}
135
136
137/**
138 * Create a new private key. Caller must free return value.
139 *
140 * @param len length of the key in bits (i.e. 2048)
141 * @return fresh private key
142 */
143struct GNUNET_CRYPTO_rsa_PrivateKey *
144GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
145{
146 struct GNUNET_CRYPTO_rsa_PrivateKey *ret;
147 gcry_sexp_t s_key;
148 gcry_sexp_t s_keyparam;
149
150 GNUNET_assert (0 ==
151 gcry_sexp_build (&s_keyparam,
152 NULL,
153 "(genkey(rsa(nbits %d)))",
154 len));
155 GNUNET_assert (0 ==
156 gcry_pk_genkey (&s_key,
157 s_keyparam));
158 gcry_sexp_release (s_keyparam);
159#if EXTRA_CHECKS
160 GNUNET_assert (0 ==
161 gcry_pk_testkey (s_key));
162#endif
163 ret = GNUNET_new (struct GNUNET_CRYPTO_rsa_PrivateKey);
164 ret->sexp = s_key;
165 return ret;
166}
167
168
169/**
170 * Free memory occupied by the private key.
171 *
172 * @param key pointer to the memory to free
173 */
174void
175GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_rsa_PrivateKey *key)
176{
177 gcry_sexp_release (key->sexp);
178 GNUNET_free (key);
179}
180
181
182/**
183 * Encode the private key in a format suitable for
184 * storing it into a file.
185 *
186 * @param key the private key
187 * @param[out] buffer set to a buffer with the encoded key
188 * @return size of memory allocated in @a buffer
189 */
190size_t
191GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
192 char **buffer)
193{
194 size_t n;
195 char *b;
196
197 n = gcry_sexp_sprint (key->sexp,
198 GCRYSEXP_FMT_DEFAULT,
199 NULL,
200 0);
201 b = GNUNET_malloc (n);
202 GNUNET_assert (n ==
203 gcry_sexp_sprint (key->sexp,
204 GCRYSEXP_FMT_DEFAULT,
205 b,
206 n));
207 *buffer = b;
208 return n;
209}
210
211
212/**
213 * Decode the private key from the data-format back
214 * to the "normal", internal format.
215 *
216 * @param buf the buffer where the private key data is stored
217 * @param len the length of the data in @a buf
218 * @return NULL on error
219 */
220struct GNUNET_CRYPTO_rsa_PrivateKey *
221GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
222 size_t len)
223{
224 struct GNUNET_CRYPTO_rsa_PrivateKey *key;
225
226 key = GNUNET_new (struct GNUNET_CRYPTO_rsa_PrivateKey);
227 if (0 !=
228 gcry_sexp_new (&key->sexp,
229 buf,
230 len,
231 0))
232 {
233 GNUNET_break_op (0);
234 GNUNET_free (key);
235 return NULL;
236 }
237 /* FIXME: verify that this is an RSA private key */
238 return key;
239}
240
241
242/**
243 * Extract the public key of the given private key.
244 *
245 * @param priv the private key
246 * @retur NULL on error, otherwise the public key
247 */
248struct GNUNET_CRYPTO_rsa_PublicKey *
249GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_rsa_PrivateKey *priv)
250{
251 struct GNUNET_CRYPTO_rsa_PublicKey *pub;
252 gcry_mpi_t ne[2];
253 int rc;
254 gcry_sexp_t result;
255
256 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
257 if (0 != rc)
258 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
259 if (0 != rc)
260 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
261 if (0 != rc)
262 {
263 GNUNET_break_op (0);
264 return NULL;
265 }
266 rc = gcry_sexp_build (&result,
267 NULL,
268 "(public-key(rsa(n %m)(e %m)))",
269 ne[0],
270 ne[1]);
271 gcry_mpi_release (ne[0]);
272 gcry_mpi_release (ne[1]);
273 pub = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey);
274 pub->sexp = result;
275 return pub;
276}
277
278
279/**
280 * Free memory occupied by the public key.
281 *
282 * @param key pointer to the memory to free
283 */
284void
285GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_rsa_PublicKey *key)
286{
287 gcry_sexp_release (key->sexp);
288 GNUNET_free (key);
289}
290
291
292/**
293 * Encode the public key in a format suitable for
294 * storing it into a file.
295 *
296 * @param key the private key
297 * @param[out] buffer set to a buffer with the encoded key
298 * @return size of memory allocated in @a buffer
299 */
300size_t
301GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_rsa_PublicKey *key,
302 char **buffer)
303{
304 size_t n;
305 char *b;
306
307 n = gcry_sexp_sprint (key->sexp,
308 GCRYSEXP_FMT_ADVANCED,
309 NULL,
310 0);
311 b = GNUNET_malloc (n);
312 GNUNET_assert (n ==
313 gcry_sexp_sprint (key->sexp,
314 GCRYSEXP_FMT_ADVANCED,
315 b,
316 n));
317 *buffer = b;
318 return n;
319}
320
321
322/**
323 * Decode the public key from the data-format back
324 * to the "normal", internal format.
325 *
326 * @param buf the buffer where the public key data is stored
327 * @param len the length of the data in @a buf
328 * @return NULL on error
329 */
330struct GNUNET_CRYPTO_rsa_PublicKey *
331GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
332 size_t len)
333{
334 struct GNUNET_CRYPTO_rsa_PublicKey *key;
335 gcry_mpi_t n;
336 int ret;
337
338 key = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey);
339 if (0 !=
340 gcry_sexp_new (&key->sexp,
341 buf,
342 len,
343 0))
344 {
345 GNUNET_break_op (0);
346 GNUNET_free (key);
347 return NULL;
348 }
349 /* verify that this is an RSA public key */
350 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
351 if (0 != ret)
352 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
353 if (0 != ret)
354 {
355 /* this is no public RSA key */
356 GNUNET_break (0);
357 gcry_sexp_release (key->sexp);
358 GNUNET_free (key);
359 return NULL;
360 }
361 gcry_mpi_release (n);
362 return key;
363}
364
365
366/**
367 * Create a blinding key
368 *
369 * @param len length of the key in bits (i.e. 2048)
370 * @return the newly created blinding key
371 */
372struct GNUNET_CRYPTO_rsa_BlindingKey *
373GNUNET_CRYPTO_rsa_blinding_key_create (unsigned int len)
374{
375 struct GNUNET_CRYPTO_rsa_BlindingKey *blind;
376
377 blind = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
378 blind->r = gcry_mpi_new (len);
379 gcry_mpi_randomize (blind->r,
380 len,
381 GCRY_STRONG_RANDOM);
382 return blind;
383}
384
385
386/**
387 * Destroy a blinding key
388 *
389 * @param bkey the blinding key to destroy
390 */
391void
392GNUNET_CRYPTO_rsa_blinding_key_free (struct GNUNET_CRYPTO_rsa_BlindingKey *bkey)
393{
394 gcry_mpi_release (bkey->r);
395 GNUNET_free (bkey);
396}
397
398
399/**
400 * Encode the blinding key in a format suitable for
401 * storing it into a file.
402 *
403 * @param bkey the blinding key
404 * @param[out] buffer set to a buffer with the encoded key
405 * @return size of memory allocated in @a buffer
406 */
407size_t
408GNUNET_CRYPTO_rsa_blinding_key_encode (const struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
409 char **buffer)
410{
411 size_t n;
412 char *b;
413 size_t rsize;
414
415 gcry_mpi_print (GCRYMPI_FMT_USG,
416 NULL,
417 0,
418 &n,
419 bkey->r);
420 b = GNUNET_malloc (n);
421 GNUNET_assert (0 ==
422 gcry_mpi_print (GCRYMPI_FMT_USG,
423 (unsigned char *) b,
424 n,
425 &rsize,
426 bkey->r));
427 *buffer = b;
428 return n;
429}
430
431
432/**
433 * Decode the blinding key from the data-format back
434 * to the "normal", internal format.
435 *
436 * @param buf the buffer where the public key data is stored
437 * @param len the length of the data in @a buf
438 * @return NULL on error
439 */
440struct GNUNET_CRYPTO_rsa_BlindingKey *
441GNUNET_CRYPTO_rsa_blinding_key_decode (const char *buf,
442 size_t len)
443{
444 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
445 size_t rsize;
446
447 bkey = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
448 if (0 !=
449 gcry_mpi_scan (&bkey->r,
450 GCRYMPI_FMT_USG,
451 (const unsigned char *) buf,
452 len,
453 &rsize))
454 {
455 GNUNET_break_op (0);
456 GNUNET_free (bkey);
457 return NULL;
458 }
459 return bkey;
460}
461
462
463/**
464 * Blinds the given message with the given blinding key
465 *
466 * @param hash hash of the message to sign
467 * @param bkey the blinding key
468 * @param pkey the public key of the signer
469 * @param[out] buffer set to a buffer with the blinded message to be signed
470 * @return number of bytes stored in @a buffer
471 */
472size_t
473GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
474 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
475 struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
476 char **buffer)
477{
478 gcry_mpi_t data;
479 gcry_mpi_t ne[2];
480 gcry_mpi_t r_e;
481 gcry_mpi_t data_r_e;
482 size_t rsize;
483 size_t n;
484 gcry_error_t rc;
485 char *b;
486 int ret;
487
488 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
489 if (0 != ret)
490 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
491 if (0 != ret)
492 {
493 GNUNET_break (0);
494 *buffer = NULL;
495 return 0;
496 }
497 if (0 != (rc = gcry_mpi_scan (&data,
498 GCRYMPI_FMT_USG,
499 (const unsigned char *) hash,
500 sizeof (struct GNUNET_HashCode),
501 &rsize)))
502 {
503 GNUNET_break (0);
504 gcry_mpi_release (ne[0]);
505 gcry_mpi_release (ne[1]);
506 *buffer = NULL;
507 return 0;
508 }
509 r_e = gcry_mpi_new (0);
510 gcry_mpi_powm (r_e,
511 bkey->r,
512 ne[1],
513 ne[0]);
514 data_r_e = gcry_mpi_new (0);
515 gcry_mpi_mulm (data_r_e,
516 data,
517 r_e,
518 ne[0]);
519 gcry_mpi_release (ne[0]);
520 gcry_mpi_release (ne[1]);
521 gcry_mpi_release (r_e);
522
523 gcry_mpi_print (GCRYMPI_FMT_USG,
524 NULL,
525 0,
526 &n,
527 data_r_e);
528 b = GNUNET_malloc (n);
529 rc = gcry_mpi_print (GCRYMPI_FMT_USG,
530 (unsigned char *) b,
531 n,
532 &rsize,
533 data_r_e);
534 gcry_mpi_release (data_r_e);
535 *buffer = b;
536 return n;
537}
538
539
540/**
541 * Convert the data specified in the given purpose argument to an
542 * S-expression suitable for signature operations.
543 *
544 * @param ptr pointer to the data to convert
545 * @param size the size of the data
546 * @return converted s-expression
547 */
548static gcry_sexp_t
549data_to_sexp (const void *ptr, size_t size)
550{
551 gcry_mpi_t value;
552 gcry_sexp_t data;
553
554 value = NULL;
555 data = NULL;
556 GNUNET_assert (0 ==
557 gcry_mpi_scan (&value,
558 GCRYMPI_FMT_USG,
559 ptr,
560 size,
561 NULL));
562 GNUNET_assert (0 ==
563 gcry_sexp_build (&data,
564 NULL,
565 "(data (flags raw) (value %M))",
566 value));
567 gcry_mpi_release (value);
568 return data;
569}
570
571
572/**
573 * Sign the given message.
574 *
575 * @param key private key to use for the signing
576 * @param msg the message to sign
577 * @param msg_len number of bytes in @a msg to sign
578 * @return NULL on error, signature on success
579 */
580struct GNUNET_CRYPTO_rsa_Signature *
581GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
582 const void *msg,
583 size_t msg_len)
584{
585 struct GNUNET_CRYPTO_rsa_Signature *sig;
586 gcry_sexp_t result;
587 gcry_sexp_t data;
588
589 data = data_to_sexp (msg,
590 msg_len);
591 if (0 !=
592 gcry_pk_sign (&result,
593 data,
594 key->sexp))
595 {
596 GNUNET_break (0);
597 return NULL;
598 }
599 gcry_sexp_release (data);
600 sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
601 sig->sexp = result;
602 return sig;
603}
604
605
606/**
607 * Free memory occupied by signature.
608 *
609 * @param sig memory to freee
610 */
611void
612GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_rsa_Signature *sig)
613{
614 gcry_sexp_release (sig->sexp);
615 GNUNET_free (sig);
616}
617
618
619/**
620 * Encode the signature key in a format suitable for
621 * storing it into a file.
622 *
623 * @param sig the signature
624 * @param[out] buffer set to a buffer with the encoded key
625 * @return size of memory allocated in @a buffer
626 */
627size_t
628GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_rsa_Signature *sig,
629 char **buffer)
630{
631 size_t n;
632 char *b;
633
634 n = gcry_sexp_sprint (sig->sexp,
635 GCRYSEXP_FMT_ADVANCED,
636 NULL,
637 0);
638 b = GNUNET_malloc (n);
639 GNUNET_assert (n ==
640 gcry_sexp_sprint (sig->sexp,
641 GCRYSEXP_FMT_ADVANCED,
642 b,
643 n));
644 *buffer = b;
645 return n;
646}
647
648
649/**
650 * Decode the public key from the data-format back
651 * to the "normal", internal format.
652 *
653 * @param buf the buffer where the public key data is stored
654 * @param len the length of the data in @a buf
655 * @return NULL on error
656 */
657struct GNUNET_CRYPTO_rsa_Signature *
658GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
659 size_t len)
660{
661 struct GNUNET_CRYPTO_rsa_Signature *sig;
662 int ret;
663 gcry_mpi_t s;
664
665 sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
666 if (0 !=
667 gcry_sexp_new (&sig->sexp,
668 buf,
669 len,
670 0))
671 {
672 GNUNET_break_op (0);
673 GNUNET_free (sig);
674 return NULL;
675 }
676 /* verify that this is an RSA signature */
677 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
678 if (0 != ret)
679 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
680 if (0 != ret)
681 {
682 /* this is no RSA Signature */
683 GNUNET_break_op (0);
684 gcry_sexp_release (sig->sexp);
685 GNUNET_free (sig);
686 return NULL;
687 }
688 gcry_mpi_release (s);
689 return sig;
690}
691
692
693/**
694 * Unblind a signature made on blinding signature purpose. The signature
695 * purpose should have been generated with #GNUNET_CRYPTO_rsa_sign() using
696 * a message that was generated with #GNUNET_CRYPTO_rsa_blind().
697 *
698 * @param sig the signature made on the blinded signature purpose
699 * @param bkey the blinding key used to blind the signature purpose
700 * @param pkey the public key of the signer
701 * @return unblinded signature on success, NULL on error
702 */
703struct GNUNET_CRYPTO_rsa_Signature *
704GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_rsa_Signature *sig,
705 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
706 struct GNUNET_CRYPTO_rsa_PublicKey *pkey)
707{
708 gcry_mpi_t n;
709 gcry_mpi_t s;
710 gcry_mpi_t r_inv;
711 gcry_mpi_t ubsig;
712 int ret;
713 struct GNUNET_CRYPTO_rsa_Signature *sret;
714
715 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
716 if (0 != ret)
717 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
718 if (0 != ret)
719 {
720 GNUNET_break_op (0);
721 return NULL;
722 }
723 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
724 if (0 != ret)
725 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
726 if (0 != ret)
727 {
728 gcry_mpi_release (n);
729 GNUNET_break_op (0);
730 return NULL;
731 }
732 r_inv = gcry_mpi_new (0);
733 if (1 !=
734 gcry_mpi_invm (r_inv,
735 bkey->r,
736 n))
737 {
738 GNUNET_break_op (0);
739 gcry_mpi_release (n);
740 gcry_mpi_release (r_inv);
741 gcry_mpi_release (s);
742 return NULL;
743 }
744 ubsig = gcry_mpi_new (0);
745 gcry_mpi_mulm (ubsig, s, r_inv, n);
746 gcry_mpi_release (n);
747 gcry_mpi_release (r_inv);
748 gcry_mpi_release (s);
749
750 sret = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
751 GNUNET_assert (0 ==
752 gcry_sexp_build (&sret->sexp,
753 NULL,
754 "(sig-val (rsa (s %M)))",
755 ubsig));
756 gcry_mpi_release (ubsig);
757 return sret;
758}
759
760
761/**
762 * Verify signature with the given hash.
763 *
764 * @param hash hash of the message to verify to match the @a sig
765 * @param sig signature that is being validated
766 * @param public_key public key of the signer
767 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
768 */
769int
770GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
771 const struct GNUNET_CRYPTO_rsa_Signature *sig,
772 const struct GNUNET_CRYPTO_rsa_PublicKey *public_key)
773{
774 gcry_sexp_t data;
775 int rc;
776
777 data = data_to_sexp (hash,
778 sizeof (struct GNUNET_HashCode));
779 rc = gcry_pk_verify (sig->sexp,
780 data,
781 public_key->sexp);
782 gcry_sexp_release (data);
783 if (0 != rc)
784 {
785 LOG (GNUNET_ERROR_TYPE_WARNING,
786 _("RSA signature verification failed at %s:%d: %s\n"),
787 __FILE__,
788 __LINE__,
789 gcry_strerror (rc));
790 return GNUNET_SYSERR;
791 }
792 return GNUNET_OK;
793}
794
795
796/* end of util/rsa.c */
diff --git a/src/util/test_crypto_rsa.c b/src/util/test_crypto_rsa.c
new file mode 100644
index 000000000..a0a6b4722
--- /dev/null
+++ b/src/util/test_crypto_rsa.c
@@ -0,0 +1,82 @@
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 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 <gnunet/gnunet_util_lib.h>
24
25#define KEY_SIZE 1024
26
27
28int
29main (int argc,
30 char *argv[])
31{
32#define RND_BLK_SIZE 4096
33 unsigned char rnd_blk[RND_BLK_SIZE];
34 struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
35 struct GNUNET_CRYPTO_rsa_PublicKey *pub;
36 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
37 struct GNUNET_CRYPTO_rsa_Signature *sig;
38 struct GNUNET_CRYPTO_rsa_Signature *bsig;
39 struct GNUNET_HashCode hash;
40 char *blind_buf;
41 size_t bsize;
42
43 GNUNET_log_setup ("test-rsa", "WARNING", NULL);
44 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
45 rnd_blk,
46 RND_BLK_SIZE);
47 GNUNET_CRYPTO_hash (rnd_blk,
48 RND_BLK_SIZE,
49 &hash);
50 priv = GNUNET_CRYPTO_rsa_private_key_create (KEY_SIZE);
51 pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
52 /* try ordinary sig first */
53 sig = GNUNET_CRYPTO_rsa_sign (priv,
54 &hash,
55 sizeof (hash));
56 GNUNET_assert (GNUNET_OK ==
57 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
58 GNUNET_CRYPTO_rsa_signature_free (sig);
59
60 /* test blind signing */
61 bkey = GNUNET_CRYPTO_rsa_blinding_key_create (KEY_SIZE);
62 bsize = GNUNET_CRYPTO_rsa_blind (&hash,
63 bkey,
64 pub,
65 &blind_buf);
66 GNUNET_assert (0 != bsize);
67 bsig = GNUNET_CRYPTO_rsa_sign (priv,
68 blind_buf,
69 bsize);
70 GNUNET_free (blind_buf);
71 sig = GNUNET_CRYPTO_rsa_unblind (bsig,
72 bkey,
73 pub);
74 GNUNET_CRYPTO_rsa_signature_free (bsig);
75 GNUNET_assert (GNUNET_OK ==
76 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
77 GNUNET_CRYPTO_rsa_signature_free (sig);
78 GNUNET_CRYPTO_rsa_private_key_free (priv);
79 GNUNET_CRYPTO_rsa_public_key_free (pub);
80 GNUNET_CRYPTO_rsa_blinding_key_free (bkey);
81 return 0;
82}