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.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file util/crypto_rsa.c
21 * @brief Chaum-style Blind signatures based on RSA
22 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
23 * @author Christian Grothoff
24 * @author Jeffrey Burdges <burdges@gnunet.org>
28 #include "gnunet_crypto_lib.h"
30 #define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-rsa", __VA_ARGS__)
34 * The private information of an RSA key pair.
36 struct GNUNET_CRYPTO_RsaPrivateKey
39 * Libgcrypt S-expression for the RSA private key.
46 * The public information of an RSA key pair.
48 struct GNUNET_CRYPTO_RsaPublicKey
51 * Libgcrypt S-expression for the RSA public key.
58 * @brief an RSA signature
60 struct GNUNET_CRYPTO_RsaSignature
63 * Libgcrypt S-expression for the RSA signature.
70 * @brief RSA blinding key
75 * Random value used for blinding.
82 * Extract values from an S-expression.
84 * @param array where to store the result(s)
85 * @param sexp S-expression to parse
86 * @param topname top-level name in the S-expression that is of interest
87 * @param elems names of the elements to extract
88 * @return 0 on success
91 key_from_sexp (gcry_mpi_t *array,
101 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
103 l2 = gcry_sexp_cadr (list);
104 gcry_sexp_release (list);
109 for (s = elems; *s; s++, idx++)
111 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
113 for (unsigned int i = 0; i < idx; i++)
115 gcry_free (array[i]);
118 gcry_sexp_release (list);
119 return 3; /* required parameter not found */
121 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
122 gcry_sexp_release (l2);
125 for (unsigned int i = 0; i < idx; i++)
127 gcry_free (array[i]);
130 gcry_sexp_release (list);
131 return 4; /* required parameter is invalid */
134 gcry_sexp_release (list);
140 * Create a new private key. Caller must free return value.
142 * @param len length of the key in bits (i.e. 2048)
143 * @return fresh private key
145 struct GNUNET_CRYPTO_RsaPrivateKey *
146 GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
148 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
150 gcry_sexp_t s_keyparam;
153 gcry_sexp_build (&s_keyparam,
155 "(genkey(rsa(nbits %d)))",
158 gcry_pk_genkey (&s_key,
160 gcry_sexp_release (s_keyparam);
163 gcry_pk_testkey (s_key));
165 ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
172 * Free memory occupied by the private key.
174 * @param key pointer to the memory to free
177 GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
179 gcry_sexp_release (key->sexp);
185 * Encode the private key in a format suitable for
186 * storing it into a file.
188 * @param key the private key
189 * @param[out] buffer set to a buffer with the encoded key
190 * @return size of memory allocated in @a buffer
193 GNUNET_CRYPTO_rsa_private_key_encode (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
199 n = gcry_sexp_sprint (key->sexp,
200 GCRYSEXP_FMT_DEFAULT,
203 b = GNUNET_malloc (n);
204 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
205 gcry_sexp_sprint (key->sexp,
206 GCRYSEXP_FMT_DEFAULT,
215 * Decode the private key from the data-format back
216 * to the "normal", internal format.
218 * @param buf the buffer where the private key data is stored
219 * @param len the length of the data in @a buf
220 * @return NULL on error
222 struct GNUNET_CRYPTO_RsaPrivateKey *
223 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
226 struct GNUNET_CRYPTO_RsaPrivateKey *key;
227 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
229 gcry_sexp_new (&key->sexp,
234 LOG (GNUNET_ERROR_TYPE_WARNING,
235 "Decoded private key is not valid\n");
239 if (0 != gcry_pk_testkey (key->sexp))
241 LOG (GNUNET_ERROR_TYPE_WARNING,
242 "Decoded private key is not valid\n");
243 GNUNET_CRYPTO_rsa_private_key_free (key);
251 * Extract the public key of the given private key.
253 * @param priv the private key
254 * @retur NULL on error, otherwise the public key
256 struct GNUNET_CRYPTO_RsaPublicKey *
257 GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
259 struct GNUNET_CRYPTO_RsaPublicKey *pub;
264 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
266 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
268 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
274 rc = gcry_sexp_build (&result,
276 "(public-key(rsa(n %m)(e %m)))",
279 gcry_mpi_release (ne[0]);
280 gcry_mpi_release (ne[1]);
281 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
288 * Free memory occupied by the public key.
290 * @param key pointer to the memory to free
293 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
295 gcry_sexp_release (key->sexp);
301 * Encode the public key in a format suitable for
302 * storing it into a file.
304 * @param key the private key
305 * @param[out] buffer set to a buffer with the encoded key
306 * @return size of memory allocated in @a buffer
309 GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key,
315 n = gcry_sexp_sprint (key->sexp,
316 GCRYSEXP_FMT_ADVANCED,
319 b = GNUNET_malloc (n);
320 GNUNET_assert ((n -1) == /* since the last byte is \0 */
321 gcry_sexp_sprint (key->sexp,
322 GCRYSEXP_FMT_ADVANCED,
331 * Compute hash over the public key.
333 * @param key public key to hash
334 * @param hc where to store the hash code
337 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
338 struct GNUNET_HashCode *hc)
343 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
345 GNUNET_CRYPTO_hash (buf,
353 * Decode the public key from the data-format back
354 * to the "normal", internal format.
356 * @param buf the buffer where the public key data is stored
357 * @param len the length of the data in @a buf
358 * @return NULL on error
360 struct GNUNET_CRYPTO_RsaPublicKey *
361 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
364 struct GNUNET_CRYPTO_RsaPublicKey *key;
368 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
370 gcry_sexp_new (&key->sexp,
379 /* verify that this is an RSA public key */
380 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
382 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
385 /* this is no public RSA key */
387 gcry_sexp_release (key->sexp);
391 gcry_mpi_release (n);
397 * Test for malicious RSA key.
399 * Assuming n is an RSA modulous and r is generated using a call to
400 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
401 * malicious RSA key designed to deanomize the user.
403 * @param r KDF result
404 * @param n RSA modulus
405 * @return True if gcd(r,n) = 1, False means RSA key is malicious
408 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
413 g = gcry_mpi_new (0);
414 t = gcry_mpi_gcd(g,r,n);
415 gcry_mpi_release (g);
421 * Create a blinding key
423 * @param len length of the key in bits (i.e. 2048)
424 * @param bks pre-secret to use to derive the blinding key
425 * @return the newly created blinding key, NULL if RSA key is malicious
427 static struct RsaBlindingKey *
428 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
429 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
431 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
432 struct RsaBlindingKey *blind;
435 blind = GNUNET_new (struct RsaBlindingKey);
436 GNUNET_assert( NULL != blind );
438 /* Extract the composite n from the RSA public key */
439 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
440 /* Assert that it at least looks like an RSA key */
441 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
443 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
448 if (0 == rsa_gcd_validate(blind->r, n)) {
453 gcry_mpi_release (n);
459 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
462 There was previously a call to GNUNET_CRYPTO_kdf in
463 bkey = rsa_blinding_key_derive (len, bks);
464 that gives exactly len bits where
465 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
467 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
468 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
469 pkey.n making the effective bkey be
470 bkey mod pkey.n = bkey - pkey.n
471 so the effective bkey has its high bit set with probability r/2.
473 We expect r to be close to 1/2 if the exchange is honest, but the
474 exchange can choose r otherwise.
476 In blind signing, the exchange sees
477 B = bkey * S mod pkey.n
478 On deposit, the exchange sees S so they can compute bkey' = B/S mod
479 pkey.n for all B they recorded to see if bkey' has it's high bit set.
480 Also, note the exchange can compute 1/S efficiently since they know the
483 I suppose that happens with probability r/(1+r) if its the wrong B, not
484 completely sure. If otoh we've the right B, then we've the probability
485 r/2 of a set high bit in the effective bkey.
487 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
488 the wrong and right probabilities 1/3 and 1/4, respectively.
490 I feared this gives the exchange a meaningful fraction of a bit of
491 information per coin involved in the transaction. It sounds damaging if
492 numerous coins were involved. And it could run across transactions in
495 We fixed this by using a more uniform deterministic pseudo-random number
496 generator for blinding factors. I do not believe this to be a problem
497 for the rsa_full_domain_hash routine, but better safe than sorry.
502 * Compare the values of two signatures.
504 * @param s1 one signature
505 * @param s2 the other signature
506 * @return 0 if the two are equal
509 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
510 struct GNUNET_CRYPTO_RsaSignature *s2)
518 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
520 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
535 * Compare the values of two public keys.
537 * @param p1 one public key
538 * @param p2 the other public key
539 * @return 0 if the two are equal
542 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
543 struct GNUNET_CRYPTO_RsaPublicKey *p2)
551 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
553 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
568 * Compare the values of two private keys.
570 * @param p1 one private key
571 * @param p2 the other private key
572 * @return 0 if the two are equal
575 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
576 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
584 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
586 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
601 * Obtain the length of the RSA key in bits.
603 * @param key the public key to introspect
604 * @return length of the key in bits
607 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
612 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
613 { /* Not an RSA public key */
617 rval = gcry_mpi_get_nbits (n);
618 gcry_mpi_release (n);
624 * Destroy a blinding key
626 * @param bkey the blinding key to destroy
629 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
631 gcry_mpi_release (bkey->r);
637 * Print an MPI to a newly created buffer
639 * @param v MPI to print.
640 * @param[out] newly allocated buffer containing the result
641 * @return number of bytes stored in @a buffer
644 numeric_mpi_alloc_n_print (gcry_mpi_t v,
651 gcry_mpi_print (GCRYMPI_FMT_USG,
656 b = GNUNET_malloc (n);
658 gcry_mpi_print (GCRYMPI_FMT_USG,
669 * Computes a full domain hash seeded by the given public key.
670 * This gives a measure of provable security to the Taler exchange
671 * against one-more forgery attacks. See:
672 * https://eprint.iacr.org/2001/002.pdf
673 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
675 * @param hash initial hash of the message to sign
676 * @param pkey the public key of the signer
677 * @param rsize If not NULL, the number of bytes actually stored in buffer
678 * @return MPI value set to the FDH, NULL if RSA key is malicious
681 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
682 const struct GNUNET_HashCode *hash)
689 /* Extract the composite n from the RSA public key */
690 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
691 /* Assert that it at least looks like an RSA key */
692 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
694 /* We key with the public denomination key as a homage to RSA-PSS by *
695 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
696 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
697 * polynomial-time one-more forgary attack. Yey seeding! */
698 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
700 GNUNET_CRYPTO_kdf_mod_mpi (&r,
707 ok = rsa_gcd_validate(r,n);
708 gcry_mpi_release (n);
711 gcry_mpi_release (r);
717 * Blinds the given message with the given blinding key
719 * @param hash hash of the message to sign
720 * @param bkey the blinding key
721 * @param pkey the public key of the signer
722 * @param[out] buf set to a buffer with the blinded message to be signed
723 * @param[out] buf_size number of bytes stored in @a buf
724 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
727 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
728 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
729 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
730 char **buf, size_t *buf_size)
732 struct RsaBlindingKey *bkey;
739 GNUNET_assert (buf != NULL && buf_size != NULL);
740 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
742 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
751 data = rsa_full_domain_hash (pkey, hash);
753 goto rsa_gcd_validate_failure;
755 bkey = rsa_blinding_key_derive (pkey, bks);
757 gcry_mpi_release (data);
758 goto rsa_gcd_validate_failure;
761 r_e = gcry_mpi_new (0);
766 data_r_e = gcry_mpi_new (0);
767 gcry_mpi_mulm (data_r_e,
771 gcry_mpi_release (data);
772 gcry_mpi_release (ne[0]);
773 gcry_mpi_release (ne[1]);
774 gcry_mpi_release (r_e);
775 rsa_blinding_key_free (bkey);
777 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
778 gcry_mpi_release (data_r_e);
781 rsa_gcd_validate_failure:
782 /* We know the RSA key is malicious here, so warn the wallet. */
783 /* GNUNET_break_op (0); */
784 gcry_mpi_release (ne[0]);
785 gcry_mpi_release (ne[1]);
793 * Convert an MPI to an S-expression suitable for signature operations.
795 * @param value pointer to the data to convert
796 * @return converted s-expression
799 mpi_to_sexp (gcry_mpi_t value)
801 gcry_sexp_t data = NULL;
804 gcry_sexp_build (&data,
806 "(data (flags raw) (value %M))",
813 * Sign the given MPI.
815 * @param key private key to use for the signing
816 * @param value the MPI to sign
817 * @return NULL on error, signature on success
819 static struct GNUNET_CRYPTO_RsaSignature *
820 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
823 struct GNUNET_CRYPTO_RsaSignature *sig;
828 data = mpi_to_sexp (value);
831 (rc = gcry_pk_sign (&result,
835 LOG (GNUNET_ERROR_TYPE_WARNING,
836 _("RSA signing failed at %s:%d: %s\n"),
844 /* Lenstra protection was first added to libgcrypt 1.6.4
845 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
847 #if GCRYPT_VERSION_NUMBER < 0x010604
848 /* verify signature (guards against Lenstra's attack with fault injection...) */
849 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
851 gcry_pk_verify (result,
856 GNUNET_CRYPTO_rsa_public_key_free (public_key);
857 gcry_sexp_release (data);
858 gcry_sexp_release (result);
861 GNUNET_CRYPTO_rsa_public_key_free (public_key);
864 /* return signature */
865 gcry_sexp_release (data);
866 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
873 * Sign a blinded value, which must be a full domain hash of a message.
875 * @param key private key to use for the signing
876 * @param msg the message to sign
877 * @param msg_len number of bytes in @a msg to sign
878 * @return NULL on error, signature on success
880 struct GNUNET_CRYPTO_RsaSignature *
881 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
886 struct GNUNET_CRYPTO_RsaSignature *sig;
895 sig = rsa_sign_mpi (key, v);
896 gcry_mpi_release (v);
902 * Create and sign a full domain hash of a message.
904 * @param key private key to use for the signing
905 * @param hash the hash of the message to sign
906 * @return NULL on error, including a malicious RSA key, signature on success
908 struct GNUNET_CRYPTO_RsaSignature *
909 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
910 const struct GNUNET_HashCode *hash)
912 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
914 struct GNUNET_CRYPTO_RsaSignature *sig;
916 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
917 v = rsa_full_domain_hash (pkey, hash);
918 GNUNET_CRYPTO_rsa_public_key_free (pkey);
919 if (NULL == v) /* rsa_gcd_validate failed meaning */
920 return NULL; /* our *own* RSA key is malicious. */
922 sig = rsa_sign_mpi (key, v);
923 gcry_mpi_release (v);
929 * Free memory occupied by signature.
931 * @param sig memory to freee
934 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
936 gcry_sexp_release (sig->sexp);
942 * Encode the given signature in a format suitable for storing it into a file.
944 * @param sig the signature
945 * @param[out] buffer set to a buffer with the encoded key
946 * @return size of memory allocated in @a buffer
949 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
955 n = gcry_sexp_sprint (sig->sexp,
956 GCRYSEXP_FMT_ADVANCED,
959 b = GNUNET_malloc (n);
960 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
961 gcry_sexp_sprint (sig->sexp,
962 GCRYSEXP_FMT_ADVANCED,
971 * Decode the signature from the data-format back to the "normal", internal
974 * @param buf the buffer where the public key data is stored
975 * @param len the length of the data in @a buf
976 * @return NULL on error
978 struct GNUNET_CRYPTO_RsaSignature *
979 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
982 struct GNUNET_CRYPTO_RsaSignature *sig;
986 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
988 gcry_sexp_new (&sig->sexp,
997 /* verify that this is an RSA signature */
998 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1000 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1003 /* this is no RSA Signature */
1004 GNUNET_break_op (0);
1005 gcry_sexp_release (sig->sexp);
1009 gcry_mpi_release (s);
1015 * Duplicate the given public key
1017 * @param key the public key to duplicate
1018 * @return the duplicate key; NULL upon error
1020 struct GNUNET_CRYPTO_RsaPublicKey *
1021 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1023 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1024 gcry_sexp_t dup_sexp;
1027 /* check if we really are exporting a public key */
1028 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1029 GNUNET_assert (NULL != dup_sexp);
1030 gcry_sexp_release (dup_sexp);
1032 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1033 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1034 dup->sexp = dup_sexp;
1040 * Unblind a blind-signed signature. The signature should have been generated
1041 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1042 * #GNUNET_CRYPTO_rsa_blind().
1044 * @param sig the signature made on the blinded signature purpose
1045 * @param bks the blinding key secret used to blind the signature purpose
1046 * @param pkey the public key of the signer
1047 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1049 struct GNUNET_CRYPTO_RsaSignature *
1050 GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
1051 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1052 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1054 struct RsaBlindingKey *bkey;
1060 struct GNUNET_CRYPTO_RsaSignature *sret;
1062 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1064 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1067 GNUNET_break_op (0);
1070 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1072 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1075 gcry_mpi_release (n);
1076 GNUNET_break_op (0);
1080 bkey = rsa_blinding_key_derive (pkey, bks);
1083 /* RSA key is malicious since rsa_gcd_validate failed here.
1084 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1085 * so the exchange is being malicious in an unfamilair way, maybe
1086 * just trying to crash us. */
1087 GNUNET_break_op (0);
1088 gcry_mpi_release (n);
1089 gcry_mpi_release (s);
1093 r_inv = gcry_mpi_new (0);
1095 gcry_mpi_invm (r_inv,
1099 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1100 * caught above, but we handle it the same here. */
1101 GNUNET_break_op (0);
1102 gcry_mpi_release (r_inv);
1103 rsa_blinding_key_free (bkey);
1104 gcry_mpi_release (n);
1105 gcry_mpi_release (s);
1109 ubsig = gcry_mpi_new (0);
1110 gcry_mpi_mulm (ubsig, s, r_inv, n);
1111 gcry_mpi_release (n);
1112 gcry_mpi_release (r_inv);
1113 gcry_mpi_release (s);
1114 rsa_blinding_key_free (bkey);
1116 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1118 gcry_sexp_build (&sret->sexp,
1120 "(sig-val (rsa (s %M)))",
1122 gcry_mpi_release (ubsig);
1128 * Verify whether the given hash corresponds to the given signature and
1129 * the signature is valid with respect to the given public key.
1131 * @param hash hash of the message to verify to match the @a sig
1132 * @param sig signature that is being validated
1133 * @param pkey public key of the signer
1134 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1137 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1138 const struct GNUNET_CRYPTO_RsaSignature *sig,
1139 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1145 r = rsa_full_domain_hash (pkey, hash);
1147 GNUNET_break_op (0);
1148 /* RSA key is malicious since rsa_gcd_validate failed here.
1149 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1150 * so the exchange is being malicious in an unfamilair way, maybe
1151 * just trying to crash us. Arguably, we've only an internal error
1152 * though because we should've detected this in our previous call
1153 * to GNUNET_CRYPTO_rsa_unblind. */
1157 data = mpi_to_sexp(r);
1158 gcry_mpi_release (r);
1160 rc = gcry_pk_verify (sig->sexp,
1163 gcry_sexp_release (data);
1166 LOG (GNUNET_ERROR_TYPE_WARNING,
1167 _("RSA signature verification failed at %s:%d: %s\n"),
1170 gcry_strerror (rc));
1171 return GNUNET_SYSERR;
1178 * Duplicate the given private key
1180 * @param key the private key to duplicate
1181 * @return the duplicate key; NULL upon error
1183 struct GNUNET_CRYPTO_RsaPrivateKey *
1184 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1186 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1187 gcry_sexp_t dup_sexp;
1190 /* check if we really are exporting a private key */
1191 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1192 GNUNET_assert (NULL != dup_sexp);
1193 gcry_sexp_release (dup_sexp);
1195 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1196 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1197 dup->sexp = dup_sexp;
1203 * Duplicate the given private key
1205 * @param key the private key to duplicate
1206 * @return the duplicate key; NULL upon error
1208 struct GNUNET_CRYPTO_RsaSignature *
1209 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1211 struct GNUNET_CRYPTO_RsaSignature *dup;
1212 gcry_sexp_t dup_sexp;
1217 /* verify that this is an RSA signature */
1218 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1220 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1221 GNUNET_assert (0 == ret);
1222 gcry_mpi_release (s);
1224 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1225 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1226 dup->sexp = dup_sexp;
1231 /* end of util/rsa.c */