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 GNUNET_CRYPTO_RsaPrivateKey *key,
205 n = gcry_sexp_sprint (key->sexp,
206 GCRYSEXP_FMT_DEFAULT,
209 b = GNUNET_malloc (n);
210 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
211 gcry_sexp_sprint (key->sexp,
212 GCRYSEXP_FMT_DEFAULT,
221 * Decode the private key from the data-format back
222 * to the "normal", internal format.
224 * @param buf the buffer where the private key data is stored
225 * @param len the length of the data in @a buf
226 * @return NULL on error
228 struct GNUNET_CRYPTO_RsaPrivateKey *
229 GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
232 struct GNUNET_CRYPTO_RsaPrivateKey *key;
233 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
235 gcry_sexp_new (&key->sexp,
240 LOG (GNUNET_ERROR_TYPE_WARNING,
241 "Decoded private key is not valid\n");
245 if (0 != gcry_pk_testkey (key->sexp))
247 LOG (GNUNET_ERROR_TYPE_WARNING,
248 "Decoded private key is not valid\n");
249 GNUNET_CRYPTO_rsa_private_key_free (key);
257 * Extract the public key of the given private key.
259 * @param priv the private key
260 * @retur NULL on error, otherwise the public key
262 struct GNUNET_CRYPTO_RsaPublicKey *
263 GNUNET_CRYPTO_rsa_private_key_get_public (const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
265 struct GNUNET_CRYPTO_RsaPublicKey *pub;
270 BENCHMARK_START (rsa_private_key_get_public);
272 rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
274 rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
276 rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
282 rc = gcry_sexp_build (&result,
284 "(public-key(rsa(n %m)(e %m)))",
287 gcry_mpi_release (ne[0]);
288 gcry_mpi_release (ne[1]);
289 pub = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
291 BENCHMARK_END (rsa_private_key_get_public);
297 * Free memory occupied by the public key.
299 * @param key pointer to the memory to free
302 GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_RsaPublicKey *key)
304 gcry_sexp_release (key->sexp);
310 * Encode the public key in a format suitable for
311 * storing it into a file.
313 * @param key the private key
314 * @param[out] buffer set to a buffer with the encoded key
315 * @return size of memory allocated in @a buffer
318 GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_RsaPublicKey *key,
324 n = gcry_sexp_sprint (key->sexp,
325 GCRYSEXP_FMT_ADVANCED,
328 b = GNUNET_malloc (n);
329 GNUNET_assert ((n -1) == /* since the last byte is \0 */
330 gcry_sexp_sprint (key->sexp,
331 GCRYSEXP_FMT_ADVANCED,
340 * Compute hash over the public key.
342 * @param key public key to hash
343 * @param hc where to store the hash code
346 GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey *key,
347 struct GNUNET_HashCode *hc)
352 buf_size = GNUNET_CRYPTO_rsa_public_key_encode (key,
354 GNUNET_CRYPTO_hash (buf,
362 * Decode the public key from the data-format back
363 * to the "normal", internal format.
365 * @param buf the buffer where the public key data is stored
366 * @param len the length of the data in @a buf
367 * @return NULL on error
369 struct GNUNET_CRYPTO_RsaPublicKey *
370 GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
373 struct GNUNET_CRYPTO_RsaPublicKey *key;
377 key = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
379 gcry_sexp_new (&key->sexp,
388 /* verify that this is an RSA public key */
389 ret = key_from_sexp (&n, key->sexp, "public-key", "n");
391 ret = key_from_sexp (&n, key->sexp, "rsa", "n");
394 /* this is no public RSA key */
396 gcry_sexp_release (key->sexp);
400 gcry_mpi_release (n);
406 * Test for malicious RSA key.
408 * Assuming n is an RSA modulous and r is generated using a call to
409 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
410 * malicious RSA key designed to deanomize the user.
412 * @param r KDF result
413 * @param n RSA modulus
414 * @return True if gcd(r,n) = 1, False means RSA key is malicious
417 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
422 g = gcry_mpi_new (0);
423 t = gcry_mpi_gcd(g,r,n);
424 gcry_mpi_release (g);
430 * Create a blinding key
432 * @param len length of the key in bits (i.e. 2048)
433 * @param bks pre-secret to use to derive the blinding key
434 * @return the newly created blinding key, NULL if RSA key is malicious
436 static struct RsaBlindingKey *
437 rsa_blinding_key_derive (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
438 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
440 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
441 struct RsaBlindingKey *blind;
444 blind = GNUNET_new (struct RsaBlindingKey);
445 GNUNET_assert( NULL != blind );
447 /* Extract the composite n from the RSA public key */
448 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
449 /* Assert that it at least looks like an RSA key */
450 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
452 GNUNET_CRYPTO_kdf_mod_mpi (&blind->r,
457 if (0 == rsa_gcd_validate(blind->r, n)) {
462 gcry_mpi_release (n);
468 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
471 There was previously a call to GNUNET_CRYPTO_kdf in
472 bkey = rsa_blinding_key_derive (len, bks);
473 that gives exactly len bits where
474 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
476 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
477 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
478 pkey.n making the effective bkey be
479 bkey mod pkey.n = bkey - pkey.n
480 so the effective bkey has its high bit set with probability r/2.
482 We expect r to be close to 1/2 if the exchange is honest, but the
483 exchange can choose r otherwise.
485 In blind signing, the exchange sees
486 B = bkey * S mod pkey.n
487 On deposit, the exchange sees S so they can compute bkey' = B/S mod
488 pkey.n for all B they recorded to see if bkey' has it's high bit set.
489 Also, note the exchange can compute 1/S efficiently since they know the
492 I suppose that happens with probability r/(1+r) if its the wrong B, not
493 completely sure. If otoh we've the right B, then we've the probability
494 r/2 of a set high bit in the effective bkey.
496 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
497 the wrong and right probabilities 1/3 and 1/4, respectively.
499 I feared this gives the exchange a meaningful fraction of a bit of
500 information per coin involved in the transaction. It sounds damaging if
501 numerous coins were involved. And it could run across transactions in
504 We fixed this by using a more uniform deterministic pseudo-random number
505 generator for blinding factors. I do not believe this to be a problem
506 for the rsa_full_domain_hash routine, but better safe than sorry.
511 * Compare the values of two signatures.
513 * @param s1 one signature
514 * @param s2 the other signature
515 * @return 0 if the two are equal
518 GNUNET_CRYPTO_rsa_signature_cmp (struct GNUNET_CRYPTO_RsaSignature *s1,
519 struct GNUNET_CRYPTO_RsaSignature *s2)
527 z1 = GNUNET_CRYPTO_rsa_signature_encode (s1,
529 z2 = GNUNET_CRYPTO_rsa_signature_encode (s2,
544 * Compare the values of two public keys.
546 * @param p1 one public key
547 * @param p2 the other public key
548 * @return 0 if the two are equal
551 GNUNET_CRYPTO_rsa_public_key_cmp (struct GNUNET_CRYPTO_RsaPublicKey *p1,
552 struct GNUNET_CRYPTO_RsaPublicKey *p2)
560 z1 = GNUNET_CRYPTO_rsa_public_key_encode (p1,
562 z2 = GNUNET_CRYPTO_rsa_public_key_encode (p2,
577 * Compare the values of two private keys.
579 * @param p1 one private key
580 * @param p2 the other private key
581 * @return 0 if the two are equal
584 GNUNET_CRYPTO_rsa_private_key_cmp (struct GNUNET_CRYPTO_RsaPrivateKey *p1,
585 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
593 z1 = GNUNET_CRYPTO_rsa_private_key_encode (p1,
595 z2 = GNUNET_CRYPTO_rsa_private_key_encode (p2,
610 * Obtain the length of the RSA key in bits.
612 * @param key the public key to introspect
613 * @return length of the key in bits
616 GNUNET_CRYPTO_rsa_public_key_len (const struct GNUNET_CRYPTO_RsaPublicKey *key)
621 if (0 != key_from_sexp (&n, key->sexp, "rsa", "n"))
622 { /* Not an RSA public key */
626 rval = gcry_mpi_get_nbits (n);
627 gcry_mpi_release (n);
633 * Destroy a blinding key
635 * @param bkey the blinding key to destroy
638 rsa_blinding_key_free (struct RsaBlindingKey *bkey)
640 gcry_mpi_release (bkey->r);
646 * Print an MPI to a newly created buffer
648 * @param v MPI to print.
649 * @param[out] newly allocated buffer containing the result
650 * @return number of bytes stored in @a buffer
653 numeric_mpi_alloc_n_print (gcry_mpi_t v,
660 gcry_mpi_print (GCRYMPI_FMT_USG,
665 b = GNUNET_malloc (n);
667 gcry_mpi_print (GCRYMPI_FMT_USG,
678 * Computes a full domain hash seeded by the given public key.
679 * This gives a measure of provable security to the Taler exchange
680 * against one-more forgery attacks. See:
681 * https://eprint.iacr.org/2001/002.pdf
682 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
684 * @param hash initial hash of the message to sign
685 * @param pkey the public key of the signer
686 * @param rsize If not NULL, the number of bytes actually stored in buffer
687 * @return MPI value set to the FDH, NULL if RSA key is malicious
690 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
691 const struct GNUNET_HashCode *hash)
698 /* Extract the composite n from the RSA public key */
699 GNUNET_assert( 0 == key_from_sexp (&n, pkey->sexp, "rsa", "n") );
700 /* Assert that it at least looks like an RSA key */
701 GNUNET_assert( 0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE) );
703 /* We key with the public denomination key as a homage to RSA-PSS by *
704 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
705 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
706 * polynomial-time one-more forgary attack. Yey seeding! */
707 xts_len = GNUNET_CRYPTO_rsa_public_key_encode (pkey, &xts);
709 GNUNET_CRYPTO_kdf_mod_mpi (&r,
716 ok = rsa_gcd_validate(r,n);
717 gcry_mpi_release (n);
720 gcry_mpi_release (r);
726 * Blinds the given message with the given blinding key
728 * @param hash hash of the message to sign
729 * @param bkey the blinding key
730 * @param pkey the public key of the signer
731 * @param[out] buf set to a buffer with the blinded message to be signed
732 * @param[out] buf_size number of bytes stored in @a buf
733 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
736 GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
737 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
738 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
739 char **buf, size_t *buf_size)
741 struct RsaBlindingKey *bkey;
748 BENCHMARK_START (rsa_blind);
750 GNUNET_assert (buf != NULL && buf_size != NULL);
751 ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
753 ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
762 data = rsa_full_domain_hash (pkey, hash);
764 goto rsa_gcd_validate_failure;
766 bkey = rsa_blinding_key_derive (pkey, bks);
768 gcry_mpi_release (data);
769 goto rsa_gcd_validate_failure;
772 r_e = gcry_mpi_new (0);
777 data_r_e = gcry_mpi_new (0);
778 gcry_mpi_mulm (data_r_e,
782 gcry_mpi_release (data);
783 gcry_mpi_release (ne[0]);
784 gcry_mpi_release (ne[1]);
785 gcry_mpi_release (r_e);
786 rsa_blinding_key_free (bkey);
788 *buf_size = numeric_mpi_alloc_n_print (data_r_e, buf);
789 gcry_mpi_release (data_r_e);
791 BENCHMARK_END (rsa_blind);
795 rsa_gcd_validate_failure:
796 /* We know the RSA key is malicious here, so warn the wallet. */
797 /* GNUNET_break_op (0); */
798 gcry_mpi_release (ne[0]);
799 gcry_mpi_release (ne[1]);
807 * Convert an MPI to an S-expression suitable for signature operations.
809 * @param value pointer to the data to convert
810 * @return converted s-expression
813 mpi_to_sexp (gcry_mpi_t value)
815 gcry_sexp_t data = NULL;
818 gcry_sexp_build (&data,
820 "(data (flags raw) (value %M))",
827 * Sign the given MPI.
829 * @param key private key to use for the signing
830 * @param value the MPI to sign
831 * @return NULL on error, signature on success
833 static struct GNUNET_CRYPTO_RsaSignature *
834 rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
837 struct GNUNET_CRYPTO_RsaSignature *sig;
842 data = mpi_to_sexp (value);
845 (rc = gcry_pk_sign (&result,
849 LOG (GNUNET_ERROR_TYPE_WARNING,
850 _("RSA signing failed at %s:%d: %s\n"),
858 /* Lenstra protection was first added to libgcrypt 1.6.4
859 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
861 #if GCRYPT_VERSION_NUMBER < 0x010604
862 /* verify signature (guards against Lenstra's attack with fault injection...) */
863 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public (key);
865 gcry_pk_verify (result,
870 GNUNET_CRYPTO_rsa_public_key_free (public_key);
871 gcry_sexp_release (data);
872 gcry_sexp_release (result);
875 GNUNET_CRYPTO_rsa_public_key_free (public_key);
878 /* return signature */
879 gcry_sexp_release (data);
880 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
887 * Sign a blinded value, which must be a full domain hash of a message.
889 * @param key private key to use for the signing
890 * @param msg the message to sign
891 * @param msg_len number of bytes in @a msg to sign
892 * @return NULL on error, signature on success
894 struct GNUNET_CRYPTO_RsaSignature *
895 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
900 struct GNUNET_CRYPTO_RsaSignature *sig;
902 BENCHMARK_START (rsa_sign_blinded);
911 sig = rsa_sign_mpi (key, v);
912 gcry_mpi_release (v);
913 BENCHMARK_END (rsa_sign_blinded);
919 * Create and sign a full domain hash of a message.
921 * @param key private key to use for the signing
922 * @param hash the hash of the message to sign
923 * @return NULL on error, including a malicious RSA key, signature on success
925 struct GNUNET_CRYPTO_RsaSignature *
926 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
927 const struct GNUNET_HashCode *hash)
929 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
931 struct GNUNET_CRYPTO_RsaSignature *sig;
933 pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
934 v = rsa_full_domain_hash (pkey, hash);
935 GNUNET_CRYPTO_rsa_public_key_free (pkey);
936 if (NULL == v) /* rsa_gcd_validate failed meaning */
937 return NULL; /* our *own* RSA key is malicious. */
939 sig = rsa_sign_mpi (key, v);
940 gcry_mpi_release (v);
946 * Free memory occupied by signature.
948 * @param sig memory to freee
951 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig)
953 gcry_sexp_release (sig->sexp);
959 * Encode the given signature in a format suitable for storing it into a file.
961 * @param sig the signature
962 * @param[out] buffer set to a buffer with the encoded key
963 * @return size of memory allocated in @a buffer
966 GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_RsaSignature *sig,
972 n = gcry_sexp_sprint (sig->sexp,
973 GCRYSEXP_FMT_ADVANCED,
976 b = GNUNET_malloc (n);
977 GNUNET_assert ((n - 1) == /* since the last byte is \0 */
978 gcry_sexp_sprint (sig->sexp,
979 GCRYSEXP_FMT_ADVANCED,
988 * Decode the signature from the data-format back to the "normal", internal
991 * @param buf the buffer where the public key data is stored
992 * @param len the length of the data in @a buf
993 * @return NULL on error
995 struct GNUNET_CRYPTO_RsaSignature *
996 GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
999 struct GNUNET_CRYPTO_RsaSignature *sig;
1003 sig = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1005 gcry_sexp_new (&sig->sexp,
1010 GNUNET_break_op (0);
1014 /* verify that this is an RSA signature */
1015 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1017 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1020 /* this is no RSA Signature */
1021 GNUNET_break_op (0);
1022 gcry_sexp_release (sig->sexp);
1026 gcry_mpi_release (s);
1032 * Duplicate the given public key
1034 * @param key the public key to duplicate
1035 * @return the duplicate key; NULL upon error
1037 struct GNUNET_CRYPTO_RsaPublicKey *
1038 GNUNET_CRYPTO_rsa_public_key_dup (const struct GNUNET_CRYPTO_RsaPublicKey *key)
1040 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1041 gcry_sexp_t dup_sexp;
1044 /* check if we really are exporting a public key */
1045 dup_sexp = gcry_sexp_find_token (key->sexp, "public-key", 0);
1046 GNUNET_assert (NULL != dup_sexp);
1047 gcry_sexp_release (dup_sexp);
1049 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1050 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPublicKey);
1051 dup->sexp = dup_sexp;
1057 * Unblind a blind-signed signature. The signature should have been generated
1058 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1059 * #GNUNET_CRYPTO_rsa_blind().
1061 * @param sig the signature made on the blinded signature purpose
1062 * @param bks the blinding key secret used to blind the signature purpose
1063 * @param pkey the public key of the signer
1064 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1066 struct GNUNET_CRYPTO_RsaSignature *
1067 GNUNET_CRYPTO_rsa_unblind (const struct GNUNET_CRYPTO_RsaSignature *sig,
1068 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1069 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1071 struct RsaBlindingKey *bkey;
1077 struct GNUNET_CRYPTO_RsaSignature *sret;
1079 BENCHMARK_START (rsa_unblind);
1081 ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
1083 ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
1086 GNUNET_break_op (0);
1089 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1091 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1094 gcry_mpi_release (n);
1095 GNUNET_break_op (0);
1099 bkey = rsa_blinding_key_derive (pkey, bks);
1102 /* RSA key is malicious since rsa_gcd_validate failed here.
1103 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1104 * so the exchange is being malicious in an unfamilair way, maybe
1105 * just trying to crash us. */
1106 GNUNET_break_op (0);
1107 gcry_mpi_release (n);
1108 gcry_mpi_release (s);
1112 r_inv = gcry_mpi_new (0);
1114 gcry_mpi_invm (r_inv,
1118 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1119 * caught above, but we handle it the same here. */
1120 GNUNET_break_op (0);
1121 gcry_mpi_release (r_inv);
1122 rsa_blinding_key_free (bkey);
1123 gcry_mpi_release (n);
1124 gcry_mpi_release (s);
1128 ubsig = gcry_mpi_new (0);
1129 gcry_mpi_mulm (ubsig, s, r_inv, n);
1130 gcry_mpi_release (n);
1131 gcry_mpi_release (r_inv);
1132 gcry_mpi_release (s);
1133 rsa_blinding_key_free (bkey);
1135 sret = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1137 gcry_sexp_build (&sret->sexp,
1139 "(sig-val (rsa (s %M)))",
1141 gcry_mpi_release (ubsig);
1142 BENCHMARK_END (rsa_unblind);
1148 * Verify whether the given hash corresponds to the given signature and
1149 * the signature is valid with respect to the given public key.
1151 * @param hash hash of the message to verify to match the @a sig
1152 * @param sig signature that is being validated
1153 * @param pkey public key of the signer
1154 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1157 GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
1158 const struct GNUNET_CRYPTO_RsaSignature *sig,
1159 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1165 BENCHMARK_START (rsa_verify);
1167 r = rsa_full_domain_hash (pkey, hash);
1169 GNUNET_break_op (0);
1170 /* RSA key is malicious since rsa_gcd_validate failed here.
1171 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1172 * so the exchange is being malicious in an unfamilair way, maybe
1173 * just trying to crash us. Arguably, we've only an internal error
1174 * though because we should've detected this in our previous call
1175 * to GNUNET_CRYPTO_rsa_unblind. */
1179 data = mpi_to_sexp(r);
1180 gcry_mpi_release (r);
1182 rc = gcry_pk_verify (sig->sexp,
1185 gcry_sexp_release (data);
1188 LOG (GNUNET_ERROR_TYPE_WARNING,
1189 _("RSA signature verification failed at %s:%d: %s\n"),
1192 gcry_strerror (rc));
1193 return GNUNET_SYSERR;
1194 BENCHMARK_END (rsa_verify);
1196 BENCHMARK_END (rsa_verify);
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_RsaPrivateKey *
1208 GNUNET_CRYPTO_rsa_private_key_dup (const struct GNUNET_CRYPTO_RsaPrivateKey *key)
1210 struct GNUNET_CRYPTO_RsaPrivateKey *dup;
1211 gcry_sexp_t dup_sexp;
1214 /* check if we really are exporting a private key */
1215 dup_sexp = gcry_sexp_find_token (key->sexp, "private-key", 0);
1216 GNUNET_assert (NULL != dup_sexp);
1217 gcry_sexp_release (dup_sexp);
1219 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", key->sexp));
1220 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaPrivateKey);
1221 dup->sexp = dup_sexp;
1227 * Duplicate the given private key
1229 * @param key the private key to duplicate
1230 * @return the duplicate key; NULL upon error
1232 struct GNUNET_CRYPTO_RsaSignature *
1233 GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig)
1235 struct GNUNET_CRYPTO_RsaSignature *dup;
1236 gcry_sexp_t dup_sexp;
1241 /* verify that this is an RSA signature */
1242 ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
1244 ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
1245 GNUNET_assert (0 == ret);
1246 gcry_mpi_release (s);
1248 GNUNET_assert (0 == gcry_sexp_build (&dup_sexp, &erroff, "%S", sig->sexp));
1249 dup = GNUNET_new (struct GNUNET_CRYPTO_RsaSignature);
1250 dup->sexp = dup_sexp;
1255 /* end of util/rsa.c */