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;
411 blind = GNUNET_new (struct RsaBlindingKey);
413 /* Extract the composite n from the RSA public key */
414 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
415 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
417 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
423 /* If gcd(*r,n) != 1 then n must be a malicious fake RSA key
424 designed to deanomize the user. */
425 g = gcry_mpi_new (0);
426 GNUNET_assert( gcry_mpi_gcd(g,blind->r,n) );
427 gcry_mpi_release (g);
429 gcry_mpi_release (n);
435 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
438 There was previously a call to GNUNET_CRYPTO_kdf in
439 bkey = rsa_blinding_key_derive (len, bks);
440 that gives exactly len bits where
441 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
443 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
444 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
445 pkey.n making the effective bkey be
446 bkey mod pkey.n = bkey - pkey.n
447 so the effective bkey has its high bit set with probability r/2.
449 We expect r to be close to 1/2 if the exchange is honest, but the
450 exchange can choose r otherwise.
452 In blind signing, the exchange sees
453 B = bkey * S mod pkey.n
454 On deposit, the exchange sees S so they can compute bkey' = B/S mod
455 pkey.n for all B they recorded to see if bkey' has it's high bit set.
456 Also, note the exchange can compute 1/S efficiently since they know the
459 I suppose that happens with probability r/(1+r) if its the wrong B, not
460 completely sure. If otoh we've the right B, then we've the probability
461 r/2 of a set high bit in the effective bkey.
463 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
464 the wrong and right probabilities 1/3 and 1/4, respectively.
466 I feared this gives the exchange a meaningful fraction of a bit of
467 information per coin involved in the transaction. It sounds damaging if
468 numerous coins were involved. And it could run across transactions in
471 We fixed this by using a more uniform deterministic pseudo-random number
472 generator for blinding factors. I do not believe this to be a problem
473 for the rsa_full_domain_hash routine, but better safe than sorry.
478 * Compare the values of two signatures.
480 * @param s1 one signature
481 * @param s2 the other signature
482 * @return 0 if the two are equal
485 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
486 struct GNUNET_CRYPTO_RsaSignature *s2)
494 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
496 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
511 * Compare the values of two public keys.
513 * @param p1 one public key
514 * @param p2 the other public key
515 * @return 0 if the two are equal
518 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
519 struct GNUNET_CRYPTO_RsaPublicKey *p2)
527 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
529 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
544 * Compare the values of two private keys.
546 * @param p1 one private key
547 * @param p2 the other private key
548 * @return 0 if the two are equal
551 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
552 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
560 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
562 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
577 * Obtain the length of the RSA key in bits.
579 * @param key the public key to introspect
580 * @return length of the key in bits
583 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
588 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
589 { /* Not an RSA public key */
593 rval = gcry_mpi_get_nbits (n);
594 gcry_mpi_release (n);
600 * Destroy a blinding key
602 * @param bkey the blinding key to destroy
605 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
607 gcry_mpi_release (bkey->r);
613 * Print an MPI to a newly created buffer
615 * @param v MPI to print.
616 * @param[out] newly allocated buffer containing the result
617 * @return number of bytes stored in @a buffer
620 numeric_mpi_alloc_n_print (gcry_mpi_t v,
627 gcry_mpi_print (GCRYMPI_FMT_USG,
632 b = GNUNET_malloc (n);
634 gcry_mpi_print (GCRYMPI_FMT_USG,
645 * Computes a full domain hash seeded by the given public key.
646 * This gives a measure of provable security to the Taler exchange
647 * against one-more forgery attacks. See:
648 * https://eprint.iacr.org/2001/002.pdf
649 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
651 * @param[out] r MPI value set to the FDH
652 * @param hash initial hash of the message to sign
653 * @param pkey the public key of the signer
654 * @param rsize If not NULL, the number of bytes actually stored in buffer
657 rsa_full_domain_hash (gcry_mpi_t *r,
658 const struct GNUNET_HashCode *hash,
659 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
666 /* Extract the composite n from the RSA public key */
667 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
668 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
670 /* We key with the public denomination key as a homage to RSA-PSS by *
671 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
672 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
673 * polynomial-time one-more forgary attack. Yey seeding! */
674 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
676 GNUNET_CRYPTO_kdf_mod_mpi (r,
684 /* If gcd(*r,n) != 1 then n must be a malicious fake RSA key
685 designed to deanomize the user. */
686 g = gcry_mpi_new (0);
687 GNUNET_assert( gcry_mpi_gcd(g,*r,n) );
688 gcry_mpi_release (g);
690 gcry_mpi_release (n);
695 * Blinds the given message with the given blinding key
697 * @param hash hash of the message to sign
698 * @param bkey the blinding key
699 * @param pkey the public key of the signer
700 * @param[out] buffer set to a buffer with the blinded message to be signed
701 * @return number of bytes stored in @a buffer
704 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
705 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
706 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
709 struct RsaBlindingKey *bkey;
717 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
719 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
727 rsa_full_domain_hash (&data, hash, pkey);
728 bkey = rsa_blinding_key_derive (pkey,
730 r_e = gcry_mpi_new (0);
735 data_r_e = gcry_mpi_new (0);
736 gcry_mpi_mulm (data_r_e,
740 gcry_mpi_release (data);
741 gcry_mpi_release (ne[0]);
742 gcry_mpi_release (ne[1]);
743 gcry_mpi_release (r_e);
744 rsa_blinding_key_free (bkey);
746 n = numeric_mpi_alloc_n_print (data_r_e, buffer);
747 gcry_mpi_release (data_r_e);
753 * Convert an MPI to an S-expression suitable for signature operations.
755 * @param value pointer to the data to convert
756 * @return converted s-expression
759 mpi_to_sexp (gcry_mpi_t value)
761 gcry_sexp_t data = NULL;
764 gcry_sexp_build (&data,
766 "(data (flags raw) (value %M))",
773 * Sign the given MPI.
775 * @param key private key to use for the signing
776 * @param value the MPI to sign
777 * @return NULL on error, signature on success
779 static struct GNUNET_CRYPTO_RsaSignature *
780 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
783 struct GNUNET_CRYPTO_RsaSignature *sig;
784 struct GNUNET_CRYPTO_RsaPublicKey *public_key;
789 data = mpi_to_sexp (value);
792 (rc = gcry_pk_sign (&result,
796 LOG (GNUNET_ERROR_TYPE_WARNING,
797 _("RSA signing failed at %s:%d: %s\n"),
805 /* verify signature (guards against Lenstra's attack with fault injection...) */
806 public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
808 gcry_pk_verify (result,
813 GNUNET_CRYPTO_rsa_public_key_free (public_key);
814 gcry_sexp_release (data);
815 gcry_sexp_release (result);
818 GNUNET_CRYPTO_rsa_public_key_free (public_key);
820 /* return signature */
821 gcry_sexp_release (data);
822 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
829 * Sign a blinded value, which must be a full domain hash of a message.
831 * @param key private key to use for the signing
832 * @param msg the message to sign
833 * @param msg_len number of bytes in @a msg to sign
834 * @return NULL on error, signature on success
836 struct GNUNET_CRYPTO_RsaSignature *
837 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
842 struct GNUNET_CRYPTO_RsaSignature *sig;
851 sig = rsa_sign_mpi (key, v);
852 gcry_mpi_release (v);
858 * Create and sign a full domain hash of a message.
860 * @param key private key to use for the signing
861 * @param hash the hash of the message to sign
862 * @return NULL on error, signature on success
864 struct GNUNET_CRYPTO_RsaSignature *
865 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
866 const struct GNUNET_HashCode *hash)
868 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
870 struct GNUNET_CRYPTO_RsaSignature *sig;
872 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
873 rsa_full_domain_hash (&v, hash, pkey);
874 GNUNET_CRYPTO_rsa_public_key_free (pkey);
876 sig = rsa_sign_mpi (key, v);
877 gcry_mpi_release (v);
884 * Free memory occupied by signature.
886 * @param sig memory to freee
889 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
891 gcry_sexp_release (sig->sexp);
897 * Encode the given signature in a format suitable for storing it into a file.
899 * @param sig the signature
900 * @param[out] buffer set to a buffer with the encoded key
901 * @return size of memory allocated in @a buffer
904 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
910 n = gcry_sexp_sprint (sig->sexp,
911 GCRYSEXP_FMT_ADVANCED,
914 b = GNUNET_malloc (n);
915 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
916 gcry_sexp_sprint (sig->sexp,
917 GCRYSEXP_FMT_ADVANCED,
926 * Decode the signature from the data-format back to the "normal", internal
929 * @param buf the buffer where the public key data is stored
930 * @param len the length of the data in @a buf
931 * @return NULL on error
933 struct GNUNET_CRYPTO_RsaSignature *
934 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
937 struct GNUNET_CRYPTO_RsaSignature *sig;
941 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
943 gcry_sexp_new (&sig->sexp,
952 /* verify that this is an RSA signature */
953 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
955 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
958 /* this is no RSA Signature */
960 gcry_sexp_release (sig->sexp);
964 gcry_mpi_release (s);
970 * Duplicate the given public key
972 * @param key the public key to duplicate
973 * @return the duplicate key; NULL upon error
975 struct GNUNET_CRYPTO_RsaPublicKey *
976 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
978 struct GNUNET_CRYPTO_RsaPublicKey *dup;
979 gcry_sexp_t dup_sexp;
982 /* check if we really are exporting a public key */
983 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
984 GNUNET_assert (NULL != dup_sexp);
985 gcry_sexp_release (dup_sexp);
987 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
988 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
989 dup->sexp = dup_sexp;
995 * Unblind a blind-signed signature. The signature should have been generated
996 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
997 * #GNUNET_CRYPTO_rsa_blind().
999 * @param sig the signature made on the blinded signature purpose
1000 * @param bks the blinding key secret used to blind the signature purpose
1001 * @param pkey the public key of the signer
1002 * @return unblinded signature on success, NULL on error
1004 struct GNUNET_CRYPTO_RsaSignature *
1005 GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
1006 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1007 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1009 struct RsaBlindingKey *bkey;
1015 struct GNUNET_CRYPTO_RsaSignature *sret;
1017 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1019 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1022 GNUNET_break_op (0);
1025 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1027 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1030 gcry_mpi_release (n);
1031 GNUNET_break_op (0);
1034 bkey = rsa_blinding_key_derive (pkey,
1037 r_inv = gcry_mpi_new (0);
1039 gcry_mpi_invm (r_inv,
1043 GNUNET_break_op (0);
1044 gcry_mpi_release (n);
1045 gcry_mpi_release (r_inv);
1046 gcry_mpi_release (s);
1047 rsa_blinding_key_free (bkey);
1050 ubsig = gcry_mpi_new (0);
1051 gcry_mpi_mulm (ubsig, s, r_inv, n);
1052 gcry_mpi_release (n);
1053 gcry_mpi_release (r_inv);
1054 gcry_mpi_release (s);
1055 rsa_blinding_key_free (bkey);
1057 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1059 gcry_sexp_build (&sret->sexp,
1061 "(sig-val (rsa (s %M)))",
1063 gcry_mpi_release (ubsig);
1069 * Verify whether the given hash corresponds to the given signature and the
1070 * signature is valid with respect to the given public key.
1072 * @param hash hash of the message to verify to match the @a sig
1073 * @param sig signature that is being validated
1074 * @param pkey public key of the signer
1075 * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
1078 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1079 const struct GNUNET_CRYPTO_RsaSignature *sig,
1080 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1086 rsa_full_domain_hash (&r, hash, pkey);
1087 data = mpi_to_sexp(r);
1088 gcry_mpi_release (r);
1090 rc = gcry_pk_verify (sig->sexp,
1093 gcry_sexp_release (data);
1096 LOG (GNUNET_ERROR_TYPE_WARNING,
1097 _("RSA signature verification failed at %s:%d: %s\n"),
1100 gcry_strerror (rc));
1101 return GNUNET_SYSERR;
1108 * Duplicate the given private key
1110 * @param key the private key to duplicate
1111 * @return the duplicate key; NULL upon error
1113 struct GNUNET_CRYPTO_RsaPrivateKey *
1114 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1116 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1117 gcry_sexp_t dup_sexp;
1120 /* check if we really are exporting a private key */
1121 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1122 GNUNET_assert (NULL != dup_sexp);
1123 gcry_sexp_release (dup_sexp);
1125 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1126 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1127 dup->sexp = dup_sexp;
1133 * Duplicate the given private key
1135 * @param key the private key to duplicate
1136 * @return the duplicate key; NULL upon error
1138 struct GNUNET_CRYPTO_RsaSignature *
1139 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1141 struct GNUNET_CRYPTO_RsaSignature *dup;
1142 gcry_sexp_t dup_sexp;
1147 /* verify that this is an RSA signature */
1148 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1150 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1151 GNUNET_assert (0 == ret);
1152 gcry_mpi_release (s);
1154 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1155 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1156 dup->sexp = dup_sexp;
1161 /* end of util/rsa.c */