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,
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 * Test for malicious RSA key.
398 * Assuming n is an RSA modulous and r is generated using a call to
399 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
400 * malicious RSA key designed to deanomize the user.
402 * @param r KDF result
403 * @param n RSA modulus
404 * @return True if gcd(r,n) = 1, False means RSA key is malicious
407 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
412 g = gcry_mpi_new (0);
413 t = gcry_mpi_gcd(g,r,n);
414 gcry_mpi_release (g);
420 * Create a blinding key
422 * @param len length of the key in bits (i.e. 2048)
423 * @param bks pre-secret to use to derive the blinding key
424 * @return the newly created blinding key, NULL if RSA key is malicious
426 static struct RsaBlindingKey *
427 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
428 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
430 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
431 struct RsaBlindingKey *blind;
434 blind = GNUNET_new (struct RsaBlindingKey);
435 GNUNET_assert( NULL != blind );
437 /* Extract the composite n from the RSA public key */
438 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
439 /* Assert that it at least looks like an RSA key */
440 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
442 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
447 if (0 == rsa_gcd_validate(blind->r, n)) {
452 gcry_mpi_release (n);
458 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
461 There was previously a call to GNUNET_CRYPTO_kdf in
462 bkey = rsa_blinding_key_derive (len, bks);
463 that gives exactly len bits where
464 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
466 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
467 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
468 pkey.n making the effective bkey be
469 bkey mod pkey.n = bkey - pkey.n
470 so the effective bkey has its high bit set with probability r/2.
472 We expect r to be close to 1/2 if the exchange is honest, but the
473 exchange can choose r otherwise.
475 In blind signing, the exchange sees
476 B = bkey * S mod pkey.n
477 On deposit, the exchange sees S so they can compute bkey' = B/S mod
478 pkey.n for all B they recorded to see if bkey' has it's high bit set.
479 Also, note the exchange can compute 1/S efficiently since they know the
482 I suppose that happens with probability r/(1+r) if its the wrong B, not
483 completely sure. If otoh we've the right B, then we've the probability
484 r/2 of a set high bit in the effective bkey.
486 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
487 the wrong and right probabilities 1/3 and 1/4, respectively.
489 I feared this gives the exchange a meaningful fraction of a bit of
490 information per coin involved in the transaction. It sounds damaging if
491 numerous coins were involved. And it could run across transactions in
494 We fixed this by using a more uniform deterministic pseudo-random number
495 generator for blinding factors. I do not believe this to be a problem
496 for the rsa_full_domain_hash routine, but better safe than sorry.
501 * Compare the values of two signatures.
503 * @param s1 one signature
504 * @param s2 the other signature
505 * @return 0 if the two are equal
508 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
509 struct GNUNET_CRYPTO_RsaSignature *s2)
517 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
519 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
534 * Compare the values of two public keys.
536 * @param p1 one public key
537 * @param p2 the other public key
538 * @return 0 if the two are equal
541 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
542 struct GNUNET_CRYPTO_RsaPublicKey *p2)
550 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
552 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
567 * Compare the values of two private keys.
569 * @param p1 one private key
570 * @param p2 the other private key
571 * @return 0 if the two are equal
574 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
575 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
583 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
585 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
600 * Obtain the length of the RSA key in bits.
602 * @param key the public key to introspect
603 * @return length of the key in bits
606 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
611 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
612 { /* Not an RSA public key */
616 rval = gcry_mpi_get_nbits (n);
617 gcry_mpi_release (n);
623 * Destroy a blinding key
625 * @param bkey the blinding key to destroy
628 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
630 gcry_mpi_release (bkey->r);
636 * Print an MPI to a newly created buffer
638 * @param v MPI to print.
639 * @param[out] newly allocated buffer containing the result
640 * @return number of bytes stored in @a buffer
643 numeric_mpi_alloc_n_print (gcry_mpi_t v,
650 gcry_mpi_print (GCRYMPI_FMT_USG,
655 b = GNUNET_malloc (n);
657 gcry_mpi_print (GCRYMPI_FMT_USG,
668 * Computes a full domain hash seeded by the given public key.
669 * This gives a measure of provable security to the Taler exchange
670 * against one-more forgery attacks. See:
671 * https://eprint.iacr.org/2001/002.pdf
672 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
674 * @param hash initial hash of the message to sign
675 * @param pkey the public key of the signer
676 * @param rsize If not NULL, the number of bytes actually stored in buffer
677 * @return MPI value set to the FDH, NULL if RSA key is malicious
680 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
681 const struct GNUNET_HashCode *hash)
688 /* Extract the composite n from the RSA public key */
689 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
690 /* Assert that it at least looks like an RSA key */
691 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
693 /* We key with the public denomination key as a homage to RSA-PSS by *
694 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
695 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
696 * polynomial-time one-more forgary attack. Yey seeding! */
697 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
699 GNUNET_CRYPTO_kdf_mod_mpi (&r,
706 ok = rsa_gcd_validate(r,n);
707 gcry_mpi_release (n);
710 gcry_mpi_release (r);
716 * Blinds the given message with the given blinding key
718 * @param hash hash of the message to sign
719 * @param bkey the blinding key
720 * @param pkey the public key of the signer
721 * @param[out] buf set to a buffer with the blinded message to be signed
722 * @param[out] buf_size number of bytes stored in @a buf
723 * @return GNUNET_YES if successful, GNUNET_NO if RSA key is malicious
726 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
727 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
728 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
729 char **buf, size_t *buf_size)
731 struct RsaBlindingKey *bkey;
738 GNUNET_assert (buf != NULL && buf_size != NULL);
739 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
741 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
750 data = rsa_full_domain_hash (pkey, hash);
752 goto rsa_gcd_validate_failure;
754 bkey = rsa_blinding_key_derive (pkey, bks);
756 gcry_mpi_release (data);
757 goto rsa_gcd_validate_failure;
760 r_e = gcry_mpi_new (0);
765 data_r_e = gcry_mpi_new (0);
766 gcry_mpi_mulm (data_r_e,
770 gcry_mpi_release (data);
771 gcry_mpi_release (ne[0]);
772 gcry_mpi_release (ne[1]);
773 gcry_mpi_release (r_e);
774 rsa_blinding_key_free (bkey);
776 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
777 gcry_mpi_release (data_r_e);
780 rsa_gcd_validate_failure:
781 /* We know the RSA key is malicious here, so warn the wallet. */
782 /* GNUNET_break_op (0); */
783 gcry_mpi_release (ne[0]);
784 gcry_mpi_release (ne[1]);
792 * Convert an MPI to an S-expression suitable for signature operations.
794 * @param value pointer to the data to convert
795 * @return converted s-expression
798 mpi_to_sexp (gcry_mpi_t value)
800 gcry_sexp_t data = NULL;
803 gcry_sexp_build (&data,
805 "(data (flags raw) (value %M))",
812 * Sign the given MPI.
814 * @param key private key to use for the signing
815 * @param value the MPI to sign
816 * @return NULL on error, signature on success
818 static struct GNUNET_CRYPTO_RsaSignature *
819 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
822 struct GNUNET_CRYPTO_RsaSignature *sig;
827 data = mpi_to_sexp (value);
830 (rc = gcry_pk_sign (&result,
834 LOG (GNUNET_ERROR_TYPE_WARNING,
835 _("RSA signing failed at %s:%d: %s\n"),
843 /* Lenstra protection was first added to libgcrypt 1.6.4
844 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
846 #if GCRYPT_VERSION_NUMBER < 0x010604
847 /* verify signature (guards against Lenstra's attack with fault injection...) */
848 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
850 gcry_pk_verify (result,
855 GNUNET_CRYPTO_rsa_public_key_free (public_key);
856 gcry_sexp_release (data);
857 gcry_sexp_release (result);
860 GNUNET_CRYPTO_rsa_public_key_free (public_key);
863 /* return signature */
864 gcry_sexp_release (data);
865 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
872 * Sign a blinded value, which must be a full domain hash of a message.
874 * @param key private key to use for the signing
875 * @param msg the message to sign
876 * @param msg_len number of bytes in @a msg to sign
877 * @return NULL on error, signature on success
879 struct GNUNET_CRYPTO_RsaSignature *
880 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
885 struct GNUNET_CRYPTO_RsaSignature *sig;
894 sig = rsa_sign_mpi (key, v);
895 gcry_mpi_release (v);
901 * Create and sign a full domain hash of a message.
903 * @param key private key to use for the signing
904 * @param hash the hash of the message to sign
905 * @return NULL on error, including a malicious RSA key, signature on success
907 struct GNUNET_CRYPTO_RsaSignature *
908 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
909 const struct GNUNET_HashCode *hash)
911 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
913 struct GNUNET_CRYPTO_RsaSignature *sig;
915 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
916 v = rsa_full_domain_hash (pkey, hash);
917 GNUNET_CRYPTO_rsa_public_key_free (pkey);
918 if (NULL == v) /* rsa_gcd_validate failed meaning */
919 return NULL; /* our *own* RSA key is malicious. */
921 sig = rsa_sign_mpi (key, v);
922 gcry_mpi_release (v);
928 * Free memory occupied by signature.
930 * @param sig memory to freee
933 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
935 gcry_sexp_release (sig->sexp);
941 * Encode the given signature in a format suitable for storing it into a file.
943 * @param sig the signature
944 * @param[out] buffer set to a buffer with the encoded key
945 * @return size of memory allocated in @a buffer
948 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
954 n = gcry_sexp_sprint (sig->sexp,
955 GCRYSEXP_FMT_ADVANCED,
958 b = GNUNET_malloc (n);
959 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
960 gcry_sexp_sprint (sig->sexp,
961 GCRYSEXP_FMT_ADVANCED,
970 * Decode the signature from the data-format back to the "normal", internal
973 * @param buf the buffer where the public key data is stored
974 * @param len the length of the data in @a buf
975 * @return NULL on error
977 struct GNUNET_CRYPTO_RsaSignature *
978 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
981 struct GNUNET_CRYPTO_RsaSignature *sig;
985 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
987 gcry_sexp_new (&sig->sexp,
996 /* verify that this is an RSA signature */
997 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
999 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1002 /* this is no RSA Signature */
1003 GNUNET_break_op (0);
1004 gcry_sexp_release (sig->sexp);
1008 gcry_mpi_release (s);
1014 * Duplicate the given public key
1016 * @param key the public key to duplicate
1017 * @return the duplicate key; NULL upon error
1019 struct GNUNET_CRYPTO_RsaPublicKey *
1020 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1022 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1023 gcry_sexp_t dup_sexp;
1026 /* check if we really are exporting a public key */
1027 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1028 GNUNET_assert (NULL != dup_sexp);
1029 gcry_sexp_release (dup_sexp);
1031 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1032 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1033 dup->sexp = dup_sexp;
1039 * Unblind a blind-signed signature. The signature should have been generated
1040 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1041 * #GNUNET_CRYPTO_rsa_blind().
1043 * @param sig the signature made on the blinded signature purpose
1044 * @param bks the blinding key secret used to blind the signature purpose
1045 * @param pkey the public key of the signer
1046 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1048 struct GNUNET_CRYPTO_RsaSignature *
1049 GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_RsaSignature *sig,
1050 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1051 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1053 struct RsaBlindingKey *bkey;
1059 struct GNUNET_CRYPTO_RsaSignature *sret;
1061 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1063 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1066 GNUNET_break_op (0);
1069 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1071 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1074 gcry_mpi_release (n);
1075 GNUNET_break_op (0);
1079 bkey = rsa_blinding_key_derive (pkey, bks);
1082 /* RSA key is malicious since rsa_gcd_validate failed here.
1083 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1084 * so the exchange is being malicious in an unfamilair way, maybe
1085 * just trying to crash us. */
1086 GNUNET_break_op (0);
1087 gcry_mpi_release (n);
1088 gcry_mpi_release (s);
1092 r_inv = gcry_mpi_new (0);
1094 gcry_mpi_invm (r_inv,
1098 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1099 * caught above, but we handle it the same here. */
1100 GNUNET_break_op (0);
1101 gcry_mpi_release (r_inv);
1102 rsa_blinding_key_free (bkey);
1103 gcry_mpi_release (n);
1104 gcry_mpi_release (s);
1108 ubsig = gcry_mpi_new (0);
1109 gcry_mpi_mulm (ubsig, s, r_inv, n);
1110 gcry_mpi_release (n);
1111 gcry_mpi_release (r_inv);
1112 gcry_mpi_release (s);
1113 rsa_blinding_key_free (bkey);
1115 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1117 gcry_sexp_build (&sret->sexp,
1119 "(sig-val (rsa (s %M)))",
1121 gcry_mpi_release (ubsig);
1127 * Verify whether the given hash corresponds to the given signature and
1128 * the signature is valid with respect to the given public key.
1130 * @param hash hash of the message to verify to match the @a sig
1131 * @param sig signature that is being validated
1132 * @param pkey public key of the signer
1133 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1136 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1137 const struct GNUNET_CRYPTO_RsaSignature *sig,
1138 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1144 r = rsa_full_domain_hash (pkey, hash);
1146 GNUNET_break_op (0);
1147 /* RSA key is malicious since rsa_gcd_validate failed here.
1148 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1149 * so the exchange is being malicious in an unfamilair way, maybe
1150 * just trying to crash us. Arguably, we've only an internal error
1151 * though because we should've detected this in our previous call
1152 * to GNUNET_CRYPTO_rsa_unblind. */
1156 data = mpi_to_sexp(r);
1157 gcry_mpi_release (r);
1159 rc = gcry_pk_verify (sig->sexp,
1162 gcry_sexp_release (data);
1165 LOG (GNUNET_ERROR_TYPE_WARNING,
1166 _("RSA signature verification failed at %s:%d: %s\n"),
1169 gcry_strerror (rc));
1170 return GNUNET_SYSERR;
1177 * Duplicate the given private key
1179 * @param key the private key to duplicate
1180 * @return the duplicate key; NULL upon error
1182 struct GNUNET_CRYPTO_RsaPrivateKey *
1183 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1185 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1186 gcry_sexp_t dup_sexp;
1189 /* check if we really are exporting a private key */
1190 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1191 GNUNET_assert (NULL != dup_sexp);
1192 gcry_sexp_release (dup_sexp);
1194 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1195 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1196 dup->sexp = dup_sexp;
1202 * Duplicate the given private key
1204 * @param key the private key to duplicate
1205 * @return the duplicate key; NULL upon error
1207 struct GNUNET_CRYPTO_RsaSignature *
1208 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1210 struct GNUNET_CRYPTO_RsaSignature *dup;
1211 gcry_sexp_t dup_sexp;
1216 /* verify that this is an RSA signature */
1217 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1219 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1220 GNUNET_assert (0 == ret);
1221 gcry_mpi_release (s);
1223 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1224 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1225 dup->sexp = dup_sexp;
1230 /* end of util/rsa.c */