2 This file is part of GNUnet
3 Copyright (C) 2014,2016 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
22 * @author Jeffrey Burdges <burdges@gnunet.org>
26 #include "gnunet_crypto_lib.h"
28 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 * The private information of an RSA key pair.
34 struct GNUNET_CRYPTO_RsaPrivateKey
37 * Libgcrypt S-expression for the RSA private key.
44 * The public information of an RSA key pair.
46 struct GNUNET_CRYPTO_RsaPublicKey
49 * Libgcrypt S-expression for the RSA public key.
56 * @brief an RSA signature
58 struct GNUNET_CRYPTO_RsaSignature
61 * Libgcrypt S-expression for the RSA signature.
68 * @brief RSA blinding key
73 * Random value used for blinding.
80 * Extract values from an S-expression.
82 * @param array where to store the result(s)
83 * @param sexp S-expression to parse
84 * @param topname top-level name in the S-expression that is of interest
85 * @param elems names of the elements to extract
86 * @return 0 on success
89 key_from_sexp (gcry_mpi_t *array,
100 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
102 l2 = gcry_sexp_cadr (list);
103 gcry_sexp_release (list);
108 for (s = elems; *s; s++, idx++)
110 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
112 for (i = 0; i < idx; i++)
114 gcry_free (array[i]);
117 gcry_sexp_release (list);
118 return 3; /* required parameter not found */
120 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
121 gcry_sexp_release (l2);
124 for (i = 0; i < idx; i++)
126 gcry_free (array[i]);
129 gcry_sexp_release (list);
130 return 4; /* required parameter is invalid */
133 gcry_sexp_release (list);
139 * Create a new private key. Caller must free return value.
141 * @param len length of the key in bits (i.e. 2048)
142 * @return fresh private key
144 struct GNUNET_CRYPTO_RsaPrivateKey *
145 GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
147 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
149 gcry_sexp_t s_keyparam;
152 gcry_sexp_build (&s_keyparam,
154 "(genkey(rsa(nbits %d)))",
157 gcry_pk_genkey (&s_key,
159 gcry_sexp_release (s_keyparam);
162 gcry_pk_testkey (s_key));
164 ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
171 * Free memory occupied by the private key.
173 * @param key pointer to the memory to free
176 GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
178 gcry_sexp_release (key->sexp);
184 * Encode the private key in a format suitable for
185 * storing it into a file.
187 * @param key the private key
188 * @param[out] buffer set to a buffer with the encoded key
189 * @return size of memory allocated in @a buffer
192 GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
198 n = gcry_sexp_sprint (key->sexp,
199 GCRYSEXP_FMT_DEFAULT,
202 b = GNUNET_malloc (n);
203 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
204 gcry_sexp_sprint (key->sexp,
205 GCRYSEXP_FMT_DEFAULT,
214 * Decode the private key from the data-format back
215 * to the "normal", internal format.
217 * @param buf the buffer where the private key data is stored
218 * @param len the length of the data in @a buf
219 * @return NULL on error
221 struct GNUNET_CRYPTO_RsaPrivateKey *
222 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
225 struct GNUNET_CRYPTO_RsaPrivateKey *key;
226 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
228 gcry_sexp_new (&key->sexp,
233 LOG (GNUNET_ERROR_TYPE_WARNING,
234 "Decoded private key is not valid\n");
238 if (0 != gcry_pk_testkey (key->sexp))
240 LOG (GNUNET_ERROR_TYPE_WARNING,
241 "Decoded private key is not valid\n");
242 GNUNET_CRYPTO_rsa_private_key_free (key);
250 * Extract the public key of the given private key.
252 * @param priv the private key
253 * @retur NULL on error, otherwise the public key
255 struct GNUNET_CRYPTO_RsaPublicKey *
256 GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
258 struct GNUNET_CRYPTO_RsaPublicKey *pub;
263 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
265 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
267 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
273 rc = gcry_sexp_build (&result,
275 "(public-key(rsa(n %m)(e %m)))",
278 gcry_mpi_release (ne[0]);
279 gcry_mpi_release (ne[1]);
280 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
287 * Free memory occupied by the public key.
289 * @param key pointer to the memory to free
292 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
294 gcry_sexp_release (key->sexp);
300 * Encode the public key in a format suitable for
301 * storing it into a file.
303 * @param key the private key
304 * @param[out] buffer set to a buffer with the encoded key
305 * @return size of memory allocated in @a buffer
308 GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key,
314 n = gcry_sexp_sprint (key->sexp,
315 GCRYSEXP_FMT_ADVANCED,
318 b = GNUNET_malloc (n);
319 GNUNET_assert ((n -1) == /* since the last byte is \0 */
320 gcry_sexp_sprint (key->sexp,
321 GCRYSEXP_FMT_ADVANCED,
330 * Compute hash over the public key.
332 * @param key public key to hash
333 * @param hc where to store the hash code
336 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
337 struct GNUNET_HashCode *hc)
342 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
344 GNUNET_CRYPTO_hash (buf,
352 * Decode the public key from the data-format back
353 * to the "normal", internal format.
355 * @param buf the buffer where the public key data is stored
356 * @param len the length of the data in @a buf
357 * @return NULL on error
359 struct GNUNET_CRYPTO_RsaPublicKey *
360 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
363 struct GNUNET_CRYPTO_RsaPublicKey *key;
367 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
369 gcry_sexp_new (&key->sexp,
378 /* verify that this is an RSA public key */
379 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
381 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
384 /* this is no public RSA key */
386 gcry_sexp_release (key->sexp);
390 gcry_mpi_release (n);
396 * Create a blinding key
398 * @param len length of the key in bits (i.e. 2048)
399 * @param bks pre-secret to use to derive the blinding key
400 * @return the newly created blinding key
402 static struct RsaBlindingKey *
403 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
404 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
406 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
407 struct RsaBlindingKey *blind;
410 blind = GNUNET_new (struct RsaBlindingKey);
412 /* Extract the composite n from the RSA public key */
413 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
414 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
416 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
426 * Compare the values of two signatures.
428 * @param s1 one signature
429 * @param s2 the other signature
430 * @return 0 if the two are equal
433 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
434 struct GNUNET_CRYPTO_RsaSignature *s2)
442 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
444 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
459 * Compare the values of two public keys.
461 * @param p1 one public key
462 * @param p2 the other public key
463 * @return 0 if the two are equal
466 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
467 struct GNUNET_CRYPTO_RsaPublicKey *p2)
475 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
477 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
492 * Compare the values of two private keys.
494 * @param p1 one private key
495 * @param p2 the other private key
496 * @return 0 if the two are equal
499 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
500 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
508 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
510 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
525 * Obtain the length of the RSA key in bits.
527 * @param key the public key to introspect
528 * @return length of the key in bits
531 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
536 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
537 { /* Not an RSA public key */
541 rval = gcry_mpi_get_nbits (n);
542 gcry_mpi_release (n);
548 * Destroy a blinding key
550 * @param bkey the blinding key to destroy
553 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
555 gcry_mpi_release (bkey->r);
561 * Print an MPI to a newly created buffer
563 * @param v MPI to print.
564 * @param[out] newly allocated buffer containing the result
565 * @return number of bytes stored in @a buffer
568 numeric_mpi_alloc_n_print (gcry_mpi_t v,
575 gcry_mpi_print (GCRYMPI_FMT_USG,
580 b = GNUNET_malloc (n);
582 gcry_mpi_print (GCRYMPI_FMT_USG,
593 * Computes a full domain hash seeded by the given public key.
594 * This gives a measure of provable security to the Taler exchange
595 * against one-more forgery attacks. See:
596 * https://eprint.iacr.org/2001/002.pdf
597 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
599 * @param[out] r MPI value set to the FDH
600 * @param hash initial hash of the message to sign
601 * @param pkey the public key of the signer
602 * @param rsize If not NULL, the number of bytes actually stored in buffer
605 rsa_full_domain_hash (gcry_mpi_t *r,
606 const struct GNUNET_HashCode *hash,
607 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
613 /* Extract the composite n from the RSA public key */
614 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
615 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
617 /* We key with the public denomination key as a homage to RSA-PSS by *
618 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
619 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
620 * polynomial-time one-more forgary attack. Yey seeding! */
621 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
623 GNUNET_CRYPTO_kdf_mod_mpi (r,
634 * Blinds the given message with the given blinding key
636 * @param hash hash of the message to sign
637 * @param bkey the blinding key
638 * @param pkey the public key of the signer
639 * @param[out] buffer set to a buffer with the blinded message to be signed
640 * @return number of bytes stored in @a buffer
643 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
644 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
645 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
648 struct RsaBlindingKey *bkey;
656 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
658 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
666 rsa_full_domain_hash (&data, hash, pkey);
667 bkey = rsa_blinding_key_derive (pkey,
669 r_e = gcry_mpi_new (0);
674 data_r_e = gcry_mpi_new (0);
675 gcry_mpi_mulm (data_r_e,
679 gcry_mpi_release (data);
680 gcry_mpi_release (ne[0]);
681 gcry_mpi_release (ne[1]);
682 gcry_mpi_release (r_e);
683 rsa_blinding_key_free (bkey);
685 n = numeric_mpi_alloc_n_print (data_r_e, buffer);
686 gcry_mpi_release (data_r_e);
692 * Convert an MPI to an S-expression suitable for signature operations.
694 * @param value pointer to the data to convert
695 * @return converted s-expression
698 mpi_to_sexp (gcry_mpi_t value)
700 gcry_sexp_t data = NULL;
703 gcry_sexp_build (&data,
705 "(data (flags raw) (value %M))",
712 * Sign the given MPI.
714 * @param key private key to use for the signing
715 * @param value the MPI to sign
716 * @return NULL on error, signature on success
718 static struct GNUNET_CRYPTO_RsaSignature *
719 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
722 struct GNUNET_CRYPTO_RsaSignature *sig;
723 struct GNUNET_CRYPTO_RsaPublicKey *public_key;
728 data = mpi_to_sexp (value);
731 (rc = gcry_pk_sign (&result,
735 LOG (GNUNET_ERROR_TYPE_WARNING,
736 _("RSA signing failed at %s:%d: %s\n"),
744 /* verify signature (guards against Lenstra's attack with fault injection...) */
745 public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
747 gcry_pk_verify (result,
752 GNUNET_CRYPTO_rsa_public_key_free (public_key);
753 gcry_sexp_release (data);
754 gcry_sexp_release (result);
757 GNUNET_CRYPTO_rsa_public_key_free (public_key);
759 /* return signature */
760 gcry_sexp_release (data);
761 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
768 * Sign a blinded value, which must be a full domain hash of a message.
770 * @param key private key to use for the signing
771 * @param msg the message to sign
772 * @param msg_len number of bytes in @a msg to sign
773 * @return NULL on error, signature on success
775 struct GNUNET_CRYPTO_RsaSignature *
776 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
781 struct GNUNET_CRYPTO_RsaSignature *sig;
790 sig = rsa_sign_mpi (key, v);
791 gcry_mpi_release (v);
797 * Create and sign a full domain hash of a message.
799 * @param key private key to use for the signing
800 * @param hash the hash of the message to sign
801 * @return NULL on error, signature on success
803 struct GNUNET_CRYPTO_RsaSignature *
804 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
805 const struct GNUNET_HashCode *hash)
807 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
809 struct GNUNET_CRYPTO_RsaSignature *sig;
811 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
812 rsa_full_domain_hash (&v, hash, pkey);
813 GNUNET_CRYPTO_rsa_public_key_free (pkey);
815 sig = rsa_sign_mpi (key, v);
816 gcry_mpi_release (v);
823 * Free memory occupied by signature.
825 * @param sig memory to freee
828 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
830 gcry_sexp_release (sig->sexp);
836 * Encode the given signature in a format suitable for storing it into a file.
838 * @param sig the signature
839 * @param[out] buffer set to a buffer with the encoded key
840 * @return size of memory allocated in @a buffer
843 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
849 n = gcry_sexp_sprint (sig->sexp,
850 GCRYSEXP_FMT_ADVANCED,
853 b = GNUNET_malloc (n);
854 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
855 gcry_sexp_sprint (sig->sexp,
856 GCRYSEXP_FMT_ADVANCED,
865 * Decode the signature from the data-format back to the "normal", internal
868 * @param buf the buffer where the public key data is stored
869 * @param len the length of the data in @a buf
870 * @return NULL on error
872 struct GNUNET_CRYPTO_RsaSignature *
873 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
876 struct GNUNET_CRYPTO_RsaSignature *sig;
880 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
882 gcry_sexp_new (&sig->sexp,
891 /* verify that this is an RSA signature */
892 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
894 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
897 /* this is no RSA Signature */
899 gcry_sexp_release (sig->sexp);
903 gcry_mpi_release (s);
909 * Duplicate the given public key
911 * @param key the public key to duplicate
912 * @return the duplicate key; NULL upon error
914 struct GNUNET_CRYPTO_RsaPublicKey *
915 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
917 struct GNUNET_CRYPTO_RsaPublicKey *dup;
918 gcry_sexp_t dup_sexp;
921 /* check if we really are exporting a public key */
922 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
923 GNUNET_assert (NULL != dup_sexp);
924 gcry_sexp_release (dup_sexp);
926 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
927 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
928 dup->sexp = dup_sexp;
934 * Unblind a blind-signed signature. The signature should have been generated
935 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
936 * #GNUNET_CRYPTO_rsa_blind().
938 * @param sig the signature made on the blinded signature purpose
939 * @param bks the blinding key secret used to blind the signature purpose
940 * @param pkey the public key of the signer
941 * @return unblinded signature on success, NULL on error
943 struct GNUNET_CRYPTO_RsaSignature *
944 GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
945 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
946 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
948 struct RsaBlindingKey *bkey;
954 struct GNUNET_CRYPTO_RsaSignature *sret;
956 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
958 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
964 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
966 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
969 gcry_mpi_release (n);
973 bkey = rsa_blinding_key_derive (pkey,
976 r_inv = gcry_mpi_new (0);
978 gcry_mpi_invm (r_inv,
983 gcry_mpi_release (n);
984 gcry_mpi_release (r_inv);
985 gcry_mpi_release (s);
986 rsa_blinding_key_free (bkey);
989 ubsig = gcry_mpi_new (0);
990 gcry_mpi_mulm (ubsig, s, r_inv, n);
991 gcry_mpi_release (n);
992 gcry_mpi_release (r_inv);
993 gcry_mpi_release (s);
994 rsa_blinding_key_free (bkey);
996 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
998 gcry_sexp_build (&sret->sexp,
1000 "(sig-val (rsa (s %M)))",
1002 gcry_mpi_release (ubsig);
1008 * Verify whether the given hash corresponds to the given signature and the
1009 * signature is valid with respect to the given public key.
1011 * @param hash hash of the message to verify to match the @a sig
1012 * @param sig signature that is being validated
1013 * @param pkey public key of the signer
1014 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1017 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1018 const struct GNUNET_CRYPTO_RsaSignature *sig,
1019 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1025 rsa_full_domain_hash (&r, hash, pkey);
1026 data = mpi_to_sexp(r);
1027 gcry_mpi_release (r);
1029 rc = gcry_pk_verify (sig->sexp,
1032 gcry_sexp_release (data);
1035 LOG (GNUNET_ERROR_TYPE_WARNING,
1036 _("RSA signature verification failed at %s:%d: %s\n"),
1039 gcry_strerror (rc));
1040 return GNUNET_SYSERR;
1047 * Duplicate the given private key
1049 * @param key the private key to duplicate
1050 * @return the duplicate key; NULL upon error
1052 struct GNUNET_CRYPTO_RsaPrivateKey *
1053 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1055 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1056 gcry_sexp_t dup_sexp;
1059 /* check if we really are exporting a private key */
1060 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1061 GNUNET_assert (NULL != dup_sexp);
1062 gcry_sexp_release (dup_sexp);
1064 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1065 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1066 dup->sexp = dup_sexp;
1072 * Duplicate the given private key
1074 * @param key the private key to duplicate
1075 * @return the duplicate key; NULL upon error
1077 struct GNUNET_CRYPTO_RsaSignature *
1078 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1080 struct GNUNET_CRYPTO_RsaSignature *dup;
1081 gcry_sexp_t dup_sexp;
1086 /* verify that this is an RSA signature */
1087 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1089 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1090 GNUNET_assert (0 == ret);
1091 gcry_mpi_release (s);
1093 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1094 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1095 dup->sexp = dup_sexp;
1100 /* end of util/rsa.c */