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
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
17 * @file util/crypto_rsa.c
18 * @brief Chaum-style Blind signatures based on RSA
19 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
20 * @author Christian Grothoff
21 * @author Jeffrey Burdges <burdges@gnunet.org>
25 #include "gnunet_crypto_lib.h"
27 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-rsa", __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
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,
98 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
100 l2 = gcry_sexp_cadr (list);
101 gcry_sexp_release (list);
106 for (s = elems; *s; s++, idx++)
108 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
110 for (unsigned int i = 0; i < idx; i++)
112 gcry_free (array[i]);
115 gcry_sexp_release (list);
116 return 3; /* required parameter not found */
118 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
119 gcry_sexp_release (l2);
122 for (unsigned int i = 0; i < idx; i++)
124 gcry_free (array[i]);
127 gcry_sexp_release (list);
128 return 4; /* required parameter is invalid */
131 gcry_sexp_release (list);
137 * Create a new private key. Caller must free return value.
139 * @param len length of the key in bits (i.e. 2048)
140 * @return fresh private key
142 struct GNUNET_CRYPTO_RsaPrivateKey *
143 GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
145 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
147 gcry_sexp_t s_keyparam;
150 gcry_sexp_build (&s_keyparam,
152 "(genkey(rsa(nbits %d)))",
155 gcry_pk_genkey (&s_key,
157 gcry_sexp_release (s_keyparam);
160 gcry_pk_testkey (s_key));
162 ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
169 * Free memory occupied by the private key.
171 * @param key pointer to the memory to free
174 GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
176 gcry_sexp_release (key->sexp);
182 * Encode the private key in a format suitable for
183 * storing it into a file.
185 * @param key the private key
186 * @param[out] buffer set to a buffer with the encoded key
187 * @return size of memory allocated in @a buffer
190 GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
196 n = gcry_sexp_sprint (key->sexp,
197 GCRYSEXP_FMT_DEFAULT,
200 b = GNUNET_malloc (n);
201 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
202 gcry_sexp_sprint (key->sexp,
203 GCRYSEXP_FMT_DEFAULT,
212 * Decode the private key from the data-format back
213 * to the "normal", internal format.
215 * @param buf the buffer where the private key data is stored
216 * @param len the length of the data in @a buf
217 * @return NULL on error
219 struct GNUNET_CRYPTO_RsaPrivateKey *
220 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
223 struct GNUNET_CRYPTO_RsaPrivateKey *key;
224 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
226 gcry_sexp_new (&key->sexp,
231 LOG (GNUNET_ERROR_TYPE_WARNING,
232 "Decoded private key is not valid\n");
236 if (0 != gcry_pk_testkey (key->sexp))
238 LOG (GNUNET_ERROR_TYPE_WARNING,
239 "Decoded private key is not valid\n");
240 GNUNET_CRYPTO_rsa_private_key_free (key);
248 * Extract the public key of the given private key.
250 * @param priv the private key
251 * @retur NULL on error, otherwise the public key
253 struct GNUNET_CRYPTO_RsaPublicKey *
254 GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
256 struct GNUNET_CRYPTO_RsaPublicKey *pub;
261 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
263 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
265 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
271 rc = gcry_sexp_build (&result,
273 "(public-key(rsa(n %m)(e %m)))",
276 gcry_mpi_release (ne[0]);
277 gcry_mpi_release (ne[1]);
278 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
285 * Free memory occupied by the public key.
287 * @param key pointer to the memory to free
290 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
292 gcry_sexp_release (key->sexp);
298 * Encode the public key in a format suitable for
299 * storing it into a file.
301 * @param key the private key
302 * @param[out] buffer set to a buffer with the encoded key
303 * @return size of memory allocated in @a buffer
306 GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key,
312 n = gcry_sexp_sprint (key->sexp,
313 GCRYSEXP_FMT_ADVANCED,
316 b = GNUNET_malloc (n);
317 GNUNET_assert ((n -1) == /* since the last byte is \0 */
318 gcry_sexp_sprint (key->sexp,
319 GCRYSEXP_FMT_ADVANCED,
328 * Compute hash over the public key.
330 * @param key public key to hash
331 * @param hc where to store the hash code
334 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
335 struct GNUNET_HashCode *hc)
340 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
342 GNUNET_CRYPTO_hash (buf,
350 * Decode the public key from the data-format back
351 * to the "normal", internal format.
353 * @param buf the buffer where the public key data is stored
354 * @param len the length of the data in @a buf
355 * @return NULL on error
357 struct GNUNET_CRYPTO_RsaPublicKey *
358 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
361 struct GNUNET_CRYPTO_RsaPublicKey *key;
365 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
367 gcry_sexp_new (&key->sexp,
376 /* verify that this is an RSA public key */
377 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
379 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
382 /* this is no public RSA key */
384 gcry_sexp_release (key->sexp);
388 gcry_mpi_release (n);
394 * Test for malicious RSA key.
396 * Assuming n is an RSA modulous and r is generated using a call to
397 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
398 * malicious RSA key designed to deanomize the user.
400 * @param r KDF result
401 * @param n RSA modulus
402 * @return True if gcd(r,n) = 1, False means RSA key is malicious
405 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
410 g = gcry_mpi_new (0);
411 t = gcry_mpi_gcd(g,r,n);
412 gcry_mpi_release (g);
418 * Create a blinding key
420 * @param len length of the key in bits (i.e. 2048)
421 * @param bks pre-secret to use to derive the blinding key
422 * @return the newly created blinding key, NULL if RSA key is malicious
424 static struct RsaBlindingKey *
425 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
426 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
428 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
429 struct RsaBlindingKey *blind;
432 blind = GNUNET_new (struct RsaBlindingKey);
433 GNUNET_assert( NULL != blind );
435 /* Extract the composite n from the RSA public key */
436 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
437 /* Assert that it at least looks like an RSA key */
438 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
440 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
445 if (0 == rsa_gcd_validate(blind->r, n)) {
450 gcry_mpi_release (n);
456 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
459 There was previously a call to GNUNET_CRYPTO_kdf in
460 bkey = rsa_blinding_key_derive (len, bks);
461 that gives exactly len bits where
462 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
464 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
465 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
466 pkey.n making the effective bkey be
467 bkey mod pkey.n = bkey - pkey.n
468 so the effective bkey has its high bit set with probability r/2.
470 We expect r to be close to 1/2 if the exchange is honest, but the
471 exchange can choose r otherwise.
473 In blind signing, the exchange sees
474 B = bkey * S mod pkey.n
475 On deposit, the exchange sees S so they can compute bkey' = B/S mod
476 pkey.n for all B they recorded to see if bkey' has it's high bit set.
477 Also, note the exchange can compute 1/S efficiently since they know the
480 I suppose that happens with probability r/(1+r) if its the wrong B, not
481 completely sure. If otoh we've the right B, then we've the probability
482 r/2 of a set high bit in the effective bkey.
484 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
485 the wrong and right probabilities 1/3 and 1/4, respectively.
487 I feared this gives the exchange a meaningful fraction of a bit of
488 information per coin involved in the transaction. It sounds damaging if
489 numerous coins were involved. And it could run across transactions in
492 We fixed this by using a more uniform deterministic pseudo-random number
493 generator for blinding factors. I do not believe this to be a problem
494 for the rsa_full_domain_hash routine, but better safe than sorry.
499 * Compare the values of two signatures.
501 * @param s1 one signature
502 * @param s2 the other signature
503 * @return 0 if the two are equal
506 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
507 struct GNUNET_CRYPTO_RsaSignature *s2)
515 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
517 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
532 * Compare the values of two public keys.
534 * @param p1 one public key
535 * @param p2 the other public key
536 * @return 0 if the two are equal
539 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
540 struct GNUNET_CRYPTO_RsaPublicKey *p2)
548 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
550 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
565 * Compare the values of two private keys.
567 * @param p1 one private key
568 * @param p2 the other private key
569 * @return 0 if the two are equal
572 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
573 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
581 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
583 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
598 * Obtain the length of the RSA key in bits.
600 * @param key the public key to introspect
601 * @return length of the key in bits
604 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
609 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
610 { /* Not an RSA public key */
614 rval = gcry_mpi_get_nbits (n);
615 gcry_mpi_release (n);
621 * Destroy a blinding key
623 * @param bkey the blinding key to destroy
626 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
628 gcry_mpi_release (bkey->r);
634 * Print an MPI to a newly created buffer
636 * @param v MPI to print.
637 * @param[out] newly allocated buffer containing the result
638 * @return number of bytes stored in @a buffer
641 numeric_mpi_alloc_n_print (gcry_mpi_t v,
648 gcry_mpi_print (GCRYMPI_FMT_USG,
653 b = GNUNET_malloc (n);
655 gcry_mpi_print (GCRYMPI_FMT_USG,
666 * Computes a full domain hash seeded by the given public key.
667 * This gives a measure of provable security to the Taler exchange
668 * against one-more forgery attacks. See:
669 * https://eprint.iacr.org/2001/002.pdf
670 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
672 * @param hash initial hash of the message to sign
673 * @param pkey the public key of the signer
674 * @param rsize If not NULL, the number of bytes actually stored in buffer
675 * @return MPI value set to the FDH, NULL if RSA key is malicious
678 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
679 const struct GNUNET_HashCode *hash)
686 /* Extract the composite n from the RSA public key */
687 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
688 /* Assert that it at least looks like an RSA key */
689 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
691 /* We key with the public denomination key as a homage to RSA-PSS by *
692 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
693 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
694 * polynomial-time one-more forgary attack. Yey seeding! */
695 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
697 GNUNET_CRYPTO_kdf_mod_mpi (&r,
704 ok = rsa_gcd_validate(r,n);
705 gcry_mpi_release (n);
708 gcry_mpi_release (r);
714 * Blinds the given message with the given blinding key
716 * @param hash hash of the message to sign
717 * @param bkey the blinding key
718 * @param pkey the public key of the signer
719 * @param[out] buf set to a buffer with the blinded message to be signed
720 * @param[out] buf_size number of bytes stored in @a buf
721 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
724 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
725 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
726 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
727 char **buf, size_t *buf_size)
729 struct RsaBlindingKey *bkey;
736 GNUNET_assert (buf != NULL && buf_size != NULL);
737 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
739 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
748 data = rsa_full_domain_hash (pkey, hash);
750 goto rsa_gcd_validate_failure;
752 bkey = rsa_blinding_key_derive (pkey, bks);
754 gcry_mpi_release (data);
755 goto rsa_gcd_validate_failure;
758 r_e = gcry_mpi_new (0);
763 data_r_e = gcry_mpi_new (0);
764 gcry_mpi_mulm (data_r_e,
768 gcry_mpi_release (data);
769 gcry_mpi_release (ne[0]);
770 gcry_mpi_release (ne[1]);
771 gcry_mpi_release (r_e);
772 rsa_blinding_key_free (bkey);
774 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
775 gcry_mpi_release (data_r_e);
778 rsa_gcd_validate_failure:
779 /* We know the RSA key is malicious here, so warn the wallet. */
780 /* GNUNET_break_op (0); */
781 gcry_mpi_release (ne[0]);
782 gcry_mpi_release (ne[1]);
790 * Convert an MPI to an S-expression suitable for signature operations.
792 * @param value pointer to the data to convert
793 * @return converted s-expression
796 mpi_to_sexp (gcry_mpi_t value)
798 gcry_sexp_t data = NULL;
801 gcry_sexp_build (&data,
803 "(data (flags raw) (value %M))",
810 * Sign the given MPI.
812 * @param key private key to use for the signing
813 * @param value the MPI to sign
814 * @return NULL on error, signature on success
816 static struct GNUNET_CRYPTO_RsaSignature *
817 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
820 struct GNUNET_CRYPTO_RsaSignature *sig;
825 data = mpi_to_sexp (value);
828 (rc = gcry_pk_sign (&result,
832 LOG (GNUNET_ERROR_TYPE_WARNING,
833 _("RSA signing failed at %s:%d: %s\n"),
841 /* Lenstra protection was first added to libgcrypt 1.6.4
842 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
844 #if GCRYPT_VERSION_NUMBER < 0x010604
845 /* verify signature (guards against Lenstra's attack with fault injection...) */
846 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
848 gcry_pk_verify (result,
853 GNUNET_CRYPTO_rsa_public_key_free (public_key);
854 gcry_sexp_release (data);
855 gcry_sexp_release (result);
858 GNUNET_CRYPTO_rsa_public_key_free (public_key);
861 /* return signature */
862 gcry_sexp_release (data);
863 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
870 * Sign a blinded value, which must be a full domain hash of a message.
872 * @param key private key to use for the signing
873 * @param msg the message to sign
874 * @param msg_len number of bytes in @a msg to sign
875 * @return NULL on error, signature on success
877 struct GNUNET_CRYPTO_RsaSignature *
878 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
883 struct GNUNET_CRYPTO_RsaSignature *sig;
892 sig = rsa_sign_mpi (key, v);
893 gcry_mpi_release (v);
899 * Create and sign a full domain hash of a message.
901 * @param key private key to use for the signing
902 * @param hash the hash of the message to sign
903 * @return NULL on error, including a malicious RSA key, signature on success
905 struct GNUNET_CRYPTO_RsaSignature *
906 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
907 const struct GNUNET_HashCode *hash)
909 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
911 struct GNUNET_CRYPTO_RsaSignature *sig;
913 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
914 v = rsa_full_domain_hash (pkey, hash);
915 GNUNET_CRYPTO_rsa_public_key_free (pkey);
916 if (NULL == v) /* rsa_gcd_validate failed meaning */
917 return NULL; /* our *own* RSA key is malicious. */
919 sig = rsa_sign_mpi (key, v);
920 gcry_mpi_release (v);
926 * Free memory occupied by signature.
928 * @param sig memory to freee
931 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
933 gcry_sexp_release (sig->sexp);
939 * Encode the given signature in a format suitable for storing it into a file.
941 * @param sig the signature
942 * @param[out] buffer set to a buffer with the encoded key
943 * @return size of memory allocated in @a buffer
946 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
952 n = gcry_sexp_sprint (sig->sexp,
953 GCRYSEXP_FMT_ADVANCED,
956 b = GNUNET_malloc (n);
957 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
958 gcry_sexp_sprint (sig->sexp,
959 GCRYSEXP_FMT_ADVANCED,
968 * Decode the signature from the data-format back to the "normal", internal
971 * @param buf the buffer where the public key data is stored
972 * @param len the length of the data in @a buf
973 * @return NULL on error
975 struct GNUNET_CRYPTO_RsaSignature *
976 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
979 struct GNUNET_CRYPTO_RsaSignature *sig;
983 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
985 gcry_sexp_new (&sig->sexp,
994 /* verify that this is an RSA signature */
995 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
997 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1000 /* this is no RSA Signature */
1001 GNUNET_break_op (0);
1002 gcry_sexp_release (sig->sexp);
1006 gcry_mpi_release (s);
1012 * Duplicate the given public key
1014 * @param key the public key to duplicate
1015 * @return the duplicate key; NULL upon error
1017 struct GNUNET_CRYPTO_RsaPublicKey *
1018 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1020 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1021 gcry_sexp_t dup_sexp;
1024 /* check if we really are exporting a public key */
1025 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1026 GNUNET_assert (NULL != dup_sexp);
1027 gcry_sexp_release (dup_sexp);
1029 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1030 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1031 dup->sexp = dup_sexp;
1037 * Unblind a blind-signed signature. The signature should have been generated
1038 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1039 * #GNUNET_CRYPTO_rsa_blind().
1041 * @param sig the signature made on the blinded signature purpose
1042 * @param bks the blinding key secret used to blind the signature purpose
1043 * @param pkey the public key of the signer
1044 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1046 struct GNUNET_CRYPTO_RsaSignature *
1047 GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
1048 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1049 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1051 struct RsaBlindingKey *bkey;
1057 struct GNUNET_CRYPTO_RsaSignature *sret;
1059 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1061 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1064 GNUNET_break_op (0);
1067 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1069 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1072 gcry_mpi_release (n);
1073 GNUNET_break_op (0);
1077 bkey = rsa_blinding_key_derive (pkey, bks);
1080 /* RSA key is malicious since rsa_gcd_validate failed here.
1081 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1082 * so the exchange is being malicious in an unfamilair way, maybe
1083 * just trying to crash us. */
1084 GNUNET_break_op (0);
1085 gcry_mpi_release (n);
1086 gcry_mpi_release (s);
1090 r_inv = gcry_mpi_new (0);
1092 gcry_mpi_invm (r_inv,
1096 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1097 * caught above, but we handle it the same here. */
1098 GNUNET_break_op (0);
1099 gcry_mpi_release (r_inv);
1100 rsa_blinding_key_free (bkey);
1101 gcry_mpi_release (n);
1102 gcry_mpi_release (s);
1106 ubsig = gcry_mpi_new (0);
1107 gcry_mpi_mulm (ubsig, s, r_inv, n);
1108 gcry_mpi_release (n);
1109 gcry_mpi_release (r_inv);
1110 gcry_mpi_release (s);
1111 rsa_blinding_key_free (bkey);
1113 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1115 gcry_sexp_build (&sret->sexp,
1117 "(sig-val (rsa (s %M)))",
1119 gcry_mpi_release (ubsig);
1125 * Verify whether the given hash corresponds to the given signature and
1126 * the signature is valid with respect to the given public key.
1128 * @param hash hash of the message to verify to match the @a sig
1129 * @param sig signature that is being validated
1130 * @param pkey public key of the signer
1131 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1134 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1135 const struct GNUNET_CRYPTO_RsaSignature *sig,
1136 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1142 r = rsa_full_domain_hash (pkey, hash);
1144 GNUNET_break_op (0);
1145 /* RSA key is malicious since rsa_gcd_validate failed here.
1146 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1147 * so the exchange is being malicious in an unfamilair way, maybe
1148 * just trying to crash us. Arguably, we've only an internal error
1149 * though because we should've detected this in our previous call
1150 * to GNUNET_CRYPTO_rsa_unblind. */
1154 data = mpi_to_sexp(r);
1155 gcry_mpi_release (r);
1157 rc = gcry_pk_verify (sig->sexp,
1160 gcry_sexp_release (data);
1163 LOG (GNUNET_ERROR_TYPE_WARNING,
1164 _("RSA signature verification failed at %s:%d: %s\n"),
1167 gcry_strerror (rc));
1168 return GNUNET_SYSERR;
1175 * Duplicate the given private key
1177 * @param key the private key to duplicate
1178 * @return the duplicate key; NULL upon error
1180 struct GNUNET_CRYPTO_RsaPrivateKey *
1181 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1183 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1184 gcry_sexp_t dup_sexp;
1187 /* check if we really are exporting a private key */
1188 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1189 GNUNET_assert (NULL != dup_sexp);
1190 gcry_sexp_release (dup_sexp);
1192 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1193 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1194 dup->sexp = dup_sexp;
1200 * Duplicate the given private key
1202 * @param key the private key to duplicate
1203 * @return the duplicate key; NULL upon error
1205 struct GNUNET_CRYPTO_RsaSignature *
1206 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1208 struct GNUNET_CRYPTO_RsaSignature *dup;
1209 gcry_sexp_t dup_sexp;
1214 /* verify that this is an RSA signature */
1215 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1217 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1218 GNUNET_assert (0 == ret);
1219 gcry_mpi_release (s);
1221 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1222 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1223 dup->sexp = dup_sexp;
1228 /* end of util/rsa.c */