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-crypto-rsa", __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,
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 (unsigned int 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 (unsigned int 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 * Test for malicious RSA key.
397 * Assuming n is an RSA modulous and r is generated using a call to
398 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
399 * malicious RSA key designed to deanomize the user.
401 * @param r KDF result
402 * @param n RSA modulus
403 * @return True if gcd(r,n) = 1, False means RSA key is malicious
406 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
411 g = gcry_mpi_new (0);
412 t = gcry_mpi_gcd(g,r,n);
413 gcry_mpi_release (g);
419 * Create a blinding key
421 * @param len length of the key in bits (i.e. 2048)
422 * @param bks pre-secret to use to derive the blinding key
423 * @return the newly created blinding key, NULL if RSA key is malicious
425 static struct RsaBlindingKey *
426 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
427 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
429 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
430 struct RsaBlindingKey *blind;
433 blind = GNUNET_new (struct RsaBlindingKey);
434 GNUNET_assert( NULL != blind );
436 /* Extract the composite n from the RSA public key */
437 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
438 /* Assert that it at least looks like an RSA key */
439 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
441 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
446 if (0 == rsa_gcd_validate(blind->r, n)) {
451 gcry_mpi_release (n);
457 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
460 There was previously a call to GNUNET_CRYPTO_kdf in
461 bkey = rsa_blinding_key_derive (len, bks);
462 that gives exactly len bits where
463 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
465 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
466 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
467 pkey.n making the effective bkey be
468 bkey mod pkey.n = bkey - pkey.n
469 so the effective bkey has its high bit set with probability r/2.
471 We expect r to be close to 1/2 if the exchange is honest, but the
472 exchange can choose r otherwise.
474 In blind signing, the exchange sees
475 B = bkey * S mod pkey.n
476 On deposit, the exchange sees S so they can compute bkey' = B/S mod
477 pkey.n for all B they recorded to see if bkey' has it's high bit set.
478 Also, note the exchange can compute 1/S efficiently since they know the
481 I suppose that happens with probability r/(1+r) if its the wrong B, not
482 completely sure. If otoh we've the right B, then we've the probability
483 r/2 of a set high bit in the effective bkey.
485 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
486 the wrong and right probabilities 1/3 and 1/4, respectively.
488 I feared this gives the exchange a meaningful fraction of a bit of
489 information per coin involved in the transaction. It sounds damaging if
490 numerous coins were involved. And it could run across transactions in
493 We fixed this by using a more uniform deterministic pseudo-random number
494 generator for blinding factors. I do not believe this to be a problem
495 for the rsa_full_domain_hash routine, but better safe than sorry.
500 * Compare the values of two signatures.
502 * @param s1 one signature
503 * @param s2 the other signature
504 * @return 0 if the two are equal
507 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
508 struct GNUNET_CRYPTO_RsaSignature *s2)
516 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
518 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
533 * Compare the values of two public keys.
535 * @param p1 one public key
536 * @param p2 the other public key
537 * @return 0 if the two are equal
540 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
541 struct GNUNET_CRYPTO_RsaPublicKey *p2)
549 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
551 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
566 * Compare the values of two private keys.
568 * @param p1 one private key
569 * @param p2 the other private key
570 * @return 0 if the two are equal
573 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
574 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
582 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
584 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
599 * Obtain the length of the RSA key in bits.
601 * @param key the public key to introspect
602 * @return length of the key in bits
605 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
610 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
611 { /* Not an RSA public key */
615 rval = gcry_mpi_get_nbits (n);
616 gcry_mpi_release (n);
622 * Destroy a blinding key
624 * @param bkey the blinding key to destroy
627 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
629 gcry_mpi_release (bkey->r);
635 * Print an MPI to a newly created buffer
637 * @param v MPI to print.
638 * @param[out] newly allocated buffer containing the result
639 * @return number of bytes stored in @a buffer
642 numeric_mpi_alloc_n_print (gcry_mpi_t v,
649 gcry_mpi_print (GCRYMPI_FMT_USG,
654 b = GNUNET_malloc (n);
656 gcry_mpi_print (GCRYMPI_FMT_USG,
667 * Computes a full domain hash seeded by the given public key.
668 * This gives a measure of provable security to the Taler exchange
669 * against one-more forgery attacks. See:
670 * https://eprint.iacr.org/2001/002.pdf
671 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
673 * @param hash initial hash of the message to sign
674 * @param pkey the public key of the signer
675 * @param rsize If not NULL, the number of bytes actually stored in buffer
676 * @return MPI value set to the FDH, NULL if RSA key is malicious
679 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
680 const struct GNUNET_HashCode *hash)
687 /* Extract the composite n from the RSA public key */
688 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
689 /* Assert that it at least looks like an RSA key */
690 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
692 /* We key with the public denomination key as a homage to RSA-PSS by *
693 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
694 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
695 * polynomial-time one-more forgary attack. Yey seeding! */
696 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
698 GNUNET_CRYPTO_kdf_mod_mpi (&r,
705 ok = rsa_gcd_validate(r,n);
706 gcry_mpi_release (n);
709 gcry_mpi_release (r);
715 * Blinds the given message with the given blinding key
717 * @param hash hash of the message to sign
718 * @param bkey the blinding key
719 * @param pkey the public key of the signer
720 * @param[out] buf set to a buffer with the blinded message to be signed
721 * @param[out] buf_size number of bytes stored in @a buf
722 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
725 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
726 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
727 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
728 char **buf, size_t *buf_size)
730 struct RsaBlindingKey *bkey;
737 GNUNET_assert (buf != NULL && buf_size != NULL);
738 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
740 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
749 data = rsa_full_domain_hash (pkey, hash);
751 goto rsa_gcd_validate_failure;
753 bkey = rsa_blinding_key_derive (pkey, bks);
755 gcry_mpi_release (data);
756 goto rsa_gcd_validate_failure;
759 r_e = gcry_mpi_new (0);
764 data_r_e = gcry_mpi_new (0);
765 gcry_mpi_mulm (data_r_e,
769 gcry_mpi_release (data);
770 gcry_mpi_release (ne[0]);
771 gcry_mpi_release (ne[1]);
772 gcry_mpi_release (r_e);
773 rsa_blinding_key_free (bkey);
775 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
776 gcry_mpi_release (data_r_e);
779 rsa_gcd_validate_failure:
780 /* We know the RSA key is malicious here, so warn the wallet. */
781 /* GNUNET_break_op (0); */
782 gcry_mpi_release (ne[0]);
783 gcry_mpi_release (ne[1]);
791 * Convert an MPI to an S-expression suitable for signature operations.
793 * @param value pointer to the data to convert
794 * @return converted s-expression
797 mpi_to_sexp (gcry_mpi_t value)
799 gcry_sexp_t data = NULL;
802 gcry_sexp_build (&data,
804 "(data (flags raw) (value %M))",
811 * Sign the given MPI.
813 * @param key private key to use for the signing
814 * @param value the MPI to sign
815 * @return NULL on error, signature on success
817 static struct GNUNET_CRYPTO_RsaSignature *
818 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
821 struct GNUNET_CRYPTO_RsaSignature *sig;
826 data = mpi_to_sexp (value);
829 (rc = gcry_pk_sign (&result,
833 LOG (GNUNET_ERROR_TYPE_WARNING,
834 _("RSA signing failed at %s:%d: %s\n"),
842 /* Lenstra protection was first added to libgcrypt 1.6.4
843 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
845 #if GCRYPT_VERSION_NUMBER < 0x010604
846 /* verify signature (guards against Lenstra's attack with fault injection...) */
847 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
849 gcry_pk_verify (result,
854 GNUNET_CRYPTO_rsa_public_key_free (public_key);
855 gcry_sexp_release (data);
856 gcry_sexp_release (result);
859 GNUNET_CRYPTO_rsa_public_key_free (public_key);
862 /* return signature */
863 gcry_sexp_release (data);
864 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
871 * Sign a blinded value, which must be a full domain hash of a message.
873 * @param key private key to use for the signing
874 * @param msg the message to sign
875 * @param msg_len number of bytes in @a msg to sign
876 * @return NULL on error, signature on success
878 struct GNUNET_CRYPTO_RsaSignature *
879 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
884 struct GNUNET_CRYPTO_RsaSignature *sig;
893 sig = rsa_sign_mpi (key, v);
894 gcry_mpi_release (v);
900 * Create and sign a full domain hash of a message.
902 * @param key private key to use for the signing
903 * @param hash the hash of the message to sign
904 * @return NULL on error, including a malicious RSA key, signature on success
906 struct GNUNET_CRYPTO_RsaSignature *
907 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
908 const struct GNUNET_HashCode *hash)
910 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
912 struct GNUNET_CRYPTO_RsaSignature *sig;
914 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
915 v = rsa_full_domain_hash (pkey, hash);
916 GNUNET_CRYPTO_rsa_public_key_free (pkey);
917 if (NULL == v) /* rsa_gcd_validate failed meaning */
918 return NULL; /* our *own* RSA key is malicious. */
920 sig = rsa_sign_mpi (key, v);
921 gcry_mpi_release (v);
927 * Free memory occupied by signature.
929 * @param sig memory to freee
932 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
934 gcry_sexp_release (sig->sexp);
940 * Encode the given signature in a format suitable for storing it into a file.
942 * @param sig the signature
943 * @param[out] buffer set to a buffer with the encoded key
944 * @return size of memory allocated in @a buffer
947 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
953 n = gcry_sexp_sprint (sig->sexp,
954 GCRYSEXP_FMT_ADVANCED,
957 b = GNUNET_malloc (n);
958 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
959 gcry_sexp_sprint (sig->sexp,
960 GCRYSEXP_FMT_ADVANCED,
969 * Decode the signature from the data-format back to the "normal", internal
972 * @param buf the buffer where the public key data is stored
973 * @param len the length of the data in @a buf
974 * @return NULL on error
976 struct GNUNET_CRYPTO_RsaSignature *
977 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
980 struct GNUNET_CRYPTO_RsaSignature *sig;
984 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
986 gcry_sexp_new (&sig->sexp,
995 /* verify that this is an RSA signature */
996 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
998 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1001 /* this is no RSA Signature */
1002 GNUNET_break_op (0);
1003 gcry_sexp_release (sig->sexp);
1007 gcry_mpi_release (s);
1013 * Duplicate the given public key
1015 * @param key the public key to duplicate
1016 * @return the duplicate key; NULL upon error
1018 struct GNUNET_CRYPTO_RsaPublicKey *
1019 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1021 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1022 gcry_sexp_t dup_sexp;
1025 /* check if we really are exporting a public key */
1026 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1027 GNUNET_assert (NULL != dup_sexp);
1028 gcry_sexp_release (dup_sexp);
1030 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1031 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1032 dup->sexp = dup_sexp;
1038 * Unblind a blind-signed signature. The signature should have been generated
1039 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1040 * #GNUNET_CRYPTO_rsa_blind().
1042 * @param sig the signature made on the blinded signature purpose
1043 * @param bks the blinding key secret used to blind the signature purpose
1044 * @param pkey the public key of the signer
1045 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1047 struct GNUNET_CRYPTO_RsaSignature *
1048 GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
1049 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1050 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1052 struct RsaBlindingKey *bkey;
1058 struct GNUNET_CRYPTO_RsaSignature *sret;
1060 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1062 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1065 GNUNET_break_op (0);
1068 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1070 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1073 gcry_mpi_release (n);
1074 GNUNET_break_op (0);
1078 bkey = rsa_blinding_key_derive (pkey, bks);
1081 /* RSA key is malicious since rsa_gcd_validate failed here.
1082 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1083 * so the exchange is being malicious in an unfamilair way, maybe
1084 * just trying to crash us. */
1085 GNUNET_break_op (0);
1086 gcry_mpi_release (n);
1087 gcry_mpi_release (s);
1091 r_inv = gcry_mpi_new (0);
1093 gcry_mpi_invm (r_inv,
1097 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1098 * caught above, but we handle it the same here. */
1099 GNUNET_break_op (0);
1100 gcry_mpi_release (r_inv);
1101 rsa_blinding_key_free (bkey);
1102 gcry_mpi_release (n);
1103 gcry_mpi_release (s);
1107 ubsig = gcry_mpi_new (0);
1108 gcry_mpi_mulm (ubsig, s, r_inv, n);
1109 gcry_mpi_release (n);
1110 gcry_mpi_release (r_inv);
1111 gcry_mpi_release (s);
1112 rsa_blinding_key_free (bkey);
1114 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1116 gcry_sexp_build (&sret->sexp,
1118 "(sig-val (rsa (s %M)))",
1120 gcry_mpi_release (ubsig);
1126 * Verify whether the given hash corresponds to the given signature and
1127 * the signature is valid with respect to the given public key.
1129 * @param hash hash of the message to verify to match the @a sig
1130 * @param sig signature that is being validated
1131 * @param pkey public key of the signer
1132 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1135 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1136 const struct GNUNET_CRYPTO_RsaSignature *sig,
1137 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1143 r = rsa_full_domain_hash (pkey, hash);
1145 GNUNET_break_op (0);
1146 /* RSA key is malicious since rsa_gcd_validate failed here.
1147 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1148 * so the exchange is being malicious in an unfamilair way, maybe
1149 * just trying to crash us. Arguably, we've only an internal error
1150 * though because we should've detected this in our previous call
1151 * to GNUNET_CRYPTO_rsa_unblind. */
1155 data = mpi_to_sexp(r);
1156 gcry_mpi_release (r);
1158 rc = gcry_pk_verify (sig->sexp,
1161 gcry_sexp_release (data);
1164 LOG (GNUNET_ERROR_TYPE_WARNING,
1165 _("RSA signature verification failed at %s:%d: %s\n"),
1168 gcry_strerror (rc));
1169 return GNUNET_SYSERR;
1176 * Duplicate the given private key
1178 * @param key the private key to duplicate
1179 * @return the duplicate key; NULL upon error
1181 struct GNUNET_CRYPTO_RsaPrivateKey *
1182 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1184 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1185 gcry_sexp_t dup_sexp;
1188 /* check if we really are exporting a private key */
1189 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1190 GNUNET_assert (NULL != dup_sexp);
1191 gcry_sexp_release (dup_sexp);
1193 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1194 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1195 dup->sexp = dup_sexp;
1201 * Duplicate the given private key
1203 * @param key the private key to duplicate
1204 * @return the duplicate key; NULL upon error
1206 struct GNUNET_CRYPTO_RsaSignature *
1207 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1209 struct GNUNET_CRYPTO_RsaSignature *dup;
1210 gcry_sexp_t dup_sexp;
1215 /* verify that this is an RSA signature */
1216 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1218 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1219 GNUNET_assert (0 == ret);
1220 gcry_mpi_release (s);
1222 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1223 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1224 dup->sexp = dup_sexp;
1229 /* end of util/rsa.c */