[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] r34853 - in gnunet/src: include util
From: |
gnunet |
Subject: |
[GNUnet-SVN] r34853 - in gnunet/src: include util |
Date: |
Fri, 9 Jan 2015 16:51:57 +0100 |
Author: grothoff
Date: 2015-01-09 16:51:57 +0100 (Fri, 09 Jan 2015)
New Revision: 34853
Added:
gnunet/src/util/crypto_rsa.c
gnunet/src/util/test_crypto_rsa.c
Modified:
gnunet/src/include/gnunet_crypto_lib.h
gnunet/src/util/Makefile.am
Log:
adding support for blind signatures (modernized version of Taler logic, with
variable key length)
Modified: gnunet/src/include/gnunet_crypto_lib.h
===================================================================
--- gnunet/src/include/gnunet_crypto_lib.h 2015-01-09 11:13:56 UTC (rev
34852)
+++ gnunet/src/include/gnunet_crypto_lib.h 2015-01-09 15:51:57 UTC (rev
34853)
@@ -1392,6 +1392,263 @@
int
GNUNET_CRYPTO_paillier_hom_get_remaining (const struct
GNUNET_CRYPTO_PaillierCiphertext *c);
+
+/* ********* Chaum-style RSA-based blind signatures ******************* */
+
+
+
+
+/**
+ * The private information of an RSA key pair.
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey;
+
+/**
+ * The public information of an RSA key pair.
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey;
+
+/**
+ * Key used to blind a message
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey;
+
+/**
+ * @brief an RSA signature
+ */
+struct GNUNET_CRYPTO_rsa_Signature;
+
+
+/**
+ * Create a new private key. Caller must free return value.
+ *
+ * @param len length of the key in bits (i.e. 2048)
+ * @return fresh private key
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey *
+GNUNET_CRYPTO_rsa_private_key_create (unsigned int len);
+
+
+/**
+ * Free memory occupied by the private key.
+ *
+ * @param key pointer to the memory to free
+ */
+void
+GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_rsa_PrivateKey *key);
+
+
+/**
+ * Encode the private key in a format suitable for
+ * storing it into a file.
+ *
+ * @param key the private key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocatedin @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_private_key_encode (const struct
GNUNET_CRYPTO_rsa_PrivateKey *key,
+ char **buffer);
+
+
+/**
+ * Decode the private key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the private key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey *
+GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
+ size_t len);
+
+
+/**
+ * Extract the public key of the given private key.
+ *
+ * @param priv the private key
+ * @retur NULL on error, otherwise the public key
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey *
+GNUNET_CRYPTO_rsa_private_key_get_public (const struct
GNUNET_CRYPTO_rsa_PrivateKey *priv);
+
+
+/**
+ * Free memory occupied by the public key.
+ *
+ * @param key pointer to the memory to free
+ */
+void
+GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_rsa_PublicKey *key);
+
+
+/**
+ * Encode the public key in a format suitable for
+ * storing it into a file.
+ *
+ * @param key the private key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_rsa_PublicKey
*key,
+ char **buffer);
+
+
+/**
+ * Decode the public key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey *
+GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
+ size_t len);
+
+
+/**
+ * Create a blinding key
+ *
+ * @param len length of the key in bits (i.e. 2048)
+ * @return the newly created blinding key
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey *
+GNUNET_CRYPTO_rsa_blinding_key_create (unsigned int len);
+
+
+/**
+ * Destroy a blinding key
+ *
+ * @param bkey the blinding key to destroy
+ */
+void
+GNUNET_CRYPTO_rsa_blinding_key_free (struct GNUNET_CRYPTO_rsa_BlindingKey
*bkey);
+
+
+/**
+ * Encode the blinding key in a format suitable for
+ * storing it into a file.
+ *
+ * @param bkey the blinding key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_blinding_key_encode (const struct
GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ char **buffer);
+
+
+/**
+ * Decode the blinding key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey *
+GNUNET_CRYPTO_rsa_blinding_key_decode (const char *buf,
+ size_t len);
+
+
+/**
+ * Blinds the given message with the given blinding key
+ *
+ * @param hash hash of the message to sign
+ * @param bkey the blinding key
+ * @param pkey the public key of the signer
+ * @param[out] buffer set to a buffer with the blinded message to be signed
+ * @return number of bytes stored in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
+ char **buffer);
+
+
+/**
+ * Sign the given message.
+ *
+ * @param key private key to use for the signing
+ * @param msg the (blinded) message to sign
+ * @param msg_len number of bytes in @a msg to sign
+ * @return NULL on error, signature on success
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
+ const void *msg,
+ size_t msg_len);
+
+
+/**
+ * Free memory occupied by signature.
+ *
+ * @param sig memory to freee
+ */
+void
+GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_rsa_Signature *sig);
+
+
+/**
+ * Encode the signature key in a format suitable for
+ * storing it into a file.
+ *
+ * @param sig the signature
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_rsa_Signature
*sig,
+ char **buffer);
+
+
+/**
+ * Decode the public key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
+ size_t len);
+
+
+/**
+ * Unblind a signature made on blinding signature purpose. The signature
+ * purpose should have been generated with #GNUNET_CRYPTO_rsa_sign() using
+ * a message that was generated with #GNUNET_CRYPTO_rsa_blind().
+ *
+ * @param sig the signature made on the blinded signature purpose
+ * @param bkey the blinding key used to blind the signature purpose
+ * @param pkey the public key of the signer
+ * @return unblinded signature on success, NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_rsa_Signature *sig,
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ struct GNUNET_CRYPTO_rsa_PublicKey *pkey);
+
+
+/**
+ * Verify signature with the given hash.
+ *
+ * @param hash the message to verify to match the @a sig
+ * @param sig signature that is being validated
+ * @param public_key public key of the signer
+ * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
+ */
+int
+GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
+ const struct GNUNET_CRYPTO_rsa_Signature *sig,
+ const struct GNUNET_CRYPTO_rsa_PublicKey *public_key);
+
+
#if 0 /* keep Emacsens' auto-indent happy */
{
#endif
Modified: gnunet/src/util/Makefile.am
===================================================================
--- gnunet/src/util/Makefile.am 2015-01-09 11:13:56 UTC (rev 34852)
+++ gnunet/src/util/Makefile.am 2015-01-09 15:51:57 UTC (rev 34853)
@@ -88,6 +88,7 @@
crypto_mpi.c \
crypto_paillier.c \
crypto_random.c \
+ crypto_rsa.c \
disk.c \
disk.h \
getopt.c \
@@ -229,6 +230,7 @@
test_crypto_hkdf \
test_crypto_paillier \
test_crypto_random \
+ test_crypto_rsa \
test_disk \
test_getopt \
test_connection.nc \
@@ -404,6 +406,11 @@
test_crypto_random_LDADD = \
libgnunetutil.la
+test_crypto_rsa_SOURCES = \
+ test_crypto_rsa.c
+test_crypto_rsa_LDADD = \
+ libgnunetutil.la
+
test_disk_SOURCES = \
test_disk.c
test_disk_LDADD = \
Added: gnunet/src/util/crypto_rsa.c
===================================================================
--- gnunet/src/util/crypto_rsa.c (rev 0)
+++ gnunet/src/util/crypto_rsa.c 2015-01-09 15:51:57 UTC (rev 34853)
@@ -0,0 +1,796 @@
+/*
+ This file is part of GNUnet
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNUnet; see the file COPYING. If not, If not, see
<http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/crypto_rsa.c
+ * @brief Chaum-style Blind signatures based on RSA
+ * @author Sree Harsha Totakura <address@hidden>
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <gcrypt.h>
+#include "gnunet_util_lib.h"
+
+#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+
+
+/**
+ * The private information of an RSA key pair.
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey
+{
+ /**
+ * Libgcrypt S-expression for the RSA private key.
+ */
+ gcry_sexp_t sexp;
+};
+
+
+/**
+ * The public information of an RSA key pair.
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey
+{
+ /**
+ * Libgcrypt S-expression for the RSA public key.
+ */
+ gcry_sexp_t sexp;
+};
+
+
+/**
+ * @brief an RSA signature
+ */
+struct GNUNET_CRYPTO_rsa_Signature
+{
+ /**
+ * Libgcrypt S-expression for the RSA signature.
+ */
+ gcry_sexp_t sexp;
+};
+
+
+/**
+ * @brief RSA blinding key
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey
+{
+ /**
+ * Random value used for blinding.
+ */
+ gcry_mpi_t r;
+};
+
+
+/**
+ * Extract values from an S-expression.
+ *
+ * @param array where to store the result(s)
+ * @param sexp S-expression to parse
+ * @param topname top-level name in the S-expression that is of interest
+ * @param elems names of the elements to extract
+ * @return 0 on success
+ */
+static int
+key_from_sexp (gcry_mpi_t *array,
+ gcry_sexp_t sexp,
+ const char *topname,
+ const char *elems)
+{
+ gcry_sexp_t list;
+ gcry_sexp_t l2;
+ const char *s;
+ unsigned int i;
+ unsigned int idx;
+
+ if (! (list = gcry_sexp_find_token (sexp, topname, 0)))
+ return 1;
+ l2 = gcry_sexp_cadr (list);
+ gcry_sexp_release (list);
+ list = l2;
+ if (! list)
+ return 2;
+ idx = 0;
+ for (s = elems; *s; s++, idx++)
+ {
+ if (! (l2 = gcry_sexp_find_token (list, s, 1)))
+ {
+ for (i = 0; i < idx; i++)
+ {
+ gcry_free (array[i]);
+ array[i] = NULL;
+ }
+ gcry_sexp_release (list);
+ return 3; /* required parameter not found */
+ }
+ array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
+ gcry_sexp_release (l2);
+ if (! array[idx])
+ {
+ for (i = 0; i < idx; i++)
+ {
+ gcry_free (array[i]);
+ array[i] = NULL;
+ }
+ gcry_sexp_release (list);
+ return 4; /* required parameter is invalid */
+ }
+ }
+ gcry_sexp_release (list);
+ return 0;
+}
+
+
+/**
+ * Create a new private key. Caller must free return value.
+ *
+ * @param len length of the key in bits (i.e. 2048)
+ * @return fresh private key
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey *
+GNUNET_CRYPTO_rsa_private_key_create (unsigned int len)
+{
+ struct GNUNET_CRYPTO_rsa_PrivateKey *ret;
+ gcry_sexp_t s_key;
+ gcry_sexp_t s_keyparam;
+
+ GNUNET_assert (0 ==
+ gcry_sexp_build (&s_keyparam,
+ NULL,
+ "(genkey(rsa(nbits %d)))",
+ len));
+ GNUNET_assert (0 ==
+ gcry_pk_genkey (&s_key,
+ s_keyparam));
+ gcry_sexp_release (s_keyparam);
+#if EXTRA_CHECKS
+ GNUNET_assert (0 ==
+ gcry_pk_testkey (s_key));
+#endif
+ ret = GNUNET_new (struct GNUNET_CRYPTO_rsa_PrivateKey);
+ ret->sexp = s_key;
+ return ret;
+}
+
+
+/**
+ * Free memory occupied by the private key.
+ *
+ * @param key pointer to the memory to free
+ */
+void
+GNUNET_CRYPTO_rsa_private_key_free (struct GNUNET_CRYPTO_rsa_PrivateKey *key)
+{
+ gcry_sexp_release (key->sexp);
+ GNUNET_free (key);
+}
+
+
+/**
+ * Encode the private key in a format suitable for
+ * storing it into a file.
+ *
+ * @param key the private key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_private_key_encode (const struct
GNUNET_CRYPTO_rsa_PrivateKey *key,
+ char **buffer)
+{
+ size_t n;
+ char *b;
+
+ n = gcry_sexp_sprint (key->sexp,
+ GCRYSEXP_FMT_DEFAULT,
+ NULL,
+ 0);
+ b = GNUNET_malloc (n);
+ GNUNET_assert (n ==
+ gcry_sexp_sprint (key->sexp,
+ GCRYSEXP_FMT_DEFAULT,
+ b,
+ n));
+ *buffer = b;
+ return n;
+}
+
+
+/**
+ * Decode the private key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the private key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_PrivateKey *
+GNUNET_CRYPTO_rsa_private_key_decode (const char *buf,
+ size_t len)
+{
+ struct GNUNET_CRYPTO_rsa_PrivateKey *key;
+
+ key = GNUNET_new (struct GNUNET_CRYPTO_rsa_PrivateKey);
+ if (0 !=
+ gcry_sexp_new (&key->sexp,
+ buf,
+ len,
+ 0))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (key);
+ return NULL;
+ }
+ /* FIXME: verify that this is an RSA private key */
+ return key;
+}
+
+
+/**
+ * Extract the public key of the given private key.
+ *
+ * @param priv the private key
+ * @retur NULL on error, otherwise the public key
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey *
+GNUNET_CRYPTO_rsa_private_key_get_public (const struct
GNUNET_CRYPTO_rsa_PrivateKey *priv)
+{
+ struct GNUNET_CRYPTO_rsa_PublicKey *pub;
+ gcry_mpi_t ne[2];
+ int rc;
+ gcry_sexp_t result;
+
+ rc = key_from_sexp (ne, priv->sexp, "public-key", "ne");
+ if (0 != rc)
+ rc = key_from_sexp (ne, priv->sexp, "private-key", "ne");
+ if (0 != rc)
+ rc = key_from_sexp (ne, priv->sexp, "rsa", "ne");
+ if (0 != rc)
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ rc = gcry_sexp_build (&result,
+ NULL,
+ "(public-key(rsa(n %m)(e %m)))",
+ ne[0],
+ ne[1]);
+ gcry_mpi_release (ne[0]);
+ gcry_mpi_release (ne[1]);
+ pub = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey);
+ pub->sexp = result;
+ return pub;
+}
+
+
+/**
+ * Free memory occupied by the public key.
+ *
+ * @param key pointer to the memory to free
+ */
+void
+GNUNET_CRYPTO_rsa_public_key_free (struct GNUNET_CRYPTO_rsa_PublicKey *key)
+{
+ gcry_sexp_release (key->sexp);
+ GNUNET_free (key);
+}
+
+
+/**
+ * Encode the public key in a format suitable for
+ * storing it into a file.
+ *
+ * @param key the private key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_public_key_encode (const struct GNUNET_CRYPTO_rsa_PublicKey
*key,
+ char **buffer)
+{
+ size_t n;
+ char *b;
+
+ n = gcry_sexp_sprint (key->sexp,
+ GCRYSEXP_FMT_ADVANCED,
+ NULL,
+ 0);
+ b = GNUNET_malloc (n);
+ GNUNET_assert (n ==
+ gcry_sexp_sprint (key->sexp,
+ GCRYSEXP_FMT_ADVANCED,
+ b,
+ n));
+ *buffer = b;
+ return n;
+}
+
+
+/**
+ * Decode the public key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_PublicKey *
+GNUNET_CRYPTO_rsa_public_key_decode (const char *buf,
+ size_t len)
+{
+ struct GNUNET_CRYPTO_rsa_PublicKey *key;
+ gcry_mpi_t n;
+ int ret;
+
+ key = GNUNET_new (struct GNUNET_CRYPTO_rsa_PublicKey);
+ if (0 !=
+ gcry_sexp_new (&key->sexp,
+ buf,
+ len,
+ 0))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (key);
+ return NULL;
+ }
+ /* verify that this is an RSA public key */
+ ret = key_from_sexp (&n, key->sexp, "public-key", "n");
+ if (0 != ret)
+ ret = key_from_sexp (&n, key->sexp, "rsa", "n");
+ if (0 != ret)
+ {
+ /* this is no public RSA key */
+ GNUNET_break (0);
+ gcry_sexp_release (key->sexp);
+ GNUNET_free (key);
+ return NULL;
+ }
+ gcry_mpi_release (n);
+ return key;
+}
+
+
+/**
+ * Create a blinding key
+ *
+ * @param len length of the key in bits (i.e. 2048)
+ * @return the newly created blinding key
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey *
+GNUNET_CRYPTO_rsa_blinding_key_create (unsigned int len)
+{
+ struct GNUNET_CRYPTO_rsa_BlindingKey *blind;
+
+ blind = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
+ blind->r = gcry_mpi_new (len);
+ gcry_mpi_randomize (blind->r,
+ len,
+ GCRY_STRONG_RANDOM);
+ return blind;
+}
+
+
+/**
+ * Destroy a blinding key
+ *
+ * @param bkey the blinding key to destroy
+ */
+void
+GNUNET_CRYPTO_rsa_blinding_key_free (struct GNUNET_CRYPTO_rsa_BlindingKey
*bkey)
+{
+ gcry_mpi_release (bkey->r);
+ GNUNET_free (bkey);
+}
+
+
+/**
+ * Encode the blinding key in a format suitable for
+ * storing it into a file.
+ *
+ * @param bkey the blinding key
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_blinding_key_encode (const struct
GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ char **buffer)
+{
+ size_t n;
+ char *b;
+ size_t rsize;
+
+ gcry_mpi_print (GCRYMPI_FMT_USG,
+ NULL,
+ 0,
+ &n,
+ bkey->r);
+ b = GNUNET_malloc (n);
+ GNUNET_assert (0 ==
+ gcry_mpi_print (GCRYMPI_FMT_USG,
+ (unsigned char *) b,
+ n,
+ &rsize,
+ bkey->r));
+ *buffer = b;
+ return n;
+}
+
+
+/**
+ * Decode the blinding key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_BlindingKey *
+GNUNET_CRYPTO_rsa_blinding_key_decode (const char *buf,
+ size_t len)
+{
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
+ size_t rsize;
+
+ bkey = GNUNET_new (struct GNUNET_CRYPTO_rsa_BlindingKey);
+ if (0 !=
+ gcry_mpi_scan (&bkey->r,
+ GCRYMPI_FMT_USG,
+ (const unsigned char *) buf,
+ len,
+ &rsize))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (bkey);
+ return NULL;
+ }
+ return bkey;
+}
+
+
+/**
+ * Blinds the given message with the given blinding key
+ *
+ * @param hash hash of the message to sign
+ * @param bkey the blinding key
+ * @param pkey the public key of the signer
+ * @param[out] buffer set to a buffer with the blinded message to be signed
+ * @return number of bytes stored in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ struct GNUNET_CRYPTO_rsa_PublicKey *pkey,
+ char **buffer)
+{
+ gcry_mpi_t data;
+ gcry_mpi_t ne[2];
+ gcry_mpi_t r_e;
+ gcry_mpi_t data_r_e;
+ size_t rsize;
+ size_t n;
+ gcry_error_t rc;
+ char *b;
+ int ret;
+
+ ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
+ if (0 != ret)
+ ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
+ if (0 != ret)
+ {
+ GNUNET_break (0);
+ *buffer = NULL;
+ return 0;
+ }
+ if (0 != (rc = gcry_mpi_scan (&data,
+ GCRYMPI_FMT_USG,
+ (const unsigned char *) hash,
+ sizeof (struct GNUNET_HashCode),
+ &rsize)))
+ {
+ GNUNET_break (0);
+ gcry_mpi_release (ne[0]);
+ gcry_mpi_release (ne[1]);
+ *buffer = NULL;
+ return 0;
+ }
+ r_e = gcry_mpi_new (0);
+ gcry_mpi_powm (r_e,
+ bkey->r,
+ ne[1],
+ ne[0]);
+ data_r_e = gcry_mpi_new (0);
+ gcry_mpi_mulm (data_r_e,
+ data,
+ r_e,
+ ne[0]);
+ gcry_mpi_release (ne[0]);
+ gcry_mpi_release (ne[1]);
+ gcry_mpi_release (r_e);
+
+ gcry_mpi_print (GCRYMPI_FMT_USG,
+ NULL,
+ 0,
+ &n,
+ data_r_e);
+ b = GNUNET_malloc (n);
+ rc = gcry_mpi_print (GCRYMPI_FMT_USG,
+ (unsigned char *) b,
+ n,
+ &rsize,
+ data_r_e);
+ gcry_mpi_release (data_r_e);
+ *buffer = b;
+ return n;
+}
+
+
+/**
+ * Convert the data specified in the given purpose argument to an
+ * S-expression suitable for signature operations.
+ *
+ * @param ptr pointer to the data to convert
+ * @param size the size of the data
+ * @return converted s-expression
+ */
+static gcry_sexp_t
+data_to_sexp (const void *ptr, size_t size)
+{
+ gcry_mpi_t value;
+ gcry_sexp_t data;
+
+ value = NULL;
+ data = NULL;
+ GNUNET_assert (0 ==
+ gcry_mpi_scan (&value,
+ GCRYMPI_FMT_USG,
+ ptr,
+ size,
+ NULL));
+ GNUNET_assert (0 ==
+ gcry_sexp_build (&data,
+ NULL,
+ "(data (flags raw) (value %M))",
+ value));
+ gcry_mpi_release (value);
+ return data;
+}
+
+
+/**
+ * Sign the given message.
+ *
+ * @param key private key to use for the signing
+ * @param msg the message to sign
+ * @param msg_len number of bytes in @a msg to sign
+ * @return NULL on error, signature on success
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_sign (const struct GNUNET_CRYPTO_rsa_PrivateKey *key,
+ const void *msg,
+ size_t msg_len)
+{
+ struct GNUNET_CRYPTO_rsa_Signature *sig;
+ gcry_sexp_t result;
+ gcry_sexp_t data;
+
+ data = data_to_sexp (msg,
+ msg_len);
+ if (0 !=
+ gcry_pk_sign (&result,
+ data,
+ key->sexp))
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ gcry_sexp_release (data);
+ sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
+ sig->sexp = result;
+ return sig;
+}
+
+
+/**
+ * Free memory occupied by signature.
+ *
+ * @param sig memory to freee
+ */
+void
+GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_rsa_Signature *sig)
+{
+ gcry_sexp_release (sig->sexp);
+ GNUNET_free (sig);
+}
+
+
+/**
+ * Encode the signature key in a format suitable for
+ * storing it into a file.
+ *
+ * @param sig the signature
+ * @param[out] buffer set to a buffer with the encoded key
+ * @return size of memory allocated in @a buffer
+ */
+size_t
+GNUNET_CRYPTO_rsa_signature_encode (const struct GNUNET_CRYPTO_rsa_Signature
*sig,
+ char **buffer)
+{
+ size_t n;
+ char *b;
+
+ n = gcry_sexp_sprint (sig->sexp,
+ GCRYSEXP_FMT_ADVANCED,
+ NULL,
+ 0);
+ b = GNUNET_malloc (n);
+ GNUNET_assert (n ==
+ gcry_sexp_sprint (sig->sexp,
+ GCRYSEXP_FMT_ADVANCED,
+ b,
+ n));
+ *buffer = b;
+ return n;
+}
+
+
+/**
+ * Decode the public key from the data-format back
+ * to the "normal", internal format.
+ *
+ * @param buf the buffer where the public key data is stored
+ * @param len the length of the data in @a buf
+ * @return NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_signature_decode (const char *buf,
+ size_t len)
+{
+ struct GNUNET_CRYPTO_rsa_Signature *sig;
+ int ret;
+ gcry_mpi_t s;
+
+ sig = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
+ if (0 !=
+ gcry_sexp_new (&sig->sexp,
+ buf,
+ len,
+ 0))
+ {
+ GNUNET_break_op (0);
+ GNUNET_free (sig);
+ return NULL;
+ }
+ /* verify that this is an RSA signature */
+ ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
+ if (0 != ret)
+ ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
+ if (0 != ret)
+ {
+ /* this is no RSA Signature */
+ GNUNET_break_op (0);
+ gcry_sexp_release (sig->sexp);
+ GNUNET_free (sig);
+ return NULL;
+ }
+ gcry_mpi_release (s);
+ return sig;
+}
+
+
+/**
+ * Unblind a signature made on blinding signature purpose. The signature
+ * purpose should have been generated with #GNUNET_CRYPTO_rsa_sign() using
+ * a message that was generated with #GNUNET_CRYPTO_rsa_blind().
+ *
+ * @param sig the signature made on the blinded signature purpose
+ * @param bkey the blinding key used to blind the signature purpose
+ * @param pkey the public key of the signer
+ * @return unblinded signature on success, NULL on error
+ */
+struct GNUNET_CRYPTO_rsa_Signature *
+GNUNET_CRYPTO_rsa_unblind (struct GNUNET_CRYPTO_rsa_Signature *sig,
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey,
+ struct GNUNET_CRYPTO_rsa_PublicKey *pkey)
+{
+ gcry_mpi_t n;
+ gcry_mpi_t s;
+ gcry_mpi_t r_inv;
+ gcry_mpi_t ubsig;
+ int ret;
+ struct GNUNET_CRYPTO_rsa_Signature *sret;
+
+ ret = key_from_sexp (&n, pkey->sexp, "public-key", "n");
+ if (0 != ret)
+ ret = key_from_sexp (&n, pkey->sexp, "rsa", "n");
+ if (0 != ret)
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ ret = key_from_sexp (&s, sig->sexp, "sig-val", "s");
+ if (0 != ret)
+ ret = key_from_sexp (&s, sig->sexp, "rsa", "s");
+ if (0 != ret)
+ {
+ gcry_mpi_release (n);
+ GNUNET_break_op (0);
+ return NULL;
+ }
+ r_inv = gcry_mpi_new (0);
+ if (1 !=
+ gcry_mpi_invm (r_inv,
+ bkey->r,
+ n))
+ {
+ GNUNET_break_op (0);
+ gcry_mpi_release (n);
+ gcry_mpi_release (r_inv);
+ gcry_mpi_release (s);
+ return NULL;
+ }
+ ubsig = gcry_mpi_new (0);
+ gcry_mpi_mulm (ubsig, s, r_inv, n);
+ gcry_mpi_release (n);
+ gcry_mpi_release (r_inv);
+ gcry_mpi_release (s);
+
+ sret = GNUNET_new (struct GNUNET_CRYPTO_rsa_Signature);
+ GNUNET_assert (0 ==
+ gcry_sexp_build (&sret->sexp,
+ NULL,
+ "(sig-val (rsa (s %M)))",
+ ubsig));
+ gcry_mpi_release (ubsig);
+ return sret;
+}
+
+
+/**
+ * Verify signature with the given hash.
+ *
+ * @param hash hash of the message to verify to match the @a sig
+ * @param sig signature that is being validated
+ * @param public_key public key of the signer
+ * @returns #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
+ */
+int
+GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
+ const struct GNUNET_CRYPTO_rsa_Signature *sig,
+ const struct GNUNET_CRYPTO_rsa_PublicKey *public_key)
+{
+ gcry_sexp_t data;
+ int rc;
+
+ data = data_to_sexp (hash,
+ sizeof (struct GNUNET_HashCode));
+ rc = gcry_pk_verify (sig->sexp,
+ data,
+ public_key->sexp);
+ gcry_sexp_release (data);
+ if (0 != rc)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ _("RSA signature verification failed at %s:%d: %s\n"),
+ __FILE__,
+ __LINE__,
+ gcry_strerror (rc));
+ return GNUNET_SYSERR;
+ }
+ return GNUNET_OK;
+}
+
+
+/* end of util/rsa.c */
Added: gnunet/src/util/test_crypto_rsa.c
===================================================================
--- gnunet/src/util/test_crypto_rsa.c (rev 0)
+++ gnunet/src/util/test_crypto_rsa.c 2015-01-09 15:51:57 UTC (rev 34853)
@@ -0,0 +1,82 @@
+/*
+ This file is part of GNUnet
+ (C) 2014 Christian Grothoff (and other contributing authors)
+
+ GNUnet is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, If not, see
<http://www.gnu.org/licenses/>
+*/
+
+/**
+ * @file util/test_crypto_rsa.c
+ * @brief testcase for utility functions for RSA cryptography
+ * @author Sree Harsha Totakura <address@hidden>
+ */
+#include "platform.h"
+#include <gnunet/gnunet_util_lib.h>
+
+#define KEY_SIZE 1024
+
+
+int
+main (int argc,
+ char *argv[])
+{
+#define RND_BLK_SIZE 4096
+ unsigned char rnd_blk[RND_BLK_SIZE];
+ struct GNUNET_CRYPTO_rsa_PrivateKey *priv;
+ struct GNUNET_CRYPTO_rsa_PublicKey *pub;
+ struct GNUNET_CRYPTO_rsa_BlindingKey *bkey;
+ struct GNUNET_CRYPTO_rsa_Signature *sig;
+ struct GNUNET_CRYPTO_rsa_Signature *bsig;
+ struct GNUNET_HashCode hash;
+ char *blind_buf;
+ size_t bsize;
+
+ GNUNET_log_setup ("test-rsa", "WARNING", NULL);
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+ rnd_blk,
+ RND_BLK_SIZE);
+ GNUNET_CRYPTO_hash (rnd_blk,
+ RND_BLK_SIZE,
+ &hash);
+ priv = GNUNET_CRYPTO_rsa_private_key_create (KEY_SIZE);
+ pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
+ /* try ordinary sig first */
+ sig = GNUNET_CRYPTO_rsa_sign (priv,
+ &hash,
+ sizeof (hash));
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+
+ /* test blind signing */
+ bkey = GNUNET_CRYPTO_rsa_blinding_key_create (KEY_SIZE);
+ bsize = GNUNET_CRYPTO_rsa_blind (&hash,
+ bkey,
+ pub,
+ &blind_buf);
+ GNUNET_assert (0 != bsize);
+ bsig = GNUNET_CRYPTO_rsa_sign (priv,
+ blind_buf,
+ bsize);
+ GNUNET_free (blind_buf);
+ sig = GNUNET_CRYPTO_rsa_unblind (bsig,
+ bkey,
+ pub);
+ GNUNET_CRYPTO_rsa_signature_free (bsig);
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_CRYPTO_rsa_private_key_free (priv);
+ GNUNET_CRYPTO_rsa_public_key_free (pub);
+ GNUNET_CRYPTO_rsa_blinding_key_free (bkey);
+ return 0;
+}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [GNUnet-SVN] r34853 - in gnunet/src: include util,
gnunet <=