gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 01/02: add crypto_cs implementation


From: gnunet
Subject: [gnunet] 01/02: add crypto_cs implementation
Date: Tue, 07 Dec 2021 20:48:39 +0100

This is an automated email from the git hooks/post-receive script.

lucien-heuzeveldt pushed a commit to branch master
in repository gnunet.

commit 2bcdfc2f958f5fd2512103c2240f1c24c07524d7
Author: Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
AuthorDate: Mon Dec 6 22:13:35 2021 +0100

    add crypto_cs implementation
---
 src/include/gnunet_crypto_lib.h | 270 +++++++++++++++++++++++++
 src/util/Makefile.am            |   1 +
 src/util/crypto_cs.c            | 425 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 696 insertions(+)

diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index edb4bb230..9166f822b 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -392,6 +392,127 @@ struct GNUNET_CRYPTO_PaillierCiphertext
 };
 
 
+/**
+ * Curve25519 Scalar
+ */
+struct GNUNET_CRYPTO_Cs25519Scalar
+{
+  /**
+   * 32 byte scalar
+   */
+  unsigned char d[crypto_core_ed25519_SCALARBYTES];
+};
+
+
+/**
+ * Curve25519 point
+ */
+struct GNUNET_CRYPTO_Cs25519Point
+{
+  /**
+   * This is a point on the Curve25519.
+   * The x coordinate can be restored using the y coordinate
+   */
+  unsigned char y[crypto_core_ed25519_BYTES];
+};
+
+
+/**
+ * The private information of an Schnorr key pair.
+ */
+struct GNUNET_CRYPTO_CsPrivateKey
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar scalar;
+};
+
+
+/**
+ * The public information of an Schnorr key pair.
+ */
+struct GNUNET_CRYPTO_CsPublicKey
+{
+  struct GNUNET_CRYPTO_Cs25519Point point;
+};
+
+
+/**
+ * Secret used for blinding (alpha and beta).
+ */
+struct GNUNET_CRYPTO_CsBlindingSecret
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar alpha;
+  struct GNUNET_CRYPTO_Cs25519Scalar beta;
+};
+
+
+/**
+ * the private r used in the signature
+ */
+struct GNUNET_CRYPTO_CsRSecret
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar scalar;
+};
+
+
+/**
+ * the public R (derived from r) used in c
+ */
+struct GNUNET_CRYPTO_CsRPublic
+{
+  struct GNUNET_CRYPTO_Cs25519Point point;
+};
+
+
+/**
+ * Schnorr c to be signed
+ */
+struct GNUNET_CRYPTO_CsC
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar scalar;
+};
+
+
+/**
+ * s in the signature
+ */
+struct GNUNET_CRYPTO_CsS
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar scalar;
+};
+
+
+/**
+ * blinded s in the signature
+ */
+struct GNUNET_CRYPTO_CsBlindS
+{
+  struct GNUNET_CRYPTO_Cs25519Scalar scalar;
+};
+
+
+/**
+ * CS Signtature containing scalar s and point R
+ */
+struct GNUNET_CRYPTO_CsSignature
+{
+  /**
+   * Schnorr signatures are composed of a scalar s and a curve point
+   */
+  struct GNUNET_CRYPTO_CsS s_scalar;
+  struct GNUNET_CRYPTO_CsRPublic r_point;
+};
+
+
+/**
+ * Nonce
+ */
+struct GNUNET_CRYPTO_CsNonce
+{
+  /*a nonce*/
+  unsigned char nonce[256 / 8];
+};
+
+
 /* **************** Functions and Macros ************* */
 
 /**
@@ -2436,6 +2557,155 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode 
*hash,
                           const struct GNUNET_CRYPTO_RsaPublicKey *public_key);
 
 
+/**
+ * Create a new random private key.
+ *
+ * @param[out] priv where to write the fresh private key
+ */
+void
+GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey 
*priv);
+
+
+/**
+ * Extract the public key of the given private key.
+ *
+ * @param priv the private key
+ * @param[out] pub where to write the public key
+ */
+void
+GNUNET_CRYPTO_cs_private_key_get_public (const struct
+                                         GNUNET_CRYPTO_CsPrivateKey *priv,
+                                         struct GNUNET_CRYPTO_CsPublicKey 
*pub);
+
+
+/**
+ * Derive a new secret r pair r0 and r1.
+ * In original papers r is generated randomly
+ * To provide abort-idempotency, r needs to be derived but still needs to be 
UNPREDICTABLE
+ * To ensure unpredictability a new nonce should be used when a new r needs to 
be derived.
+ * Uses HKDF internally.
+ * Comment: Can be done in one HKDF shot and split output.
+ *
+ * @param nonce is a random nonce
+ * @param lts is a long-term-secret in form of a private key
+ * @param[out] r array containing derived secrets r0 and r1
+ */
+void
+GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
+                           const struct GNUNET_CRYPTO_CsPrivateKey *lts,
+                           struct GNUNET_CRYPTO_CsRSecret r[2]);
+
+
+/**
+ * Extract the public R of the given secret r.
+ *
+ * @param r_priv the private key
+ * @param[out] r_pub where to write the public key
+ */
+void
+GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
+                               struct GNUNET_CRYPTO_CsRPublic *r_pub);
+
+
+/**
+ * Derives new random blinding factors.
+ * In original papers blinding factors are generated randomly
+ * To provide abort-idempotency, blinding factors need to be derived but still 
need to be UNPREDICTABLE
+ * To ensure unpredictability a new nonce has to be used.
+ * Uses HKDF internally
+ *
+ * @param secret is secret to derive blinding factors
+ * @param secret_len secret length
+ * @param[out] bs array containing the two derived blinding secrets
+ */
+void
+GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret,
+                                          size_t secret_len,
+                                          struct GNUNET_CRYPTO_CsBlindingSecret
+                                          bs[2]);
+
+
+/**
+ * Calculate two blinded c's
+ * Comment: One would be insecure due to Wagner's algorithm solving ROS
+ *
+ * @param bs array of the two blinding factor structs each containing alpha 
and beta
+ * @param r_pub array of the two signer's nonce R
+ * @param pub the public key of the signer
+ * @param msg the message to blind in preparation for signing
+ * @param msg_len length of message msg
+ * @param[out] blinded_c array of the two blinded c's
+ * @param[out] blinded_r_pub array of the two blinded R
+ */
+void
+GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
+                                 bs[2],
+                                 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
+                                 const struct GNUNET_CRYPTO_CsPublicKey *pub,
+                                 const void *msg,
+                                 size_t msg_len,
+                                 struct GNUNET_CRYPTO_CsC blinded_c[2],
+                                 struct GNUNET_CRYPTO_CsRPublic
+                                 blinded_r_pub[2]);
+
+
+/**
+ * Sign a blinded c
+ * This function derives b from a nonce and a longterm secret
+ * In original papers b is generated randomly
+ * To provide abort-idempotency, b needs to be derived but still need to be 
UNPREDICTABLE.
+ * To ensure unpredictability a new nonce has to be used for every signature
+ * HKDF is used internally for derivation
+ * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
+ *
+ * @param priv private key to use for the signing and as LTS in HKDF
+ * @param r array of the two secret nonce from the signer
+ * @param c array of the two blinded c to sign c_b
+ * @param nonce is a random nonce
+ * @param[out] blinded_signature_scalar where to write the signature
+ * @return 0 or 1 for b (see Clause Blind Signature Scheme)
+ */
+unsigned int
+GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
+                              const struct GNUNET_CRYPTO_CsRSecret r[2],
+                              const struct GNUNET_CRYPTO_CsC c[2],
+                              const struct GNUNET_CRYPTO_CsNonce *nonce,
+                              struct GNUNET_CRYPTO_CsBlindS *
+                              blinded_signature_scalar
+                              );
+
+
+/**
+ * Unblind a blind-signed signature using a c that was blinded
+ *
+ * @param blinded_signature_scalar the signature made on the blinded c
+ * @param bs the blinding factors used in the blinding
+ * @param[out] signature_scalar where to write the unblinded signature
+ */
+void
+GNUNET_CRYPTO_cs_unblind (const struct
+                          GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
+                          const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
+                          struct GNUNET_CRYPTO_CsS *signature_scalar);
+
+
+/**
+ * Verify whether the given message corresponds to the given signature and the
+ * signature is valid with respect to the given public key.
+ *
+ * @param sig signature that is being validated
+ * @param pub public key of the signer
+ * @param msg is the message that should be signed by @a sig  (message is used 
to calculate c)
+ * @param msg_len is the message length
+ * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
+                         const struct GNUNET_CRYPTO_CsPublicKey *pub,
+                         const void *msg,
+                         size_t msg_len);
+
+
 #if 0 /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/util/Makefile.am b/src/util/Makefile.am
index d21ac5e86..771be1ee3 100644
--- a/src/util/Makefile.am
+++ b/src/util/Makefile.am
@@ -61,6 +61,7 @@ libgnunetutil_la_SOURCES = \
   container_multihashmap32.c \
   crypto_symmetric.c \
   crypto_crc.c \
+  crypto_cs.c \
   crypto_ecc.c \
   crypto_ecc_gnsrecord.c \
   $(DLOG) \
diff --git a/src/util/crypto_cs.c b/src/util/crypto_cs.c
new file mode 100644
index 000000000..5c441b669
--- /dev/null
+++ b/src/util/crypto_cs.c
@@ -0,0 +1,425 @@
+/*
+   This file is part of GNUnet
+   Copyright (C) 2014,2016,2019 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   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
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
+ */
+
+/**
+ * @file util/crypto_cs.c
+ * @brief Clause Blind Schnorr signatures using Curve25519
+ * @author Lucien Heuzeveldt <lucienclaude.heuzeveldt@students.bfh.ch>
+ * @author Gian Demarmels <gian@demarmels.org>
+ */
+#include "platform.h"
+#include "gnunet_crypto_lib.h"
+#include <sodium.h>
+#include <gcrypt.h>
+
+/**
+ * IMPLEMENTATION NOTICE:
+ *
+ * This is an implementation of the Clause Blind Schnorr Signature Scheme 
using Curve25519.
+ * Further details about the Clause Blind Schnorr Signature Scheme can be 
found here:
+ * https://eprint.iacr.org/2019/877.pdf
+ *
+ * We use libsodium wherever possible.
+ */
+
+
+/**
+ * Create a new random private key.
+ *
+ * @param[out] priv where to write the fresh private key
+ */
+void
+GNUNET_CRYPTO_cs_private_key_generate (struct GNUNET_CRYPTO_CsPrivateKey *priv)
+{
+  crypto_core_ed25519_scalar_random (priv->scalar.d);
+}
+
+
+/**
+ * Extract the public key of the given private key.
+ *
+ * @param priv the private key
+ * @param[out] pub where to write the public key
+ */
+void
+GNUNET_CRYPTO_cs_private_key_get_public (const struct
+                                         GNUNET_CRYPTO_CsPrivateKey *priv,
+                                         struct GNUNET_CRYPTO_CsPublicKey *pub)
+{
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
+                                                              priv->scalar.d));
+}
+
+
+/**
+ * maps 32 random bytes to a scalar
+ * this is necessary because libsodium expects scalar to be in the prime order 
subgroup
+ * @param[out] scalar containing 32 byte char array, is modified to be in 
prime order subgroup
+ */
+static void
+map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar *scalar)
+{
+  // perform clamping as described in RFC7748
+  scalar->d[0] &= 248;
+  scalar->d[31] &= 127;
+  scalar->d[31] |= 64;
+}
+
+
+/**
+ * Derive a new secret r pair r0 and r1.
+ * In original papers r is generated randomly
+ * To provide abort-idempotency, r needs to be derived but still needs to be 
UNPREDICTABLE
+ * To ensure unpredictability a new nonce should be used when a new r needs to 
be derived.
+ * Uses HKDF internally.
+ * Comment: Can be done in one HKDF shot and split output.
+ *
+ * @param nonce is a random nonce
+ * @param lts is a long-term-secret in form of a private key
+ * @param[out] r array containing derived secrets r0 and r1
+ */
+void
+GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
+                           const struct GNUNET_CRYPTO_CsPrivateKey *lts,
+                           struct GNUNET_CRYPTO_CsRSecret r[2])
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_hkdf (r,
+                                     sizeof (struct GNUNET_CRYPTO_CsRSecret)
+                                     * 2,
+                                     GCRY_MD_SHA512,
+                                     GCRY_MD_SHA256,
+                                     "r",
+                                     strlen ("r"),
+                                     lts,
+                                     sizeof (*lts),
+                                     nonce,
+                                     sizeof (*nonce),
+                                     NULL,
+                                     0));
+
+  map_to_scalar_subgroup (&r[0].scalar);
+  map_to_scalar_subgroup (&r[1].scalar);
+}
+
+
+/**
+ * Extract the public R of the given secret r.
+ *
+ * @param r_priv the private key
+ * @param[out] r_pub where to write the public key
+ */
+void
+GNUNET_CRYPTO_cs_r_get_public (const struct GNUNET_CRYPTO_CsRSecret *r_priv,
+                               struct GNUNET_CRYPTO_CsRPublic *r_pub)
+{
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
+                                                              
r_priv->scalar.d));
+}
+
+
+/**
+ * Derives new random blinding factors.
+ * In original papers blinding factors are generated randomly
+ * To provide abort-idempotency, blinding factors need to be derived but still 
need to be UNPREDICTABLE
+ * To ensure unpredictability a new nonce has to be used.
+ * Uses HKDF internally
+ *
+ * @param secret is secret to derive blinding factors
+ * @param secret_len secret length
+ * @param[out] bs array containing the two derived blinding secrets
+ */
+void
+GNUNET_CRYPTO_cs_blinding_secrets_derive (const void *secret,
+                                          size_t secret_len,
+                                          struct GNUNET_CRYPTO_CsBlindingSecret
+                                          bs[2])
+{
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_hkdf (bs,
+                                     sizeof (struct
+                                             GNUNET_CRYPTO_CsBlindingSecret)
+                                     * 2,
+                                     GCRY_MD_SHA512,
+                                     GCRY_MD_SHA256,
+                                     "alphabeta",
+                                     strlen ("alphabeta"),
+                                     secret,
+                                     secret_len,
+                                     NULL,
+                                     0));
+  map_to_scalar_subgroup (&bs[0].alpha);
+  map_to_scalar_subgroup (&bs[0].beta);
+  map_to_scalar_subgroup (&bs[1].alpha);
+  map_to_scalar_subgroup (&bs[1].beta);
+}
+
+
+/*
+order of subgroup required for scalars by libsodium
+2^252 + 27742317777372353535851937790883648493
+copied from 
https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/ed25519/ref10/ed25519_ref10.c
+and converted to big endian
+*/
+static const unsigned char L_BIG_ENDIAN[32] = {
+  0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xde, 0xf9, 0xde, 0xa2, 0xf7,
+  0x9c, 0xd6, 0x58, 0x12, 0x63, 0x1a, 0x5c, 0xf5, 0xd3, 0xed
+};
+
+
+/**
+ * Computes a Hash of (R', m) mapped to a Curve25519 scalar
+ *
+ * @param hash initial hash of the message to be signed
+ * @param pub denomination public key (used as salt)
+ * @param[out] c C containing scalar
+ */
+static void
+cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic *r_dash,
+                     const void *msg,
+                     size_t msg_len,
+                     const struct GNUNET_CRYPTO_CsPublicKey *pub,
+                     struct GNUNET_CRYPTO_CsC *c)
+{
+  // SHA-512 hash of R' and message
+  size_t r_m_concat_len = sizeof(struct GNUNET_CRYPTO_CsRPublic) + msg_len;
+  char r_m_concat[r_m_concat_len];
+  memcpy (r_m_concat, r_dash, sizeof(struct GNUNET_CRYPTO_CsRPublic));
+  memcpy (r_m_concat + sizeof(struct GNUNET_CRYPTO_CsRPublic), msg, msg_len);
+  struct GNUNET_HashCode prehash;
+  GNUNET_CRYPTO_hash (r_m_concat, r_m_concat_len, &prehash);
+
+  // modulus converted to MPI representation
+  gcry_mpi_t l_mpi;
+  GNUNET_CRYPTO_mpi_scan_unsigned (&l_mpi, L_BIG_ENDIAN, sizeof(L_BIG_ENDIAN));
+
+  // calculate full domain hash
+  gcry_mpi_t c_mpi;
+  GNUNET_CRYPTO_kdf_mod_mpi (&c_mpi,
+                             l_mpi,
+                             pub,
+                             sizeof(struct GNUNET_CRYPTO_CsPublicKey),
+                             &prehash,
+                             sizeof(struct GNUNET_HashCode),
+                             "Curve25519FDH");
+  gcry_mpi_release (l_mpi);
+
+  // convert c from mpi
+  unsigned char c_big_endian[256 / 8];
+  GNUNET_CRYPTO_mpi_print_unsigned (c_big_endian, sizeof(c_big_endian), c_mpi);
+  gcry_mpi_release (c_mpi);
+  for (size_t i = 0; i<32; i++)
+    c->scalar.d[i] = c_big_endian[31 - i];
+}
+
+
+/**
+ * calculate R'
+ *
+ * @param bs blinding secret
+ * @param r_pub R
+ * @param pub public key
+ * @param[out] blinded_r_pub R'
+ */
+static void
+calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
+             const struct GNUNET_CRYPTO_CsRPublic *r_pub,
+             const struct GNUNET_CRYPTO_CsPublicKey *pub,
+             struct GNUNET_CRYPTO_CsRPublic *blinded_r_pub)
+{
+  // R'i = Ri + alpha i*G + beta i*pub
+  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
+                   alpha_mul_base.y,
+                   bs->alpha.d));
+  struct GNUNET_CRYPTO_Cs25519Point beta_mul_pub;
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (beta_mul_pub.y,
+                                                         bs->beta.d,
+                                                         pub->point.y));
+  struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base_plus_beta_mul_pub;
+  GNUNET_assert (0 == crypto_core_ed25519_add (
+                   alpha_mul_base_plus_beta_mul_pub.y,
+                   alpha_mul_base.y,
+                   beta_mul_pub.y));
+  GNUNET_assert (0 == crypto_core_ed25519_add (blinded_r_pub->point.y,
+                                               r_pub->point.y,
+                                               
alpha_mul_base_plus_beta_mul_pub.
+                                               y));
+}
+
+
+/**
+ * Calculate two blinded c's
+ * Comment: One would be insecure due to Wagner's algorithm solving ROS
+ *
+ * @param bs array of the two blinding factor structs each containing alpha 
and beta
+ * @param r_pub array of the two signer's nonce R
+ * @param pub the public key of the signer
+ * @param msg the message to blind in preparation for signing
+ * @param msg_len length of message msg
+ * @param[out] blinded_c array of the two blinded c's
+ * @param[out] blinded_r_pub array of the two blinded R
+ */
+void
+GNUNET_CRYPTO_cs_calc_blinded_c (const struct GNUNET_CRYPTO_CsBlindingSecret
+                                 bs[2],
+                                 const struct GNUNET_CRYPTO_CsRPublic r_pub[2],
+                                 const struct GNUNET_CRYPTO_CsPublicKey *pub,
+                                 const void *msg,
+                                 size_t msg_len,
+                                 struct GNUNET_CRYPTO_CsC blinded_c[2],
+                                 struct GNUNET_CRYPTO_CsRPublic
+                                 blinded_r_pub[2])
+{
+  // for i 0/1: R'i = Ri + alpha i*G + beta i*pub
+  calc_r_dash (&bs[0], &r_pub[0], pub, &blinded_r_pub[0]);
+  calc_r_dash (&bs[1], &r_pub[1], pub, &blinded_r_pub[1]);
+
+  // for i 0/1: c'i = H(R'i, msg)
+  struct GNUNET_CRYPTO_CsC c_dash_0;
+  struct GNUNET_CRYPTO_CsC c_dash_1;
+  cs_full_domain_hash (&blinded_r_pub[0], msg, msg_len, pub, &c_dash_0);
+  cs_full_domain_hash (&blinded_r_pub[1], msg, msg_len, pub, &c_dash_1);
+
+  // for i 0/1: ci = c'i + beta i mod p
+  crypto_core_ed25519_scalar_add (blinded_c[0].scalar.d,
+                                  c_dash_0.scalar.d,
+                                  bs[0].beta.d);
+  crypto_core_ed25519_scalar_add (blinded_c[1].scalar.d,
+                                  c_dash_1.scalar.d,
+                                  bs[1].beta.d);
+}
+
+
+/**
+ * Sign a blinded c
+ * This function derives b from a nonce and a longterm secret
+ * In original papers b is generated randomly
+ * To provide abort-idempotency, b needs to be derived but still need to be 
UNPREDICTABLE.
+ * To ensure unpredictability a new nonce has to be used for every signature
+ * HKDF is used internally for derivation
+ * r0 and r1 can be derived prior by using GNUNET_CRYPTO_cs_r_derive
+ *
+ * @param priv private key to use for the signing and as LTS in HKDF
+ * @param r array of the two secret nonce from the signer
+ * @param c array of the two blinded c to sign c_b
+ * @param nonce is a random nonce
+ * @param[out] blinded_signature_scalar where to write the signature
+ * @return 0 or 1 for b (see Clause Blind Signature Scheme)
+ */
+unsigned int
+GNUNET_CRYPTO_cs_sign_derive (const struct GNUNET_CRYPTO_CsPrivateKey *priv,
+                              const struct GNUNET_CRYPTO_CsRSecret r[2],
+                              const struct GNUNET_CRYPTO_CsC c[2],
+                              const struct GNUNET_CRYPTO_CsNonce *nonce,
+                              struct GNUNET_CRYPTO_CsBlindS *
+                              blinded_signature_scalar
+                              )
+{
+  uint32_t hkdf_out;
+
+  // derive clause session identifier b (random bit)
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CRYPTO_hkdf (&hkdf_out,
+                                     sizeof (hkdf_out),
+                                     GCRY_MD_SHA512,
+                                     GCRY_MD_SHA256,
+                                     "b",
+                                     strlen ("b"),
+                                     priv,
+                                     sizeof (*priv),
+                                     nonce,
+                                     sizeof (*nonce),
+                                     NULL,
+                                     0));
+  unsigned int b = hkdf_out % 2;
+
+  // s = r_b + c_b priv
+  struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
+  crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
+                                  c[b].scalar.d,
+                                  priv->scalar.d);
+  crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
+                                  r[b].scalar.d,
+                                  c_b_mul_priv.d);
+
+  return b;
+}
+
+
+/**
+ * Unblind a blind-signed signature using a c that was blinded
+ *
+ * @param blinded_signature_scalar the signature made on the blinded c
+ * @param bs the blinding factors used in the blinding
+ * @param[out] signature_scalar where to write the unblinded signature
+ */
+void
+GNUNET_CRYPTO_cs_unblind (const struct
+                          GNUNET_CRYPTO_CsBlindS *blinded_signature_scalar,
+                          const struct GNUNET_CRYPTO_CsBlindingSecret *bs,
+                          struct GNUNET_CRYPTO_CsS *signature_scalar)
+{
+  crypto_core_ed25519_scalar_add (signature_scalar->scalar.d,
+                                  blinded_signature_scalar->scalar.d,
+                                  bs->alpha.d);
+}
+
+
+/**
+ * Verify whether the given message corresponds to the given signature and the
+ * signature is valid with respect to the given public key.
+ *
+ * @param sig signature that is being validated
+ * @param pub public key of the signer
+ * @param msg is the message that should be signed by @a sig  (message is used 
to calculate c)
+ * @param msg_len is the message length
+ * @returns #GNUNET_YES on success, #GNUNET_SYSERR if signature invalid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_cs_verify (const struct GNUNET_CRYPTO_CsSignature *sig,
+                         const struct GNUNET_CRYPTO_CsPublicKey *pub,
+                         const void *msg,
+                         size_t msg_len)
+{
+  // calculate c' = H(R, m)
+  struct GNUNET_CRYPTO_CsC c_dash;
+  cs_full_domain_hash (&sig->r_point, msg, msg_len, pub, &c_dash);
+
+  // s'G ?= R' + c' pub
+  struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
+                   sig_scal_mul_base.y,
+                   sig->s_scalar.scalar.d));
+  struct GNUNET_CRYPTO_Cs25519Point c_dash_mul_pub;
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_dash_mul_pub.y,
+                                                         c_dash.scalar.d,
+                                                         pub->point.y));
+  struct GNUNET_CRYPTO_Cs25519Point R_add_c_dash_mul_pub;
+  GNUNET_assert (0 == crypto_core_ed25519_add (R_add_c_dash_mul_pub.y,
+                                               sig->r_point.point.y,
+                                               c_dash_mul_pub.y));
+
+  return 0 == GNUNET_memcmp (&sig_scal_mul_base,
+                             &R_add_c_dash_mul_pub)
+    ? GNUNET_OK
+    : GNUNET_SYSERR;
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]