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 {
41 * Libgcrypt S-expression for the RSA private key.
48 * The public information of an RSA key pair.
50 struct GNUNET_CRYPTO_RsaPublicKey {
52 * Libgcrypt S-expression for the RSA public key.
59 * @brief an RSA signature
61 struct GNUNET_CRYPTO_RsaSignature {
63 * Libgcrypt S-expression for the RSA signature.
70 * @brief RSA blinding key
72 struct RsaBlindingKey {
74 * Random value used for blinding.
81 * Extract values from an S-expression.
83 * @param array where to store the result(s)
84 * @param sexp S-expression to parse
85 * @param topname top-level name in the S-expression that is of interest
86 * @param elems names of the elements to extract
87 * @return 0 on success
90 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 (unsigned int i = 0; i < idx; 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 (unsigned int i = 0; i < idx; 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;
151 BENCHMARK_START(rsa_private_key_create);
154 gcry_sexp_build(&s_keyparam,
156 "(genkey(rsa(nbits %d)))",
159 gcry_pk_genkey(&s_key,
161 gcry_sexp_release(s_keyparam);
164 gcry_pk_testkey(s_key));
166 ret = GNUNET_new(struct GNUNET_CRYPTO_RsaPrivateKey);
168 BENCHMARK_END(rsa_private_key_create);
174 * Free memory occupied by the private key.
176 * @param key pointer to the memory to free
179 GNUNET_CRYPTO_rsa_private_key_free(struct GNUNET_CRYPTO_RsaPrivateKey *key)
181 gcry_sexp_release(key->sexp);
187 * Encode the private key in a format suitable for
188 * storing it into a file.
190 * @param key the private key
191 * @param[out] buffer set to a buffer with the encoded key
192 * @return size of memory allocated in @a buffer
195 GNUNET_CRYPTO_rsa_private_key_encode(const struct GNUNET_CRYPTO_RsaPrivateKey *key,
201 n = gcry_sexp_sprint(key->sexp,
202 GCRYSEXP_FMT_DEFAULT,
205 b = GNUNET_malloc(n);
206 GNUNET_assert((n - 1) == /* since the last byte is \0 */
207 gcry_sexp_sprint(key->sexp,
208 GCRYSEXP_FMT_DEFAULT,
217 * Decode the private key from the data-format back
218 * to the "normal", internal format.
220 * @param buf the buffer where the private key data is stored
221 * @param len the length of the data in @a buf
222 * @return NULL on error
224 struct GNUNET_CRYPTO_RsaPrivateKey *
225 GNUNET_CRYPTO_rsa_private_key_decode(const char *buf,
228 struct GNUNET_CRYPTO_RsaPrivateKey *key;
230 key = GNUNET_new(struct GNUNET_CRYPTO_RsaPrivateKey);
232 gcry_sexp_new(&key->sexp,
237 LOG(GNUNET_ERROR_TYPE_WARNING,
238 "Decoded private key is not valid\n");
242 if (0 != gcry_pk_testkey(key->sexp))
244 LOG(GNUNET_ERROR_TYPE_WARNING,
245 "Decoded private key is not valid\n");
246 GNUNET_CRYPTO_rsa_private_key_free(key);
254 * Extract the public key of the given private key.
256 * @param priv the private key
257 * @retur NULL on error, otherwise the public key
259 struct GNUNET_CRYPTO_RsaPublicKey *
260 GNUNET_CRYPTO_rsa_private_key_get_public(const struct GNUNET_CRYPTO_RsaPrivateKey *priv)
262 struct GNUNET_CRYPTO_RsaPublicKey *pub;
267 BENCHMARK_START(rsa_private_key_get_public);
269 rc = key_from_sexp(ne, priv->sexp, "public-key", "ne");
271 rc = key_from_sexp(ne, priv->sexp, "private-key", "ne");
273 rc = key_from_sexp(ne, priv->sexp, "rsa", "ne");
279 rc = gcry_sexp_build(&result,
281 "(public-key(rsa(n %m)(e %m)))",
284 gcry_mpi_release(ne[0]);
285 gcry_mpi_release(ne[1]);
286 pub = GNUNET_new(struct GNUNET_CRYPTO_RsaPublicKey);
288 BENCHMARK_END(rsa_private_key_get_public);
294 * Free memory occupied by the public key.
296 * @param key pointer to the memory to free
299 GNUNET_CRYPTO_rsa_public_key_free(struct GNUNET_CRYPTO_RsaPublicKey *key)
301 gcry_sexp_release(key->sexp);
307 * Encode the public key in a format suitable for
308 * storing it into a file.
310 * @param key the private key
311 * @param[out] buffer set to a buffer with the encoded key
312 * @return size of memory allocated in @a buffer
315 GNUNET_CRYPTO_rsa_public_key_encode(const struct GNUNET_CRYPTO_RsaPublicKey *key,
321 n = gcry_sexp_sprint(key->sexp,
322 GCRYSEXP_FMT_ADVANCED,
325 b = GNUNET_malloc(n);
326 GNUNET_assert((n - 1) == /* since the last byte is \0 */
327 gcry_sexp_sprint(key->sexp,
328 GCRYSEXP_FMT_ADVANCED,
337 * Compute hash over the public key.
339 * @param key public key to hash
340 * @param hc where to store the hash code
343 GNUNET_CRYPTO_rsa_public_key_hash(const struct GNUNET_CRYPTO_RsaPublicKey *key,
344 struct GNUNET_HashCode *hc)
349 buf_size = GNUNET_CRYPTO_rsa_public_key_encode(key,
351 GNUNET_CRYPTO_hash(buf,
359 * Decode the public key from the data-format back
360 * to the "normal", internal format.
362 * @param buf the buffer where the public key data is stored
363 * @param len the length of the data in @a buf
364 * @return NULL on error
366 struct GNUNET_CRYPTO_RsaPublicKey *
367 GNUNET_CRYPTO_rsa_public_key_decode(const char *buf,
370 struct GNUNET_CRYPTO_RsaPublicKey *key;
374 key = GNUNET_new(struct GNUNET_CRYPTO_RsaPublicKey);
376 gcry_sexp_new(&key->sexp,
385 /* verify that this is an RSA public key */
386 ret = key_from_sexp(&n, key->sexp, "public-key", "n");
388 ret = key_from_sexp(&n, key->sexp, "rsa", "n");
391 /* this is no public RSA key */
393 gcry_sexp_release(key->sexp);
403 * Test for malicious RSA key.
405 * Assuming n is an RSA modulous and r is generated using a call to
406 * GNUNET_CRYPTO_kdf_mod_mpi, if gcd(r,n) != 1 then n must be a
407 * malicious RSA key designed to deanomize the user.
409 * @param r KDF result
410 * @param n RSA modulus
411 * @return True if gcd(r,n) = 1, False means RSA key is malicious
414 rsa_gcd_validate(gcry_mpi_t r, gcry_mpi_t n)
420 t = gcry_mpi_gcd(g, r, n);
427 * Create a blinding key
429 * @param len length of the key in bits (i.e. 2048)
430 * @param bks pre-secret to use to derive the blinding key
431 * @return the newly created blinding key, NULL if RSA key is malicious
433 static struct RsaBlindingKey *
434 rsa_blinding_key_derive(const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
435 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks)
437 char *xts = "Blinding KDF extrator HMAC key"; /* Trusts bks' randomness more */
438 struct RsaBlindingKey *blind;
441 blind = GNUNET_new(struct RsaBlindingKey);
442 GNUNET_assert(NULL != blind);
444 /* Extract the composite n from the RSA public key */
445 GNUNET_assert(0 == key_from_sexp(&n, pkey->sexp, "rsa", "n"));
446 /* Assert that it at least looks like an RSA key */
447 GNUNET_assert(0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE));
449 GNUNET_CRYPTO_kdf_mod_mpi(&blind->r,
454 if (0 == rsa_gcd_validate(blind->r, n))
466 We originally added GNUNET_CRYPTO_kdf_mod_mpi for the benifit of the
469 There was previously a call to GNUNET_CRYPTO_kdf in
470 bkey = rsa_blinding_key_derive (len, bks);
471 that gives exactly len bits where
472 len = GNUNET_CRYPTO_rsa_public_key_len (pkey);
474 Now r = 2^(len-1)/pkey.n is the probability that a set high bit being
475 okay, meaning bkey < pkey.n. It follows that (1-r)/2 of the time bkey >
476 pkey.n making the effective bkey be
477 bkey mod pkey.n = bkey - pkey.n
478 so the effective bkey has its high bit set with probability r/2.
480 We expect r to be close to 1/2 if the exchange is honest, but the
481 exchange can choose r otherwise.
483 In blind signing, the exchange sees
484 B = bkey * S mod pkey.n
485 On deposit, the exchange sees S so they can compute bkey' = B/S mod
486 pkey.n for all B they recorded to see if bkey' has it's high bit set.
487 Also, note the exchange can compute 1/S efficiently since they know the
490 I suppose that happens with probability r/(1+r) if its the wrong B, not
491 completely sure. If otoh we've the right B, then we've the probability
492 r/2 of a set high bit in the effective bkey.
494 Interestingly, r^2-r has a maximum at the default r=1/2 anyways, giving
495 the wrong and right probabilities 1/3 and 1/4, respectively.
497 I feared this gives the exchange a meaningful fraction of a bit of
498 information per coin involved in the transaction. It sounds damaging if
499 numerous coins were involved. And it could run across transactions in
502 We fixed this by using a more uniform deterministic pseudo-random number
503 generator for blinding factors. I do not believe this to be a problem
504 for the rsa_full_domain_hash routine, but better safe than sorry.
509 * Compare the values of two signatures.
511 * @param s1 one signature
512 * @param s2 the other signature
513 * @return 0 if the two are equal
516 GNUNET_CRYPTO_rsa_signature_cmp(struct GNUNET_CRYPTO_RsaSignature *s1,
517 struct GNUNET_CRYPTO_RsaSignature *s2)
525 z1 = GNUNET_CRYPTO_rsa_signature_encode(s1,
527 z2 = GNUNET_CRYPTO_rsa_signature_encode(s2,
542 * Compare the values of two public keys.
544 * @param p1 one public key
545 * @param p2 the other public key
546 * @return 0 if the two are equal
549 GNUNET_CRYPTO_rsa_public_key_cmp(struct GNUNET_CRYPTO_RsaPublicKey *p1,
550 struct GNUNET_CRYPTO_RsaPublicKey *p2)
558 z1 = GNUNET_CRYPTO_rsa_public_key_encode(p1,
560 z2 = GNUNET_CRYPTO_rsa_public_key_encode(p2,
575 * Compare the values of two private keys.
577 * @param p1 one private key
578 * @param p2 the other private key
579 * @return 0 if the two are equal
582 GNUNET_CRYPTO_rsa_private_key_cmp(struct GNUNET_CRYPTO_RsaPrivateKey *p1,
583 struct GNUNET_CRYPTO_RsaPrivateKey *p2)
591 z1 = GNUNET_CRYPTO_rsa_private_key_encode(p1,
593 z2 = GNUNET_CRYPTO_rsa_private_key_encode(p2,
608 * Obtain the length of the RSA key in bits.
610 * @param key the public key to introspect
611 * @return length of the key in bits
614 GNUNET_CRYPTO_rsa_public_key_len(const struct GNUNET_CRYPTO_RsaPublicKey *key)
619 if (0 != key_from_sexp(&n, key->sexp, "rsa", "n"))
620 { /* Not an RSA public key */
624 rval = gcry_mpi_get_nbits(n);
631 * Destroy a blinding key
633 * @param bkey the blinding key to destroy
636 rsa_blinding_key_free(struct RsaBlindingKey *bkey)
638 gcry_mpi_release(bkey->r);
644 * Print an MPI to a newly created buffer
646 * @param v MPI to print.
647 * @param[out] newly allocated buffer containing the result
648 * @return number of bytes stored in @a buffer
651 numeric_mpi_alloc_n_print(gcry_mpi_t v,
658 gcry_mpi_print(GCRYMPI_FMT_USG,
663 b = GNUNET_malloc(n);
665 gcry_mpi_print(GCRYMPI_FMT_USG,
676 * Computes a full domain hash seeded by the given public key.
677 * This gives a measure of provable security to the Taler exchange
678 * against one-more forgery attacks. See:
679 * https://eprint.iacr.org/2001/002.pdf
680 * http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
682 * @param hash initial hash of the message to sign
683 * @param pkey the public key of the signer
684 * @param rsize If not NULL, the number of bytes actually stored in buffer
685 * @return MPI value set to the FDH, NULL if RSA key is malicious
688 rsa_full_domain_hash(const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
689 const struct GNUNET_HashCode *hash)
696 /* Extract the composite n from the RSA public key */
697 GNUNET_assert(0 == key_from_sexp(&n, pkey->sexp, "rsa", "n"));
698 /* Assert that it at least looks like an RSA key */
699 GNUNET_assert(0 == gcry_mpi_get_flag(n, GCRYMPI_FLAG_OPAQUE));
701 /* We key with the public denomination key as a homage to RSA-PSS by *
702 * Mihir Bellare and Phillip Rogaway. Doing this lowers the degree *
703 * of the hypothetical polyomial-time attack on RSA-KTI created by a *
704 * polynomial-time one-more forgary attack. Yey seeding! */
705 xts_len = GNUNET_CRYPTO_rsa_public_key_encode(pkey, &xts);
707 GNUNET_CRYPTO_kdf_mod_mpi(&r,
714 ok = rsa_gcd_validate(r, n);
724 * Blinds the given message with the given blinding key
726 * @param hash hash of the message to sign
727 * @param bkey the blinding key
728 * @param pkey the public key of the signer
729 * @param[out] buf set to a buffer with the blinded message to be signed
730 * @param[out] buf_size number of bytes stored in @a buf
731 * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
734 GNUNET_CRYPTO_rsa_blind(const struct GNUNET_HashCode *hash,
735 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
736 struct GNUNET_CRYPTO_RsaPublicKey *pkey,
737 char **buf, size_t *buf_size)
739 struct RsaBlindingKey *bkey;
746 BENCHMARK_START(rsa_blind);
748 GNUNET_assert(buf != NULL && buf_size != NULL);
749 ret = key_from_sexp(ne, pkey->sexp, "public-key", "ne");
751 ret = key_from_sexp(ne, pkey->sexp, "rsa", "ne");
760 data = rsa_full_domain_hash(pkey, hash);
762 goto rsa_gcd_validate_failure;
764 bkey = rsa_blinding_key_derive(pkey, bks);
767 gcry_mpi_release(data);
768 goto rsa_gcd_validate_failure;
771 r_e = gcry_mpi_new(0);
776 data_r_e = gcry_mpi_new(0);
777 gcry_mpi_mulm(data_r_e,
781 gcry_mpi_release(data);
782 gcry_mpi_release(ne[0]);
783 gcry_mpi_release(ne[1]);
784 gcry_mpi_release(r_e);
785 rsa_blinding_key_free(bkey);
787 *buf_size = numeric_mpi_alloc_n_print(data_r_e, buf);
788 gcry_mpi_release(data_r_e);
790 BENCHMARK_END(rsa_blind);
794 rsa_gcd_validate_failure:
795 /* We know the RSA key is malicious here, so warn the wallet. */
796 /* GNUNET_break_op (0); */
797 gcry_mpi_release(ne[0]);
798 gcry_mpi_release(ne[1]);
806 * Convert an MPI to an S-expression suitable for signature operations.
808 * @param value pointer to the data to convert
809 * @return converted s-expression
812 mpi_to_sexp(gcry_mpi_t value)
814 gcry_sexp_t data = NULL;
817 gcry_sexp_build(&data,
819 "(data (flags raw) (value %M))",
826 * Sign the given MPI.
828 * @param key private key to use for the signing
829 * @param value the MPI to sign
830 * @return NULL on error, signature on success
832 static struct GNUNET_CRYPTO_RsaSignature *
833 rsa_sign_mpi(const struct GNUNET_CRYPTO_RsaPrivateKey *key,
836 struct GNUNET_CRYPTO_RsaSignature *sig;
841 data = mpi_to_sexp(value);
844 (rc = gcry_pk_sign(&result,
848 LOG(GNUNET_ERROR_TYPE_WARNING,
849 _("RSA signing failed at %s:%d: %s\n"),
857 /* Lenstra protection was first added to libgcrypt 1.6.4
858 * with commit c17f84bd02d7ee93845e92e20f6ddba814961588.
860 #if GCRYPT_VERSION_NUMBER < 0x010604
861 /* verify signature (guards against Lenstra's attack with fault injection...) */
862 struct GNUNET_CRYPTO_RsaPublicKey *public_key = GNUNET_CRYPTO_rsa_private_key_get_public(key);
864 gcry_pk_verify(result,
869 GNUNET_CRYPTO_rsa_public_key_free(public_key);
870 gcry_sexp_release(data);
871 gcry_sexp_release(result);
874 GNUNET_CRYPTO_rsa_public_key_free(public_key);
877 /* return signature */
878 gcry_sexp_release(data);
879 sig = GNUNET_new(struct GNUNET_CRYPTO_RsaSignature);
886 * Sign a blinded value, which must be a full domain hash of a message.
888 * @param key private key to use for the signing
889 * @param msg the message to sign
890 * @param msg_len number of bytes in @a msg to sign
891 * @return NULL on error, signature on success
893 struct GNUNET_CRYPTO_RsaSignature *
894 GNUNET_CRYPTO_rsa_sign_blinded(const struct GNUNET_CRYPTO_RsaPrivateKey *key,
899 struct GNUNET_CRYPTO_RsaSignature *sig;
901 BENCHMARK_START(rsa_sign_blinded);
910 sig = rsa_sign_mpi(key, v);
912 BENCHMARK_END(rsa_sign_blinded);
918 * Create and sign a full domain hash of a message.
920 * @param key private key to use for the signing
921 * @param hash the hash of the message to sign
922 * @return NULL on error, including a malicious RSA key, signature on success
924 struct GNUNET_CRYPTO_RsaSignature *
925 GNUNET_CRYPTO_rsa_sign_fdh(const struct GNUNET_CRYPTO_RsaPrivateKey *key,
926 const struct GNUNET_HashCode *hash)
928 struct GNUNET_CRYPTO_RsaPublicKey *pkey;
930 struct GNUNET_CRYPTO_RsaSignature *sig;
932 pkey = GNUNET_CRYPTO_rsa_private_key_get_public(key);
933 v = rsa_full_domain_hash(pkey, hash);
934 GNUNET_CRYPTO_rsa_public_key_free(pkey);
935 if (NULL == v) /* rsa_gcd_validate failed meaning */
936 return NULL; /* our *own* RSA key is malicious. */
938 sig = rsa_sign_mpi(key, v);
945 * Free memory occupied by signature.
947 * @param sig memory to freee
950 GNUNET_CRYPTO_rsa_signature_free(struct GNUNET_CRYPTO_RsaSignature *sig)
952 gcry_sexp_release(sig->sexp);
958 * Encode the given signature in a format suitable for storing it into a file.
960 * @param sig the signature
961 * @param[out] buffer set to a buffer with the encoded key
962 * @return size of memory allocated in @a buffer
965 GNUNET_CRYPTO_rsa_signature_encode(const struct GNUNET_CRYPTO_RsaSignature *sig,
971 n = gcry_sexp_sprint(sig->sexp,
972 GCRYSEXP_FMT_ADVANCED,
975 b = GNUNET_malloc(n);
976 GNUNET_assert((n - 1) == /* since the last byte is \0 */
977 gcry_sexp_sprint(sig->sexp,
978 GCRYSEXP_FMT_ADVANCED,
987 * Decode the signature from the data-format back to the "normal", internal
990 * @param buf the buffer where the public key data is stored
991 * @param len the length of the data in @a buf
992 * @return NULL on error
994 struct GNUNET_CRYPTO_RsaSignature *
995 GNUNET_CRYPTO_rsa_signature_decode(const char *buf,
998 struct GNUNET_CRYPTO_RsaSignature *sig;
1002 sig = GNUNET_new(struct GNUNET_CRYPTO_RsaSignature);
1004 gcry_sexp_new(&sig->sexp,
1013 /* verify that this is an RSA signature */
1014 ret = key_from_sexp(&s, sig->sexp, "sig-val", "s");
1016 ret = key_from_sexp(&s, sig->sexp, "rsa", "s");
1019 /* this is no RSA Signature */
1021 gcry_sexp_release(sig->sexp);
1025 gcry_mpi_release(s);
1031 * Duplicate the given public key
1033 * @param key the public key to duplicate
1034 * @return the duplicate key; NULL upon error
1036 struct GNUNET_CRYPTO_RsaPublicKey *
1037 GNUNET_CRYPTO_rsa_public_key_dup(const struct GNUNET_CRYPTO_RsaPublicKey *key)
1039 struct GNUNET_CRYPTO_RsaPublicKey *dup;
1040 gcry_sexp_t dup_sexp;
1043 /* check if we really are exporting a public key */
1044 dup_sexp = gcry_sexp_find_token(key->sexp, "public-key", 0);
1045 GNUNET_assert(NULL != dup_sexp);
1046 gcry_sexp_release(dup_sexp);
1048 GNUNET_assert(0 == gcry_sexp_build(&dup_sexp, &erroff, "%S", key->sexp));
1049 dup = GNUNET_new(struct GNUNET_CRYPTO_RsaPublicKey);
1050 dup->sexp = dup_sexp;
1056 * Unblind a blind-signed signature. The signature should have been generated
1057 * with #GNUNET_CRYPTO_rsa_sign() using a hash that was blinded with
1058 * #GNUNET_CRYPTO_rsa_blind().
1060 * @param sig the signature made on the blinded signature purpose
1061 * @param bks the blinding key secret used to blind the signature purpose
1062 * @param pkey the public key of the signer
1063 * @return unblinded signature on success, NULL if RSA key is bad or malicious.
1065 struct GNUNET_CRYPTO_RsaSignature *
1066 GNUNET_CRYPTO_rsa_unblind(const struct GNUNET_CRYPTO_RsaSignature *sig,
1067 const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
1068 struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1070 struct RsaBlindingKey *bkey;
1076 struct GNUNET_CRYPTO_RsaSignature *sret;
1078 BENCHMARK_START(rsa_unblind);
1080 ret = key_from_sexp(&n, pkey->sexp, "public-key", "n");
1082 ret = key_from_sexp(&n, pkey->sexp, "rsa", "n");
1088 ret = key_from_sexp(&s, sig->sexp, "sig-val", "s");
1090 ret = key_from_sexp(&s, sig->sexp, "rsa", "s");
1093 gcry_mpi_release(n);
1098 bkey = rsa_blinding_key_derive(pkey, bks);
1101 /* RSA key is malicious since rsa_gcd_validate failed here.
1102 * It should have failed during GNUNET_CRYPTO_rsa_blind too though,
1103 * so the exchange is being malicious in an unfamilair way, maybe
1104 * just trying to crash us. */
1106 gcry_mpi_release(n);
1107 gcry_mpi_release(s);
1111 r_inv = gcry_mpi_new(0);
1113 gcry_mpi_invm(r_inv,
1117 /* We cannot find r mod n, so gcd(r,n) != 1, which should get *
1118 * caught above, but we handle it the same here. */
1120 gcry_mpi_release(r_inv);
1121 rsa_blinding_key_free(bkey);
1122 gcry_mpi_release(n);
1123 gcry_mpi_release(s);
1127 ubsig = gcry_mpi_new(0);
1128 gcry_mpi_mulm(ubsig, s, r_inv, n);
1129 gcry_mpi_release(n);
1130 gcry_mpi_release(r_inv);
1131 gcry_mpi_release(s);
1132 rsa_blinding_key_free(bkey);
1134 sret = GNUNET_new(struct GNUNET_CRYPTO_RsaSignature);
1136 gcry_sexp_build(&sret->sexp,
1138 "(sig-val (rsa (s %M)))",
1140 gcry_mpi_release(ubsig);
1141 BENCHMARK_END(rsa_unblind);
1147 * Verify whether the given hash corresponds to the given signature and
1148 * the signature is valid with respect to the given public key.
1150 * @param hash hash of the message to verify to match the @a sig
1151 * @param sig signature that is being validated
1152 * @param pkey public key of the signer
1153 * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, #GNUNET_SYSERR if signature is invalid
1156 GNUNET_CRYPTO_rsa_verify(const struct GNUNET_HashCode *hash,
1157 const struct GNUNET_CRYPTO_RsaSignature *sig,
1158 const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
1164 BENCHMARK_START(rsa_verify);
1166 r = rsa_full_domain_hash(pkey, hash);
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"),
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 */