2 This file is part of GNUnet
3 Copyright (C) 2014 GNUnet e.V.
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.
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.
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/>
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
25 #include "gnunet_crypto_lib.h"
27 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
31 * The private information of an RSA key pair.
33 struct GNUNET_CRYPTO_RsaPrivateKey
36 * Libgcrypt S-expression for the RSA private key.
43 * The public information of an RSA key pair.
45 struct GNUNET_CRYPTO_RsaPublicKey
48 * Libgcrypt S-expression for the RSA public key.
55 * @brief an RSA signature
57 struct GNUNET_CRYPTO_RsaSignature
60 * Libgcrypt S-expression for the RSA signature.
67 * @brief RSA blinding key
69 struct GNUNET_CRYPTO_rsa_BlindingKey
72 * Random value used for blinding.
79 * Extract values from an S-expression.
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
88 key_from_sexp (gcry_mpi_t *array,
99 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
101 l2 = gcry_sexp_cadr (list);
102 gcry_sexp_release (list);
107 for (s = elems; *s; s++, idx++)
109 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
111 for (i = 0; i < idx; i++)
113 gcry_free (array[i]);
116 gcry_sexp_release (list);
117 return 3; /* required parameter not found */
119 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
120 gcry_sexp_release (l2);
123 for (i = 0; i < idx; i++)
125 gcry_free (array[i]);
128 gcry_sexp_release (list);
129 return 4; /* required parameter is invalid */
132 gcry_sexp_release (list);
138 * Create a new private key. Caller must free return value.
140 * @param len length of the key in bits (i.e. 2048)
141 * @return fresh private key
143 struct GNUNET_CRYPTO_RsaPrivateKey *
144 GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
146 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
148 gcry_sexp_t s_keyparam;
151 gcry_sexp_build (&s_keyparam,
153 "(genkey(rsa(nbits %d)))",
156 gcry_pk_genkey (&s_key,
158 gcry_sexp_release (s_keyparam);
161 gcry_pk_testkey (s_key));
163 ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
170 * Free memory occupied by the private key.
172 * @param key pointer to the memory to free
175 GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
177 gcry_sexp_release (key->sexp);
183 * Encode the private key in a format suitable for
184 * storing it into a file.
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
191 GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
197 n = gcry_sexp_sprint (key->sexp,
198 GCRYSEXP_FMT_DEFAULT,
201 b = GNUNET_malloc (n);
202 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
203 gcry_sexp_sprint (key->sexp,
204 GCRYSEXP_FMT_DEFAULT,
213 * Decode the private key from the data-format back
214 * to the "normal", internal format.
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
220 struct GNUNET_CRYPTO_RsaPrivateKey *
221 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
224 struct GNUNET_CRYPTO_RsaPrivateKey *key;
225 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
227 gcry_sexp_new (&key->sexp,
232 LOG (GNUNET_ERROR_TYPE_WARNING,
233 "Decoded private key is not valid\n");
237 if (0 != gcry_pk_testkey (key->sexp))
239 LOG (GNUNET_ERROR_TYPE_WARNING,
240 "Decoded private key is not valid\n");
241 GNUNET_CRYPTO_rsa_private_key_free (key);
249 * Extract the public key of the given private key.
251 * @param priv the private key
252 * @retur NULL on error, otherwise the public key
254 struct GNUNET_CRYPTO_RsaPublicKey *
255 GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
257 struct GNUNET_CRYPTO_RsaPublicKey *pub;
262 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
264 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
266 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
272 rc = gcry_sexp_build (&result,
274 "(public-key(rsa(n %m)(e %m)))",
277 gcry_mpi_release (ne[0]);
278 gcry_mpi_release (ne[1]);
279 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
286 * Free memory occupied by the public key.
288 * @param key pointer to the memory to free
291 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
293 gcry_sexp_release (key->sexp);
299 * Encode the public key in a format suitable for
300 * storing it into a file.
302 * @param key the private key
303 * @param[out] buffer set to a buffer with the encoded key
304 * @return size of memory allocated in @a buffer
307 GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key,
313 n = gcry_sexp_sprint (key->sexp,
314 GCRYSEXP_FMT_ADVANCED,
317 b = GNUNET_malloc (n);
318 GNUNET_assert ((n -1) == /* since the last byte is \0 */
319 gcry_sexp_sprint (key->sexp,
320 GCRYSEXP_FMT_ADVANCED,
329 * Compute hash over the public key.
331 * @param key public key to hash
332 * @param hc where to store the hash code
335 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
336 struct GNUNET_HashCode *hc)
341 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
343 GNUNET_CRYPTO_hash (buf,
351 * Decode the public key from the data-format back
352 * to the "normal", internal format.
354 * @param buf the buffer where the public key data is stored
355 * @param len the length of the data in @a buf
356 * @return NULL on error
358 struct GNUNET_CRYPTO_RsaPublicKey *
359 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
362 struct GNUNET_CRYPTO_RsaPublicKey *key;
366 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
368 gcry_sexp_new (&key->sexp,
377 /* verify that this is an RSA public key */
378 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
380 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
383 /* this is no public RSA key */
385 gcry_sexp_release (key->sexp);
389 gcry_mpi_release (n);
395 * Create a blinding key
397 * @param len length of the key in bits (i.e. 2048)
398 * @return the newly created blinding key
400 struct GNUNET_CRYPTO_rsa_BlindingKey *
401 GNUNET_CRYPTO_rsa_blinding_key_create (unsigned int len)
403 struct GNUNET_CRYPTO_rsa_BlindingKey *blind;
405 blind = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
406 blind->r = gcry_mpi_new (len);
407 gcry_mpi_randomize (blind->r,
415 * Compare the values of two blinding keys.
418 * @param b2 the other key
419 * @return 0 if the two are equal
422 GNUNET_CRYPTO_rsa_blinding_key_cmp (struct GNUNET_CRYPTO_rsa_BlindingKey *b1,
423 struct GNUNET_CRYPTO_rsa_BlindingKey *b2)
425 return gcry_mpi_cmp (b1->r,
431 * Compare the values of two signatures.
433 * @param s1 one signature
434 * @param s2 the other signature
435 * @return 0 if the two are equal
438 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
439 struct GNUNET_CRYPTO_RsaSignature *s2)
447 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
449 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
464 * Compare the values of two public keys.
466 * @param p1 one public key
467 * @param p2 the other public key
468 * @return 0 if the two are equal
471 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
472 struct GNUNET_CRYPTO_RsaPublicKey *p2)
480 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
482 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
497 * Compare the values of two private keys.
499 * @param p1 one private key
500 * @param p2 the other private key
501 * @return 0 if the two are equal
504 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
505 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
513 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
515 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
530 * Obtain the length of the RSA key in bits.
532 * @param key the public key to introspect
533 * @return length of the key in bits
536 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
542 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
545 /* this is no public RSA key */
549 rval = gcry_mpi_get_nbits (n);
550 gcry_mpi_release (n);
556 * Destroy a blinding key
558 * @param bkey the blinding key to destroy
561 GNUNET_CRYPTO_rsa_blinding_key_free (struct GNUNET_CRYPTO_rsa_BlindingKey *bkey)
563 gcry_mpi_release (bkey->r);
569 * Print an MPI to a newly created buffer
571 * @param v MPI to print.
572 * @param[out] newly allocated buffer containing the result
573 * @return number of bytes stored in @a buffer
576 numeric_mpi_alloc_n_print (gcry_mpi_t v,
583 gcry_mpi_print (GCRYMPI_FMT_USG,
588 b = GNUNET_malloc (n);
590 gcry_mpi_print (GCRYMPI_FMT_USG,
601 * Encode the blinding key in a format suitable for
602 * storing it into a file.
604 * @param bkey the blinding key
605 * @param[out] buffer set to a buffer with the encoded key
606 * @return size of memory allocated in @a buffer
609 GNUNET_CRYPTO_rsa_blinding_key_encode (const struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
612 return numeric_mpi_alloc_n_print (bkey->r, buffer);
617 * Decode the blinding key from the data-format back
618 * to the "normal", internal format.
620 * @param buf the buffer where the public key data is stored
621 * @param len the length of the data in @a buf
622 * @return NULL on error
624 struct GNUNET_CRYPTO_rsa_BlindingKey *
625 GNUNET_CRYPTO_rsa_blinding_key_decode (const char *buf,
628 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
631 bkey = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
633 gcry_mpi_scan (&bkey->r,
635 (const unsigned char *) buf,
648 * Computes a full domain hash seeded by the given public key.
649 * This gives a measure of provable security to the Taler exchange
650 * against one-more forgery attacks. See:
651 * https://eprint.iacr.org/2001/002.pdf
652 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
654 * @param[out] r MPI value set to the FDH
655 * @param hash initial hash of the message to sign
656 * @param pkey the public key of the signer
657 * @param rsize If not NULL, the number of bytes actually stored in buffer
658 * @return libgcrypt error that to represent an allocation failure
661 rsa_full_domain_hash (gcry_mpi_t *r,
662 const struct GNUNET_HashCode *hash,
663 const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
668 unsigned int nhashes;
674 struct GNUNET_HashCode *hs;
676 /* Uncomment the following to debug without using the full domain hash */
678 rc = gcry_mpi_scan (r,
680 (const unsigned char *)hash,
681 sizeof(struct GNUNET_HashCode),
686 nbits = GNUNET_CRYPTO_rsa_public_key_len (pkey);
690 /* Already almost an HMAC since we consume a hash, so no GCRY_MD_FLAG_HMAC. */
691 rc = gcry_md_open (&h, GCRY_MD_SHA512, 0);
695 // We seed with the public denomination key as a homage to RSA-PSS by
696 // Mihir Bellare and Phillip Rogaway. Doing this lowers the degree
697 // of the hypothetical polyomial-time attack on RSA-KTI created by a
698 // polynomial-time one-more forgary attack. Yey seeding!
699 buf_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &buf);
700 gcry_md_write (h, buf, buf_len);
703 nhashes = (nbits-1) / (8 * sizeof(struct GNUNET_HashCode)) + 1;
704 hs = GNUNET_new_array (nhashes,
705 struct GNUNET_HashCode);
706 for (i=0; i<nhashes; i++)
708 gcry_md_write (h, hash, sizeof(struct GNUNET_HashCode));
709 rc = gcry_md_copy (&h0, h);
715 gcry_md_putc (h0, i % 256);
717 gcry_md_read (h0, GCRY_MD_SHA512),
718 sizeof(struct GNUNET_HashCode));
728 rc = gcry_mpi_scan (r,
730 (const unsigned char *) hs,
731 nhashes * sizeof(struct GNUNET_HashCode),
737 // Do not allow *r to exceed n or signatures fail to verify unpredictably.
738 // This happening with gcry_mpi_clear_highbit (*r, nbits-1) so maybe
739 // gcry_mpi_clear_highbit is broken, but setting the highbit sounds good.
740 gcry_mpi_set_highbit (*r, nbits-2);
746 * Blinds the given message with the given blinding key
748 * @param hash hash of the message to sign
749 * @param bkey the blinding key
750 * @param pkey the public key of the signer
751 * @param[out] buffer set to a buffer with the blinded message to be signed
752 * @return number of bytes stored in @a buffer
755 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
756 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
757 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
769 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
771 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
779 rc = rsa_full_domain_hash (&data, hash, pkey, &rsize);
780 if (0 != rc) // Allocation error in libgcrypt
783 gcry_mpi_release (ne[0]);
784 gcry_mpi_release (ne[1]);
788 r_e = gcry_mpi_new (0);
793 data_r_e = gcry_mpi_new (0);
794 gcry_mpi_mulm (data_r_e,
798 gcry_mpi_release (data);
799 gcry_mpi_release (ne[0]);
800 gcry_mpi_release (ne[1]);
801 gcry_mpi_release (r_e);
803 n = numeric_mpi_alloc_n_print (data_r_e, buffer);
804 gcry_mpi_release (data_r_e);
810 * Convert an MPI to an S-expression suitable for signature operations.
812 * @param value pointer to the data to convert
813 * @return converted s-expression
816 mpi_to_sexp (gcry_mpi_t value)
818 gcry_sexp_t data = NULL;
821 gcry_sexp_build (&data,
823 "(data (flags raw) (value %M))",
830 * Sign the given MPI.
832 * @param key private key to use for the signing
833 * @param value the MPI to sign
834 * @return NULL on error, signature on success
836 static struct GNUNET_CRYPTO_RsaSignature *
837 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
840 struct GNUNET_CRYPTO_RsaSignature *sig;
841 struct GNUNET_CRYPTO_RsaPublicKey *public_key;
845 data = mpi_to_sexp (value);
848 gcry_pk_sign (&result,
856 /* verify signature (guards against Lenstra's attack with fault injection...) */
857 public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
859 gcry_pk_verify (result,
864 GNUNET_CRYPTO_rsa_public_key_free (public_key);
865 gcry_sexp_release (data);
866 gcry_sexp_release (result);
869 GNUNET_CRYPTO_rsa_public_key_free (public_key);
871 /* return signature */
872 gcry_sexp_release (data);
873 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
880 * Sign a blinded value, which must be a full domain hash of a message.
882 * @param key private key to use for the signing
883 * @param msg the message to sign
884 * @param msg_len number of bytes in @a msg to sign
885 * @return NULL on error, signature on success
887 struct GNUNET_CRYPTO_RsaSignature *
888 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
893 struct GNUNET_CRYPTO_RsaSignature *sig;
902 sig = rsa_sign_mpi (key, v);
903 gcry_mpi_release (value);
909 * Create and sign a full domain hash of a message.
911 * @param key private key to use for the signing
912 * @param hash the hash of the message to sign
913 * @return NULL on error, signature on success
915 struct GNUNET_CRYPTO_RsaSignature *
916 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
917 const struct GNUNET_HashCode *hash)
919 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
922 struct GNUNET_CRYPTO_RsaSignature *sig;
924 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
925 rc = rsa_full_domain_hash (&v, hash, pkey, NULL);
926 GNUNET_CRYPTO_rsa_public_key_free (pkey);
927 GNUNET_assert (0 == rc);
929 sig = rsa_sign_mpi (key, v);
930 gcry_mpi_release (value);
937 * Free memory occupied by signature.
939 * @param sig memory to freee
942 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
944 gcry_sexp_release (sig->sexp);
950 * Encode the given signature in a format suitable for storing it into a file.
952 * @param sig the signature
953 * @param[out] buffer set to a buffer with the encoded key
954 * @return size of memory allocated in @a buffer
957 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
963 n = gcry_sexp_sprint (sig->sexp,
964 GCRYSEXP_FMT_ADVANCED,
967 b = GNUNET_malloc (n);
968 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
969 gcry_sexp_sprint (sig->sexp,
970 GCRYSEXP_FMT_ADVANCED,
979 * Decode the signature from the data-format back to the "normal", internal
982 * @param buf the buffer where the public key data is stored
983 * @param len the length of the data in @a buf
984 * @return NULL on error
986 struct GNUNET_CRYPTO_RsaSignature *
987 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
990 struct GNUNET_CRYPTO_RsaSignature *sig;
994 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
996 gcry_sexp_new (&sig->sexp,
1001 GNUNET_break_op (0);
1005 /* verify that this is an RSA signature */
1006 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1008 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1011 /* this is no RSA Signature */
1012 GNUNET_break_op (0);
1013 gcry_sexp_release (sig->sexp);
1017 gcry_mpi_release (s);
1023 * Duplicate the given public key
1025 * @param key the public key to duplicate
1026 * @return the duplicate key; NULL upon error
1028 struct GNUNET_CRYPTO_RsaPublicKey *
1029 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1031 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1032 gcry_sexp_t dup_sexp;
1035 /* check if we really are exporting a public key */
1036 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1037 GNUNET_assert (NULL != dup_sexp);
1038 gcry_sexp_release (dup_sexp);
1040 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1041 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1042 dup->sexp = dup_sexp;
1048 * Unblind a blind-signed signature. The signature should have been generated
1049 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1050 * #GNUNET_CRYPTO_rsa_blind().
1052 * @param sig the signature made on the blinded signature purpose
1053 * @param bkey the blinding key used to blind the signature purpose
1054 * @param pkey the public key of the signer
1055 * @return unblinded signature on success, NULL on error
1057 struct GNUNET_CRYPTO_RsaSignature *
1058 GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
1059 struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
1060 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1067 struct GNUNET_CRYPTO_RsaSignature *sret;
1069 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1071 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1074 GNUNET_break_op (0);
1077 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1079 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1082 gcry_mpi_release (n);
1083 GNUNET_break_op (0);
1086 r_inv = gcry_mpi_new (0);
1088 gcry_mpi_invm (r_inv,
1092 GNUNET_break_op (0);
1093 gcry_mpi_release (n);
1094 gcry_mpi_release (r_inv);
1095 gcry_mpi_release (s);
1098 ubsig = gcry_mpi_new (0);
1099 gcry_mpi_mulm (ubsig, s, r_inv, n);
1100 gcry_mpi_release (n);
1101 gcry_mpi_release (r_inv);
1102 gcry_mpi_release (s);
1104 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1106 gcry_sexp_build (&sret->sexp,
1108 "(sig-val (rsa (s %M)))",
1110 gcry_mpi_release (ubsig);
1116 * Verify whether the given hash corresponds to the given signature and the
1117 * signature is valid with respect to the given public key.
1119 * @param hash hash of the message to verify to match the @a sig
1120 * @param sig signature that is being validated
1121 * @param pkey public key of the signer
1122 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1125 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1126 const struct GNUNET_CRYPTO_RsaSignature *sig,
1127 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1133 rc = rsa_full_domain_hash (&r, hash, pkey, NULL);
1134 GNUNET_assert (0 == rc); // Allocation error in libgcrypt
1135 data = mpi_to_sexp(r);
1136 gcry_mpi_release (r);
1138 rc = gcry_pk_verify (sig->sexp,
1141 gcry_sexp_release (data);
1144 LOG (GNUNET_ERROR_TYPE_WARNING,
1145 _("RSA signature verification failed at %s:%d: %s\n"),
1148 gcry_strerror (rc));
1149 return GNUNET_SYSERR;
1156 * Duplicate the given private key
1158 * @param key the private key to duplicate
1159 * @return the duplicate key; NULL upon error
1161 struct GNUNET_CRYPTO_RsaPrivateKey *
1162 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1164 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1165 gcry_sexp_t dup_sexp;
1168 /* check if we really are exporting a private key */
1169 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1170 GNUNET_assert (NULL != dup_sexp);
1171 gcry_sexp_release (dup_sexp);
1173 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1174 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1175 dup->sexp = dup_sexp;
1181 * Duplicate the given private key
1183 * @param key the private key to duplicate
1184 * @return the duplicate key; NULL upon error
1186 struct GNUNET_CRYPTO_RsaSignature *
1187 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1189 struct GNUNET_CRYPTO_RsaSignature *dup;
1190 gcry_sexp_t dup_sexp;
1195 /* verify that this is an RSA signature */
1196 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1198 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1199 GNUNET_assert (0 == ret);
1200 gcry_mpi_release (s);
1202 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1203 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1204 dup->sexp = dup_sexp;
1209 /* end of util/rsa.c */