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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file util/crypto_rsa.c
23 * @brief Chaum-style Blind signatures based on RSA
24 * @author Sree Harsha Totakura <sreeharsha@totakura.in>
25 * @author Christian Grothoff
26 * @author Jeffrey Burdges <burdges@gnunet.org>
30 #include "gnunet_crypto_lib.h"
31 #include "benchmark.h"
33 #define LOG(kind, ...) GNUNET_log_from (kind, "util-crypto-rsa", __VA_ARGS__)
37 * The private information of an RSA key pair.
39 struct GNUNET_CRYPTO_RsaPrivateKey
42 * Libgcrypt S-expression for the RSA private key.
49 * The public information of an RSA key pair.
51 struct GNUNET_CRYPTO_RsaPublicKey
54 * Libgcrypt S-expression for the RSA public key.
61 * @brief an RSA signature
63 struct GNUNET_CRYPTO_RsaSignature
66 * Libgcrypt S-expression for the RSA signature.
73 * @brief RSA blinding key
78 * Random value used for blinding.
85 * Extract values from an S-expression.
87 * @param array where to store the result(s)
88 * @param sexp S-expression to parse
89 * @param topname top-level name in the S-expression that is of interest
90 * @param elems names of the elements to extract
91 * @return 0 on success
94 key_from_sexp (gcry_mpi_t *array,
104 if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
106 l2 = gcry_sexp_cadr (list);
107 gcry_sexp_release (list);
112 for (s = elems; *s; s++, idx++)
114 if (! (l2 = gcry_sexp_find_token (list, s, 1)))
116 for (unsigned int i = 0; i < idx; i++)
118 gcry_free (array[i]);
121 gcry_sexp_release (list);
122 return 3; /* required parameter not found */
124 array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
125 gcry_sexp_release (l2);
128 for (unsigned int i = 0; i < idx; i++)
130 gcry_free (array[i]);
133 gcry_sexp_release (list);
134 return 4; /* required parameter is invalid */
137 gcry_sexp_release (list);
143 * Create a new private key. Caller must free return value.
145 * @param len length of the key in bits (i.e. 2048)
146 * @return fresh private key
148 struct GNUNET_CRYPTO_RsaPrivateKey *
149 GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
151 struct GNUNET_CRYPTO_RsaPrivateKey *ret;
153 gcry_sexp_t s_keyparam;
155 BENCHMARK_START (rsa_private_key_create);
158 gcry_sexp_build (&s_keyparam,
160 "(genkey(rsa(nbits %d)))",
163 gcry_pk_genkey (&s_key,
165 gcry_sexp_release (s_keyparam);
168 gcry_pk_testkey (s_key));
170 ret = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
172 BENCHMARK_END (rsa_private_key_create);
178 * Free memory occupied by the private key.
180 * @param key pointer to the memory to free
183 GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_RsaPrivateKey *key)
185 gcry_sexp_release (key->sexp);
191 * Encode the private key in a format suitable for
192 * storing it into a file.
194 * @param key the private key
195 * @param[out] buffer set to a buffer with the encoded key
196 * @return size of memory allocated in @a buffer
199 GNUNET_CRYPTO_rsa_private_key_encode (const struct
200 GNUNET_CRYPTO_RsaPrivateKey *key,
206 n = gcry_sexp_sprint (key->sexp,
207 GCRYSEXP_FMT_DEFAULT,
210 b = GNUNET_malloc (n);
211 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
212 gcry_sexp_sprint (key->sexp,
213 GCRYSEXP_FMT_DEFAULT,
222 * Decode the private key from the data-format back
223 * to the "normal", internal format.
225 * @param buf the buffer where the private key data is stored
226 * @param len the length of the data in @a buf
227 * @return NULL on error
229 struct GNUNET_CRYPTO_RsaPrivateKey *
230 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
233 struct GNUNET_CRYPTO_RsaPrivateKey *key;
235 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
237 gcry_sexp_new (&key->sexp,
242 LOG (GNUNET_ERROR_TYPE_WARNING,
243 "Decoded private key is not valid\n");
247 if (0 != gcry_pk_testkey (key->sexp))
249 LOG (GNUNET_ERROR_TYPE_WARNING,
250 "Decoded private key is not valid\n");
251 GNUNET_CRYPTO_rsa_private_key_free (key);
259 * Extract the public key of the given private key.
261 * @param priv the private key
262 * @retur NULL on error, otherwise the public key
264 struct GNUNET_CRYPTO_RsaPublicKey *
265 GNUNET_CRYPTO_rsa_private_key_get_public (const struct
266 GNUNET_CRYPTO_RsaPrivateKey *priv)
268 struct GNUNET_CRYPTO_RsaPublicKey *pub;
273 BENCHMARK_START (rsa_private_key_get_public);
275 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
277 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
279 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
285 rc = gcry_sexp_build (&result,
287 "(public-key(rsa(n %m)(e %m)))",
290 gcry_mpi_release (ne[0]);
291 gcry_mpi_release (ne[1]);
292 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
294 BENCHMARK_END (rsa_private_key_get_public);
300 * Free memory occupied by the public key.
302 * @param key pointer to the memory to free
305 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
307 gcry_sexp_release (key->sexp);
313 * Encode the public key in a format suitable for
314 * storing it into a file.
316 * @param key the private key
317 * @param[out] buffer set to a buffer with the encoded key
318 * @return size of memory allocated in @a buffer
321 GNUNET_CRYPTO_rsa_public_key_encode (const struct
322 GNUNET_CRYPTO_RsaPublicKey *key,
328 n = gcry_sexp_sprint (key->sexp,
329 GCRYSEXP_FMT_ADVANCED,
332 b = GNUNET_malloc (n);
333 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
334 gcry_sexp_sprint (key->sexp,
335 GCRYSEXP_FMT_ADVANCED,
344 * Compute hash over the public key.
346 * @param key public key to hash
347 * @param hc where to store the hash code
350 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
351 struct GNUNET_HashCode *hc)
356 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
358 GNUNET_CRYPTO_hash (buf,
366 * Decode the public key from the data-format back
367 * to the "normal", internal format.
369 * @param buf the buffer where the public key data is stored
370 * @param len the length of the data in @a buf
371 * @return NULL on error
373 struct GNUNET_CRYPTO_RsaPublicKey *
374 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
377 struct GNUNET_CRYPTO_RsaPublicKey *key;
381 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
383 gcry_sexp_new (&key->sexp,
392 /* verify that this is an RSA public key */
393 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
395 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
398 /* this is no public RSA key */
400 gcry_sexp_release (key->sexp);
404 gcry_mpi_release (n);
410 * Test for malicious RSA key.
412 * Assuming n is an RSA modulous and r is generated using a call to
413 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
414 * malicious RSA key designed to deanomize the user.
416 * @param r KDF result
417 * @param n RSA modulus
418 * @return True if gcd(r,n) = 1, False means RSA key is malicious
421 rsa_gcd_validate (gcry_mpi_t r, gcry_mpi_t n)
426 g = gcry_mpi_new (0);
427 t = gcry_mpi_gcd (g, r, n);
428 gcry_mpi_release (g);
434 * Create a blinding key
436 * @param len length of the key in bits (i.e. 2048)
437 * @param bks pre-secret to use to derive the blinding key
438 * @return the newly created blinding key, NULL if RSA key is malicious
440 static struct RsaBlindingKey *
441 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
442 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
444 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
445 struct RsaBlindingKey *blind;
448 blind = GNUNET_new (struct RsaBlindingKey);
449 GNUNET_assert (NULL != blind);
451 /* Extract the composite n from the RSA public key */
452 GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n"));
453 /* Assert that it at least looks like an RSA key */
454 GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE));
456 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
461 if (0 == rsa_gcd_validate (blind->r, n))
467 gcry_mpi_release (n);
473 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
476 There was previously a call to GNUNET_CRYPTO_kdf in
477 bkey = rsa_blinding_key_derive (len, bks);
478 that gives exactly len bits where
479 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
481 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
482 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
483 pkey.n making the effective bkey be
484 bkey mod pkey.n = bkey - pkey.n
485 so the effective bkey has its high bit set with probability r/2.
487 We expect r to be close to 1/2 if the exchange is honest, but the
488 exchange can choose r otherwise.
490 In blind signing, the exchange sees
491 B = bkey * S mod pkey.n
492 On deposit, the exchange sees S so they can compute bkey' = B/S mod
493 pkey.n for all B they recorded to see if bkey' has it's high bit set.
494 Also, note the exchange can compute 1/S efficiently since they know the
497 I suppose that happens with probability r/(1+r) if its the wrong B, not
498 completely sure. If otoh we've the right B, then we've the probability
499 r/2 of a set high bit in the effective bkey.
501 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
502 the wrong and right probabilities 1/3 and 1/4, respectively.
504 I feared this gives the exchange a meaningful fraction of a bit of
505 information per coin involved in the transaction. It sounds damaging if
506 numerous coins were involved. And it could run across transactions in
509 We fixed this by using a more uniform deterministic pseudo-random number
510 generator for blinding factors. I do not believe this to be a problem
511 for the rsa_full_domain_hash routine, but better safe than sorry.
516 * Compare the values of two signatures.
518 * @param s1 one signature
519 * @param s2 the other signature
520 * @return 0 if the two are equal
523 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
524 struct GNUNET_CRYPTO_RsaSignature *s2)
532 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
534 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
549 * Compare the values of two public keys.
551 * @param p1 one public key
552 * @param p2 the other public key
553 * @return 0 if the two are equal
556 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
557 struct GNUNET_CRYPTO_RsaPublicKey *p2)
565 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
567 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
582 * Compare the values of two private keys.
584 * @param p1 one private key
585 * @param p2 the other private key
586 * @return 0 if the two are equal
589 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
590 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
598 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
600 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
615 * Obtain the length of the RSA key in bits.
617 * @param key the public key to introspect
618 * @return length of the key in bits
621 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
626 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
627 { /* Not an RSA public key */
631 rval = gcry_mpi_get_nbits (n);
632 gcry_mpi_release (n);
638 * Destroy a blinding key
640 * @param bkey the blinding key to destroy
643 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
645 gcry_mpi_release (bkey->r);
651 * Print an MPI to a newly created buffer
653 * @param v MPI to print.
654 * @param[out] newly allocated buffer containing the result
655 * @return number of bytes stored in @a buffer
658 numeric_mpi_alloc_n_print (gcry_mpi_t v,
665 gcry_mpi_print (GCRYMPI_FMT_USG,
670 b = GNUNET_malloc (n);
672 gcry_mpi_print (GCRYMPI_FMT_USG,
683 * Computes a full domain hash seeded by the given public key.
684 * This gives a measure of provable security to the Taler exchange
685 * against one-more forgery attacks. See:
686 * https://eprint.iacr.org/2001/002.pdf
687 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
689 * @param hash initial hash of the message to sign
690 * @param pkey the public key of the signer
691 * @param rsize If not NULL, the number of bytes actually stored in buffer
692 * @return MPI value set to the FDH, NULL if RSA key is malicious
695 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
696 const struct GNUNET_HashCode *hash)
703 /* Extract the composite n from the RSA public key */
704 GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n"));
705 /* Assert that it at least looks like an RSA key */
706 GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE));
708 /* We key with the public denomination key as a homage to RSA-PSS by *
709 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
710 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
711 * polynomial-time one-more forgary attack. Yey seeding! */
712 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
714 GNUNET_CRYPTO_kdf_mod_mpi (&r,
721 ok = rsa_gcd_validate (r, n);
722 gcry_mpi_release (n);
725 gcry_mpi_release (r);
731 * Blinds the given message with the given blinding key
733 * @param hash hash of the message to sign
734 * @param bkey the blinding key
735 * @param pkey the public key of the signer
736 * @param[out] buf set to a buffer with the blinded message to be signed
737 * @param[out] buf_size number of bytes stored in @a buf
738 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
741 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
742 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
743 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
744 char **buf, size_t *buf_size)
746 struct RsaBlindingKey *bkey;
753 BENCHMARK_START (rsa_blind);
755 GNUNET_assert (buf != NULL && buf_size != NULL);
756 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
758 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
767 data = rsa_full_domain_hash (pkey, hash);
769 goto rsa_gcd_validate_failure;
771 bkey = rsa_blinding_key_derive (pkey, bks);
774 gcry_mpi_release (data);
775 goto rsa_gcd_validate_failure;
778 r_e = gcry_mpi_new (0);
783 data_r_e = gcry_mpi_new (0);
784 gcry_mpi_mulm (data_r_e,
788 gcry_mpi_release (data);
789 gcry_mpi_release (ne[0]);
790 gcry_mpi_release (ne[1]);
791 gcry_mpi_release (r_e);
792 rsa_blinding_key_free (bkey);
794 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
795 gcry_mpi_release (data_r_e);
797 BENCHMARK_END (rsa_blind);
801 rsa_gcd_validate_failure:
802 /* We know the RSA key is malicious here, so warn the wallet. */
803 /* GNUNET_break_op (0); */
804 gcry_mpi_release (ne[0]);
805 gcry_mpi_release (ne[1]);
813 * Convert an MPI to an S-expression suitable for signature operations.
815 * @param value pointer to the data to convert
816 * @return converted s-expression
819 mpi_to_sexp (gcry_mpi_t value)
821 gcry_sexp_t data = NULL;
824 gcry_sexp_build (&data,
826 "(data (flags raw) (value %M))",
833 * Sign the given MPI.
835 * @param key private key to use for the signing
836 * @param value the MPI to sign
837 * @return NULL on error, signature on success
839 static struct GNUNET_CRYPTO_RsaSignature *
840 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
843 struct GNUNET_CRYPTO_RsaSignature *sig;
848 data = mpi_to_sexp (value);
851 (rc = gcry_pk_sign (&result,
855 LOG (GNUNET_ERROR_TYPE_WARNING,
856 _ ("RSA signing failed at %s:%d: %s\n"),
864 /* Lenstra protection was first added to libgcrypt 1.6.4
865 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
867 #if GCRYPT_VERSION_NUMBER < 0x010604
868 /* verify signature (guards against Lenstra's attack with fault injection...) */
869 struct GNUNET_CRYPTO_RsaPublicKey *public_key =
870 GNUNET_CRYPTO_rsa_private_key_get_public (key);
872 gcry_pk_verify (result,
877 GNUNET_CRYPTO_rsa_public_key_free (public_key);
878 gcry_sexp_release (data);
879 gcry_sexp_release (result);
882 GNUNET_CRYPTO_rsa_public_key_free (public_key);
885 /* return signature */
886 gcry_sexp_release (data);
887 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
894 * Sign a blinded value, which must be a full domain hash of a message.
896 * @param key private key to use for the signing
897 * @param msg the message to sign
898 * @param msg_len number of bytes in @a msg to sign
899 * @return NULL on error, signature on success
901 struct GNUNET_CRYPTO_RsaSignature *
902 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
907 struct GNUNET_CRYPTO_RsaSignature *sig;
909 BENCHMARK_START (rsa_sign_blinded);
918 sig = rsa_sign_mpi (key, v);
919 gcry_mpi_release (v);
920 BENCHMARK_END (rsa_sign_blinded);
926 * Create and sign a full domain hash of a message.
928 * @param key private key to use for the signing
929 * @param hash the hash of the message to sign
930 * @return NULL on error, including a malicious RSA key, signature on success
932 struct GNUNET_CRYPTO_RsaSignature *
933 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
934 const struct GNUNET_HashCode *hash)
936 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
938 struct GNUNET_CRYPTO_RsaSignature *sig;
940 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
941 v = rsa_full_domain_hash (pkey, hash);
942 GNUNET_CRYPTO_rsa_public_key_free (pkey);
943 if (NULL == v) /* rsa_gcd_validate failed meaning */
944 return NULL; /* our *own* RSA key is malicious. */
946 sig = rsa_sign_mpi (key, v);
947 gcry_mpi_release (v);
953 * Free memory occupied by signature.
955 * @param sig memory to freee
958 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
960 gcry_sexp_release (sig->sexp);
966 * Encode the given signature in a format suitable for storing it into a file.
968 * @param sig the signature
969 * @param[out] buffer set to a buffer with the encoded key
970 * @return size of memory allocated in @a buffer
973 GNUNET_CRYPTO_rsa_signature_encode (const struct
974 GNUNET_CRYPTO_RsaSignature *sig,
980 n = gcry_sexp_sprint (sig->sexp,
981 GCRYSEXP_FMT_ADVANCED,
984 b = GNUNET_malloc (n);
985 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
986 gcry_sexp_sprint (sig->sexp,
987 GCRYSEXP_FMT_ADVANCED,
996 * Decode the signature from the data-format back to the "normal", internal
999 * @param buf the buffer where the public key data is stored
1000 * @param len the length of the data in @a buf
1001 * @return NULL on error
1003 struct GNUNET_CRYPTO_RsaSignature *
1004 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
1007 struct GNUNET_CRYPTO_RsaSignature *sig;
1011 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1013 gcry_sexp_new (&sig->sexp,
1018 GNUNET_break_op (0);
1022 /* verify that this is an RSA signature */
1023 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1025 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1028 /* this is no RSA Signature */
1029 GNUNET_break_op (0);
1030 gcry_sexp_release (sig->sexp);
1034 gcry_mpi_release (s);
1040 * Duplicate the given public key
1042 * @param key the public key to duplicate
1043 * @return the duplicate key; NULL upon error
1045 struct GNUNET_CRYPTO_RsaPublicKey *
1046 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1048 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1049 gcry_sexp_t dup_sexp;
1052 /* check if we really are exporting a public key */
1053 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1054 GNUNET_assert (NULL != dup_sexp);
1055 gcry_sexp_release (dup_sexp);
1057 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1058 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1059 dup->sexp = dup_sexp;
1065 * Unblind a blind-signed signature. The signature should have been generated
1066 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1067 * #GNUNET_CRYPTO_rsa_blind().
1069 * @param sig the signature made on the blinded signature purpose
1070 * @param bks the blinding key secret used to blind the signature purpose
1071 * @param pkey the public key of the signer
1072 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1074 struct GNUNET_CRYPTO_RsaSignature *
1075 GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
1076 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1077 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1079 struct RsaBlindingKey *bkey;
1085 struct GNUNET_CRYPTO_RsaSignature *sret;
1087 BENCHMARK_START (rsa_unblind);
1089 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1091 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1094 GNUNET_break_op (0);
1097 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1099 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1102 gcry_mpi_release (n);
1103 GNUNET_break_op (0);
1107 bkey = rsa_blinding_key_derive (pkey, bks);
1110 /* RSA key is malicious since rsa_gcd_validate failed here.
1111 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1112 * so the exchange is being malicious in an unfamilair way, maybe
1113 * just trying to crash us. */
1114 GNUNET_break_op (0);
1115 gcry_mpi_release (n);
1116 gcry_mpi_release (s);
1120 r_inv = gcry_mpi_new (0);
1122 gcry_mpi_invm (r_inv,
1126 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1127 * caught above, but we handle it the same here. */
1128 GNUNET_break_op (0);
1129 gcry_mpi_release (r_inv);
1130 rsa_blinding_key_free (bkey);
1131 gcry_mpi_release (n);
1132 gcry_mpi_release (s);
1136 ubsig = gcry_mpi_new (0);
1137 gcry_mpi_mulm (ubsig, s, r_inv, n);
1138 gcry_mpi_release (n);
1139 gcry_mpi_release (r_inv);
1140 gcry_mpi_release (s);
1141 rsa_blinding_key_free (bkey);
1143 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1145 gcry_sexp_build (&sret->sexp,
1147 "(sig-val (rsa (s %M)))",
1149 gcry_mpi_release (ubsig);
1150 BENCHMARK_END (rsa_unblind);
1156 * Verify whether the given hash corresponds to the given signature and
1157 * the signature is valid with respect to the given public key.
1159 * @param hash hash of the message to verify to match the @a sig
1160 * @param sig signature that is being validated
1161 * @param pkey public key of the signer
1162 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1165 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1166 const struct GNUNET_CRYPTO_RsaSignature *sig,
1167 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1173 BENCHMARK_START (rsa_verify);
1175 r = rsa_full_domain_hash (pkey, hash);
1178 GNUNET_break_op (0);
1179 /* RSA key is malicious since rsa_gcd_validate failed here.
1180 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1181 * so the exchange is being malicious in an unfamilair way, maybe
1182 * just trying to crash us. Arguably, we've only an internal error
1183 * though because we should've detected this in our previous call
1184 * to GNUNET_CRYPTO_rsa_unblind. */
1188 data = mpi_to_sexp (r);
1189 gcry_mpi_release (r);
1191 rc = gcry_pk_verify (sig->sexp,
1194 gcry_sexp_release (data);
1197 LOG (GNUNET_ERROR_TYPE_WARNING,
1198 _ ("RSA signature verification failed at %s:%d: %s\n"),
1201 gcry_strerror (rc));
1202 return GNUNET_SYSERR;
1203 BENCHMARK_END (rsa_verify);
1205 BENCHMARK_END (rsa_verify);
1211 * Duplicate the given private key
1213 * @param key the private key to duplicate
1214 * @return the duplicate key; NULL upon error
1216 struct GNUNET_CRYPTO_RsaPrivateKey *
1217 GNUNET_CRYPTO_rsa_private_key_dup (const struct
1218 GNUNET_CRYPTO_RsaPrivateKey *key)
1220 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1221 gcry_sexp_t dup_sexp;
1224 /* check if we really are exporting a private key */
1225 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1226 GNUNET_assert (NULL != dup_sexp);
1227 gcry_sexp_release (dup_sexp);
1229 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1230 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1231 dup->sexp = dup_sexp;
1237 * Duplicate the given private key
1239 * @param key the private key to duplicate
1240 * @return the duplicate key; NULL upon error
1242 struct GNUNET_CRYPTO_RsaSignature *
1243 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1245 struct GNUNET_CRYPTO_RsaSignature *dup;
1246 gcry_sexp_t dup_sexp;
1251 /* verify that this is an RSA signature */
1252 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1254 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1255 GNUNET_assert (0 == ret);
1256 gcry_mpi_release (s);
1258 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1259 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1260 dup->sexp = dup_sexp;
1265 /* end of util/rsa.c */