gnunet-svn
[Top][All Lists]
Advanced

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

[gnunet] branch master updated (23853f2d7 -> db1ea2c6e)


From: gnunet
Subject: [gnunet] branch master updated (23853f2d7 -> db1ea2c6e)
Date: Fri, 27 Oct 2023 20:08:39 +0200

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

grothoff pushed a change to branch master
in repository gnunet.

    from 23853f2d7 Merge branch 'master' of ssh://git.gnunet.org/gnunet
     new 198cc9484 NEWS: major revision of blind signature API
     new 9a9c588a6 new blind signing logic
     new d2e4ba93f distinguish blinding and session nonces
     new 7278ae87e more work on new blind signature API and implementation
     new 32af9c7db more work on new blind signing API
     new db1ea2c6e -fix memory leak

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 po/POTFILES.in                   |   1 +
 src/include/gnunet_crypto_lib.h  | 767 ++++++++++++++++++++++++++++++++++++---
 src/lib/util/Makefile.am         |  11 +-
 src/lib/util/crypto_blind_sign.c | 672 ++++++++++++++++++++++++++++++++++
 src/lib/util/crypto_cs.c         | 108 +++---
 src/lib/util/crypto_rsa.c        | 109 +++---
 src/lib/util/perf_crypto_rsa.c   |  26 +-
 src/lib/util/test_crypto_blind.c |  86 +++++
 src/lib/util/test_crypto_cs.c    | 227 ++++++------
 src/lib/util/test_crypto_rsa.c   |  74 ++--
 10 files changed, 1793 insertions(+), 288 deletions(-)
 create mode 100644 src/lib/util/crypto_blind_sign.c
 create mode 100644 src/lib/util/test_crypto_blind.c

diff --git a/po/POTFILES.in b/po/POTFILES.in
index a1471f455..5ffe64202 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -156,6 +156,7 @@ src/lib/util/container_multihashmap32.c
 src/lib/util/container_multipeermap.c
 src/lib/util/container_multishortmap.c
 src/lib/util/container_multiuuidmap.c
+src/lib/util/crypto_blind_sign.c
 src/lib/util/crypto_crc.c
 src/lib/util/crypto_cs.c
 src/lib/util/crypto_ecc.c
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index f3ea3ed25..44db5f466 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -660,17 +660,33 @@ struct GNUNET_CRYPTO_CsSignature
    * Schnorr signatures are composed of a scalar s and a curve point
    */
   struct GNUNET_CRYPTO_CsS s_scalar;
+
+  /**
+   * Curve point of the Schnorr signature.
+   */
   struct GNUNET_CRYPTO_CsRPublic r_point;
 };
 
 
 /**
- * Nonce
+ * Nonce for the session, picked by client,
+ * shared with the signer.
+ */
+struct GNUNET_CRYPTO_CsSessionNonce
+{
+  /*a nonce*/
+  unsigned char snonce[256 / 8];
+};
+
+
+/**
+ * Nonce for computing blinding factors. Not
+ * shared with the signer.
  */
-struct GNUNET_CRYPTO_CsNonce
+struct GNUNET_CRYPTO_CsBlindingNonce
 {
   /*a nonce*/
-  unsigned char nonce[256 / 8];
+  unsigned char bnonce[256 / 8];
 };
 
 
@@ -2801,8 +2817,9 @@ GNUNET_CRYPTO_rsa_private_key_get_public (
  * @param hc where to store the hash code
  */
 void
-GNUNET_CRYPTO_rsa_public_key_hash (const struct GNUNET_CRYPTO_RsaPublicKey 
*key,
-                                   struct GNUNET_HashCode *hc);
+GNUNET_CRYPTO_rsa_public_key_hash (
+  const struct GNUNET_CRYPTO_RsaPublicKey *key,
+  struct GNUNET_HashCode *hc);
 
 
 /**
@@ -2906,54 +2923,83 @@ GNUNET_CRYPTO_rsa_public_key_cmp (const struct 
GNUNET_CRYPTO_RsaPublicKey *p1,
                                   const struct GNUNET_CRYPTO_RsaPublicKey *p2);
 
 
+/**
+ * @brief RSA Parameters to create blinded signature
+ */
+struct GNUNET_CRYPTO_RsaBlindedMessage
+{
+  /**
+   * Blinded message to be signed
+   * Note: is malloc()'ed!
+   */
+  void *blinded_msg;
+
+  /**
+   * Size of the @e blinded_msg to be signed.
+   */
+  size_t blinded_msg_size;
+};
+
+
 /**
  * Blinds the given message with the given blinding key
  *
- * @param hash hash of the message to sign
+ * @param message the message to sign
+ * @param message_size number of bytes in @a message
  * @param bks the blinding key
  * @param pkey the public key of the signer
- * @param[out] buf set to a buffer with the blinded message to be signed
- * @param[out] buf_size number of bytes stored in @a buf
+ * @param[out] bm set to the blinded message
  * @return #GNUNET_YES if successful, #GNUNET_NO if RSA key is malicious
  */
 enum GNUNET_GenericReturnValue
-GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
+GNUNET_CRYPTO_rsa_blind (const void *message,
+                         size_t message_size,
                          const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
                          struct GNUNET_CRYPTO_RsaPublicKey *pkey,
-                         void **buf,
-                         size_t *buf_size);
+                         struct GNUNET_CRYPTO_RsaBlindedMessage *bm);
 
 
 /**
  * Sign a blinded value, which must be a full domain hash of a 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
+ * @param bm the (blinded) message to sign
  * @return NULL on error, signature on success
  */
 struct GNUNET_CRYPTO_RsaSignature *
 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                                const void *msg,
-                                size_t msg_len);
+                                const struct GNUNET_CRYPTO_RsaBlindedMessage 
*bm);
 
 
 /**
  * Create and sign a full domain hash of a message.
  *
  * @param key private key to use for the signing
- * @param hash the hash of the message to sign
+ * @param message the message to sign
+ * @param message_size number of bytes in @a message
  * @return NULL on error, including a malicious RSA key, signature on success
  */
 struct GNUNET_CRYPTO_RsaSignature *
 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                            const struct GNUNET_HashCode *hash);
+                            const void *message,
+                            size_t message_size);
+
+
+/**
+ * Free memory occupied by blinded message. Only frees contents, not
+ * @a bm itself.
+ *
+ * @param[in] bm memory to free
+ */
+void
+GNUNET_CRYPTO_rsa_blinded_message_free (
+  struct GNUNET_CRYPTO_RsaBlindedMessage *bm);
 
 
 /**
  * Free memory occupied by signature.
  *
- * @param sig memory to free
+ * @param[in] sig memory to free
  */
 void
 GNUNET_CRYPTO_rsa_signature_free (struct GNUNET_CRYPTO_RsaSignature *sig);
@@ -2981,8 +3027,9 @@ GNUNET_CRYPTO_rsa_signature_encode (
  * @return NULL on error
  */
 struct GNUNET_CRYPTO_RsaSignature *
-GNUNET_CRYPTO_rsa_signature_decode (const void *buf,
-                                    size_t buf_size);
+GNUNET_CRYPTO_rsa_signature_decode (
+  const void *buf,
+  size_t buf_size);
 
 
 /**
@@ -2992,7 +3039,8 @@ GNUNET_CRYPTO_rsa_signature_decode (const void *buf,
  * @return the duplicate key; NULL upon error
  */
 struct GNUNET_CRYPTO_RsaSignature *
-GNUNET_CRYPTO_rsa_signature_dup (const struct GNUNET_CRYPTO_RsaSignature *sig);
+GNUNET_CRYPTO_rsa_signature_dup (
+  const struct GNUNET_CRYPTO_RsaSignature *sig);
 
 
 /**
@@ -3015,13 +3063,15 @@ GNUNET_CRYPTO_rsa_unblind (const struct 
GNUNET_CRYPTO_RsaSignature *sig,
  * Verify whether the given hash corresponds to the given signature and the
  * signature is valid with respect to the given public key.
  *
- * @param hash the message to verify to match the @a sig
+ * @param message the message to sign
+ * @param message_size number of bytes in @a message
  * @param sig signature that is being validated
  * @param public_key public key of the signer
  * @returns #GNUNET_YES if ok, #GNUNET_NO if RSA key is malicious, 
#GNUNET_SYSERR if signature
  */
 enum GNUNET_GenericReturnValue
-GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
+GNUNET_CRYPTO_rsa_verify (const void *message,
+                          size_t message_size,
                           const struct GNUNET_CRYPTO_RsaSignature *sig,
                           const struct GNUNET_CRYPTO_RsaPublicKey *public_key);
 
@@ -3061,10 +3111,11 @@ GNUNET_CRYPTO_cs_private_key_get_public (
  * @param[out] r array containing derived secrets r0 and r1
  */
 void
-GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
-                           const char *seed,
-                           const struct GNUNET_CRYPTO_CsPrivateKey *lts,
-                           struct GNUNET_CRYPTO_CsRSecret r[2]);
+GNUNET_CRYPTO_cs_r_derive (
+  const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
+  const char *seed,
+  const struct GNUNET_CRYPTO_CsPrivateKey *lts,
+  struct GNUNET_CRYPTO_CsRSecret r[2]);
 
 
 /**
@@ -3074,27 +3125,57 @@ GNUNET_CRYPTO_cs_r_derive (const struct 
GNUNET_CRYPTO_CsNonce *nonce,
  * @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_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 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
+ * Uses HKDF internally.
  *
  * @param blind_seed is the blinding seed to derive blinding factors
  * @param[out] bs array containing the two derived blinding secrets
  */
 void
 GNUNET_CRYPTO_cs_blinding_secrets_derive (
-  const struct GNUNET_CRYPTO_CsNonce *blind_seed,
+  const struct GNUNET_CRYPTO_CsBlindingNonce *blind_seed,
   struct GNUNET_CRYPTO_CsBlindingSecret bs[2]);
 
 
 /**
- * Calculate two blinded c's
+ * @brief CS Parameters derived from the message
+ * during blinding to create blinded signature
+ */
+struct GNUNET_CRYPTO_CsBlindedMessage
+{
+  /**
+   * The Clause Schnorr c_0 and c_1 containing the blinded message
+   */
+  struct GNUNET_CRYPTO_CsC c[2];
+
+  /**
+   * Nonce used in initial request.
+   */
+  struct GNUNET_CRYPTO_CsSessionNonce nonce;
+
+};
+
+
+/**
+ * Pair of Public R values for Cs denominations
+ */
+struct GNUNET_CRYPTO_CSPublicRPairP
+{
+  struct GNUNET_CRYPTO_CsRPublic r_pub[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
@@ -3103,7 +3184,7 @@ GNUNET_CRYPTO_cs_blinding_secrets_derive (
  * @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
+ * @param[out] r_pub_blind array of the two blinded R
  */
 void
 GNUNET_CRYPTO_cs_calc_blinded_c (
@@ -3113,32 +3194,49 @@ GNUNET_CRYPTO_cs_calc_blinded_c (
   const void *msg,
   size_t msg_len,
   struct GNUNET_CRYPTO_CsC blinded_c[2],
-  struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2]);
+  struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind);
 
 
 /**
- * Sign a blinded c
- * This function derives b from a nonce and a longterm secret
- * In original papers b is generated randomly
+ * The Sign Answer for Clause Blind Schnorr signature.
+ * The sign operation returns a parameter @param b and the signature
+ * scalar @param s_scalar.
+ */
+struct GNUNET_CRYPTO_CsBlindSignature
+{
+  /**
+   * To make ROS problem harder, the signer chooses an unpredictable b and
+   * only calculates signature of c_b
+   */
+  unsigned int b;
+
+  /**
+   * The blinded s scalar calculated from c_b
+   */
+  struct GNUNET_CRYPTO_CsBlindS s_scalar;
+};
+
+
+/**
+ * Sign a blinded @a c.
+ * This function derives b from a nonce and a longterm secret.
+ * In the 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
+ * 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)
+ * @param r array of the two secret inputs from the signer
+ * @param bm blinded message, including array of the two blinded c to sign c_b 
and the random nonce
+ * @param[out] cs_blind_sig where to write the blind signature
  */
-unsigned int
+void
 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);
+  const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
+  struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig);
 
 
 /**
@@ -3166,10 +3264,571 @@ GNUNET_CRYPTO_cs_unblind (
  * @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);
+GNUNET_CRYPTO_cs_verify (
+  const struct GNUNET_CRYPTO_CsSignature *sig,
+  const struct GNUNET_CRYPTO_CsPublicKey *pub,
+  const void *msg,
+  size_t msg_len);
+
+
+
+/**
+ * Types of public keys used for blind signatures.
+ */
+enum GNUNET_CRYPTO_BlindSignatureAlgorithm
+{
+
+  /**
+   * Invalid type of signature.
+   */
+  GNUNET_CRYPTO_BSA_INVALID = 0,
+
+  /**
+   * RSA blind signature.
+   */
+  GNUNET_CRYPTO_BSA_RSA = 1,
+
+  /**
+   * Clause Blind Schnorr signature.
+   */
+  GNUNET_CRYPTO_BSA_CS = 2
+};
+
+
+/**
+ * @brief Type of (unblinded) signatures.
+ */
+struct GNUNET_CRYPTO_UnblindedSignature
+{
+
+  /**
+   * Type of the signature.
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     */
+    struct GNUNET_CRYPTO_CsSignature cs_signature;
+
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
+
+  } details;
+
+};
+
+
+/**
+ * @brief Type for *blinded* signatures.
+ * Must be unblinded before it becomes valid.
+ */
+struct GNUNET_CRYPTO_BlindedSignature
+{
+
+  /**
+   * Type of the signature.
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     * At this point only the blinded s scalar is used.
+     * The final signature consisting of r,s is built after unblinding.
+     */
+    struct GNUNET_CRYPTO_CsBlindSignature blinded_cs_answer;
+
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaSignature *blinded_rsa_signature;
+
+  } details;
+
+};
+
+
+/**
+ * @brief Type of public signing keys for blind signatures.
+ */
+struct GNUNET_CRYPTO_BlindSignPublicKey
+{
+
+  /**
+   * Type of the public key.
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Hash of the public key.
+   */
+  struct GNUNET_HashCode pub_key_hash;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     */
+    struct GNUNET_CRYPTO_CsPublicKey cs_public_key;
+
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaPublicKey *rsa_public_key;
+
+  } details;
+};
+
+
+/**
+ * @brief Type of private signing keys for blind signing.
+ */
+struct GNUNET_CRYPTO_BlindSignPrivateKey
+{
+
+  /**
+   * Type of the public key.
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     */
+    struct GNUNET_CRYPTO_CsPrivateKey cs_private_key;
+
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaPrivateKey *rsa_private_key;
+
+  } details;
+};
+
+
+/**
+ * @brief Blinded message ready for blind signing.
+ */
+struct GNUNET_CRYPTO_BlindedMessage
+{
+  /**
+   * Type of the sign blinded message
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     */
+    struct GNUNET_CRYPTO_CsBlindedMessage cs_blinded_message;
+
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_RSA in @a cipher.
+     */
+    struct GNUNET_CRYPTO_RsaBlindedMessage rsa_blinded_message;
+
+  } details;
+};
+
+
+/**
+ * Secret r for Cs denominations
+ */
+struct GNUNET_CRYPTO_CSPrivateRPairP
+{
+  struct GNUNET_CRYPTO_CsRSecret r[2];
+};
+
+
+/**
+ * @brief Input needed for blinding a message.
+ */
+struct GNUNET_CRYPTO_BlindingInputValues
+{
+
+  /**
+   * Type of the signature.
+   */
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher;
+
+  /**
+   * Reference counter.
+   */
+  unsigned int rc;
+
+  /**
+   * Details, depending on @e cipher.
+   */
+  union
+  {
+    /**
+     * If we use #GNUNET_CRYPTO_BSA_CS in @a cipher.
+     */
+    struct GNUNET_CRYPTO_CSPublicRPairP cs_values;
+
+  } details;
+
+};
+
+
+/**
+ * Nonce used to deterministiacally derive input values
+ * used in multi-round blind signature protocols.
+ */
+union GNUNET_CRYPTO_BlindSessionNonce
+{
+  /**
+   * Nonce used when signing with CS.
+   */
+  struct GNUNET_CRYPTO_CsSessionNonce cs_nonce;
+};
+
+
+/**
+ * Compute blinding input values for a given @a nonce and
+ * @a salt.
+ *
+ * @param bsign_priv private key to compute input values for
+ * @param nonce session nonce to derive input values from
+ * @param salt salt to include in derivation logic
+ * @return blinding input values 
+ */
+struct GNUNET_CRYPTO_BlindingInputValues *
+GNUNET_CRYPTO_get_blinding_input_values (
+  const struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
+  const char *salt);
+
+
+/**
+ * Decrement reference counter of a @a bsign_pub, and free it if it reaches 
zero.
+ *
+ * @param[in] bsign_pub key to free
+ */
+void
+GNUNET_CRYPTO_blind_sign_pub_decref (struct GNUNET_CRYPTO_BlindSignPublicKey 
*bsign_pub);
+
+
+/**
+ * Decrement reference counter of a @a bsign_priv, and free it if it reaches 
zero.
+ *
+ * @param[in] bsign_priv key to free
+ */
+void
+GNUNET_CRYPTO_blind_sign_priv_decref (struct GNUNET_CRYPTO_BlindSignPrivateKey 
*bsign_priv);
+
+
+/**
+ * Decrement reference counter of a @a ub_sig, and free it if it reaches zero.
+ *
+ * @param[in] ub_sig signature to free
+ */
+void
+GNUNET_CRYPTO_unblinded_sig_decref (struct GNUNET_CRYPTO_UnblindedSignature 
*ub_sig);
+
+
+/**
+ * Decrement reference counter of a @a blind_sig, and free it if it reaches 
zero.
+ *
+ * @param[in] blind_sig signature to free
+ */
+void
+GNUNET_CRYPTO_blinded_sig_decref (
+  struct GNUNET_CRYPTO_BlindedSignature *blind_sig);
+
+
+/**
+ * Decrement reference counter of a @a bm, and free it if it reaches zero.
+ *
+ * @param[in] bm blinded message to free
+ */
+void
+GNUNET_CRYPTO_blinded_message_decref (
+  struct GNUNET_CRYPTO_BlindedMessage *bm);
+
+
+/**
+ * Increment reference counter of the given @a bm.
+ *
+ * @param[in,out] bm blinded message to increment reference counter for
+ * @return alias of @a bm with RC incremented
+ */
+struct GNUNET_CRYPTO_BlindedMessage *
+GNUNET_CRYPTO_blinded_message_incref (
+  struct GNUNET_CRYPTO_BlindedMessage *bm);
+
+
+/**
+ * Increment reference counter of the given @a bsign_pub.
+ *
+ * @param[in,out] bsign_pub public key to increment reference counter for
+ * @return alias of @a bsign_pub with RC incremented
+ */
+struct GNUNET_CRYPTO_BlindSignPublicKey *
+GNUNET_CRYPTO_bsign_pub_incref (struct GNUNET_CRYPTO_BlindSignPublicKey 
*bsign_pub);
+/**
+ * Increment reference counter of the given @a bsign_priv.
+ *
+ * @param[in,out] bsign_priv private key to increment reference counter for
+ * @return alias of @a bsign_priv with RC incremented
+ */
+struct GNUNET_CRYPTO_BlindSignPrivateKey *
+GNUNET_CRYPTO_bsign_priv_incref (struct GNUNET_CRYPTO_BlindSignPrivateKey 
*bsign_priv);
+
+
+/**
+ * Increment reference counter of the given @a ub_sig.
+ *
+ * @param[in,out] ub_sig signature to increment reference counter for
+ * @return alias of @a ub_sig with RC incremented
+ */
+struct GNUNET_CRYPTO_UnblindedSignature *
+GNUNET_CRYPTO_ub_sig_incref (struct GNUNET_CRYPTO_UnblindedSignature *ub_sig);
+
+
+/**
+ * Increment reference counter of the given @a blind_sig.
+ *
+ * @param[in,out] blind_sig signature to increment reference counter for
+ * @return alias of @a blind_sig with RC incremented
+ */
+struct GNUNET_CRYPTO_BlindedSignature *
+GNUNET_CRYPTO_blind_sig_incref (
+  struct GNUNET_CRYPTO_BlindedSignature *blind_sig);
+
+
+/**
+ * Compare two denomination public keys.
+ *
+ * @param bp1 first key
+ * @param bp2 second key
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+GNUNET_CRYPTO_bsign_pub_cmp (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bp1,
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bp2);
+
+
+/**
+ * Compare two denomination signatures.
+ *
+ * @param sig1 first signature
+ * @param sig2 second signature
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+GNUNET_CRYPTO_ub_sig_cmp (const struct GNUNET_CRYPTO_UnblindedSignature *sig1,
+                          const struct GNUNET_CRYPTO_UnblindedSignature *sig2);
+
+
+/**
+ * Compare two blinded denomination signatures.
+ *
+ * @param sig1 first signature
+ * @param sig2 second signature
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+GNUNET_CRYPTO_blind_sig_cmp (
+  const struct GNUNET_CRYPTO_BlindedSignature *sig1,
+  const struct GNUNET_CRYPTO_BlindedSignature *sig2);
+
+
+/**
+ * Compare two blinded messages.
+ *
+ * @param bp1 first blinded message
+ * @param bp2 second blinded message
+ * @return 0 if the keys are equal, otherwise -1 or 1
+ */
+int
+GNUNET_CRYPTO_blinded_message_cmp (
+  const struct GNUNET_CRYPTO_BlindedMessage *bp1,
+  const struct GNUNET_CRYPTO_BlindedMessage *bp2);
+
+
+/**
+ * Initialize public-private key pair for blind signatures.
+ *
+ * For #GNUNET_CRYPTO_BSA_RSA, an additional "unsigned int"
+ * argument with the number of bits for 'n' (e.g. 2048) must
+ * be passed.
+ *
+ * @param[out] bsign_priv where to write the private key with RC 1
+ * @param[out] bsign_pub where to write the public key with RC 1
+ * @param cipher which type of cipher to use
+ * @param ... RSA key size (eg. 2048/3072/4096)
+ * @return #GNUNET_OK on success, #GNUNET_NO if parameterst were invalid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sign_keys_create (
+  struct GNUNET_CRYPTO_BlindSignPrivateKey **bsign_priv,
+  struct GNUNET_CRYPTO_BlindSignPublicKey **bsign_pub,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
+  ...);
+
+
+/**
+ * Initialize public-private key pair for blind signatures.
+ *
+ * For #GNUNET_CRYPTO_BSA_RSA, an additional "unsigned int"
+ * argument with the number of bits for 'n' (e.g. 2048) must
+ * be passed.
+ *
+ * @param[out] bsign_priv where to write the private key with RC 1
+ * @param[out] bsign_pub where to write the public key with RC 1
+ * @param cipher which type of cipher to use
+ * @param ap RSA key size (eg. 2048/3072/4096)
+ * @return #GNUNET_OK on success, #GNUNET_NO if parameterst were invalid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sign_keys_create_va (
+  struct GNUNET_CRYPTO_BlindSignPrivateKey **bsign_priv,
+  struct GNUNET_CRYPTO_BlindSignPublicKey **bsign_pub,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
+  va_list ap);
+
+
+/**
+ * @brief Type of blinding secrets.  Must be exactly 32 bytes (DB).
+ */
+union GNUNET_CRYPTO_BlindingSecretP
+{
+  /**
+   * Clause Schnorr nonce.
+   */
+  struct GNUNET_CRYPTO_CsBlindingNonce nonce;
+
+  /**
+   * Variant for RSA for blind signatures.
+   */
+  struct GNUNET_CRYPTO_RsaBlindingKeySecret rsa_bks;
+};
+
+
+/**
+ * Blind message for blind signing with @a dk using blinding secret @a 
coin_bks.
+ *
+ * @param bsign_pub public key to blind for
+ * @param bks blinding secret to use
+ * @param nonce nonce used to obtain @a alg_values
+ *        can be NULL if input values are not used for the cipher
+ * @param message message to sign
+ * @param message_size number of bytes in @a message
+ * @param alg_values algorithm specific values to blind the @a message
+ * @return blinded message to give to signer, NULL on error
+ */
+struct GNUNET_CRYPTO_BlindedMessage *
+GNUNET_CRYPTO_message_blind_to_sign (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
+  const void *message,
+  size_t message_size,
+  const struct GNUNET_CRYPTO_BlindingInputValues *alg_values);
+
+
+/**
+ * Create blind signature.
+ *
+ * @param bsign_priv private key to use for signing
+ * @param salt salt value to use for the HKDF,
+ *        can be NULL if input values are not used for the cipher
+ * @param blinded_message the already blinded message to sign
+ * @return blind signature with RC=1, NULL on failure
+ */
+struct GNUNET_CRYPTO_BlindedSignature *
+GNUNET_CRYPTO_blind_sign (
+  const struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv,
+  const char *salt,
+  const struct GNUNET_CRYPTO_BlindedMessage *blinded_message);
+
+
+/**
+ * Unblind blind signature.
+ *
+ * @param blinded_sig the blind signature
+ * @param bks blinding secret to use
+ * @param message message that was supposedly signed
+ * @param message_size number of bytes in @a message
+ * @param alg_values algorithm specific values
+ * @param bsign_pub public key used for signing
+ * @return unblinded signature with RC=1, NULL on error
+ */
+struct GNUNET_CRYPTO_UnblindedSignature *
+GNUNET_CRYPTO_blind_sig_unblind (
+  const struct GNUNET_CRYPTO_BlindedSignature *blinded_sig,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
+  const void *message,
+  size_t message_size,
+  const struct GNUNET_CRYPTO_BlindingInputValues *alg_values,
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub);
+
+
+/**
+ * Verify signature made blindly.
+ *
+ * @param bsign_pub public key
+ * @param ub_sig signature made blindly with the private key
+ * @param message message that was supposedly signed
+ * @param message_size number of bytes in @a message
+ * @return #GNUNET_OK if the signature is valid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sig_verify (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
+  const struct GNUNET_CRYPTO_UnblindedSignature *ub_sig,
+  const void *message,
+  size_t message_size);
 
 
 /**
diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am
index d1b6f8287..7ab6301f5 100644
--- a/src/lib/util/Makefile.am
+++ b/src/lib/util/Makefile.am
@@ -52,7 +52,7 @@ libgnunetutil_la_SOURCES = \
   container_multiuuidmap.c \
   container_multipeermap.c \
   container_multihashmap32.c \
-  crypto_symmetric.c \
+  crypto_blind_sign.c \
   crypto_crc.c \
   crypto_cs.c \
   crypto_ecc.c \
@@ -70,6 +70,7 @@ libgnunetutil_la_SOURCES = \
   crypto_pow.c \
   crypto_random.c \
   crypto_rsa.c \
+  crypto_symmetric.c \
   disk.c \
   disk.h \
   dnsparser.c \
@@ -197,7 +198,7 @@ check_PROGRAMS = \
  test_container_multihashmap32 \
  test_container_multipeermap \
  test_container_heap \
- test_crypto_symmetric \
+ test_crypto_blind \
  test_crypto_crc \
  test_crypto_cs \
  test_crypto_ecdsa \
@@ -214,6 +215,7 @@ check_PROGRAMS = \
  test_crypto_paillier \
  test_crypto_random \
  test_crypto_rsa \
+ test_crypto_symmetric \
  test_disk \
  test_getopt \
  test_hexcoder \
@@ -346,6 +348,11 @@ test_container_heap_SOURCES = \
 test_container_heap_LDADD = \
  libgnunetutil.la
 
+test_crypto_blind_SOURCES = \
+ test_crypto_blind.c
+test_crypto_blind_LDADD = \
+ libgnunetutil.la
+
 test_crypto_symmetric_SOURCES = \
  test_crypto_symmetric.c
 test_crypto_symmetric_LDADD = \
diff --git a/src/lib/util/crypto_blind_sign.c b/src/lib/util/crypto_blind_sign.c
new file mode 100644
index 000000000..bbe5a5496
--- /dev/null
+++ b/src/lib/util/crypto_blind_sign.c
@@ -0,0 +1,672 @@
+/*
+  This file is part of GNUNET
+  Copyright (C) 2021, 2022, 2023 GNUnet e.V.
+
+  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, see <http://www.gnu.org/licenses/>
+*/
+/**
+ * @file crypto_blind_sign.c
+ * @brief blind signatures (abstraction over RSA or CS)
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+
+void
+GNUNET_CRYPTO_blind_sign_priv_decref (struct GNUNET_CRYPTO_BlindSignPrivateKey 
*bsign_priv)
+{
+  GNUNET_assert (bsign_priv->rc > 0);
+  bsign_priv->rc--;
+  if (0 != bsign_priv->rc)
+    return;
+  switch (bsign_priv->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (NULL != bsign_priv->details.rsa_private_key)
+    {
+      GNUNET_CRYPTO_rsa_private_key_free (bsign_priv->details.rsa_private_key);
+      bsign_priv->details.rsa_private_key = NULL;
+    }
+    bsign_priv->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    bsign_priv->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  }
+  GNUNET_free (bsign_priv);
+}
+
+
+void
+GNUNET_CRYPTO_blind_sign_pub_decref (struct GNUNET_CRYPTO_BlindSignPublicKey 
*bsign_pub)
+{
+  GNUNET_assert (bsign_pub->rc > 0);
+  bsign_pub->rc--;
+  if (0 != bsign_pub->rc)
+    return;
+  switch (bsign_pub->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (NULL != bsign_pub->details.rsa_public_key)
+    {
+      GNUNET_CRYPTO_rsa_public_key_free (bsign_pub->details.rsa_public_key);
+      bsign_pub->details.rsa_public_key = NULL;
+    }
+    bsign_pub->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    break;
+  }
+  GNUNET_free (bsign_pub);
+}
+
+
+void
+GNUNET_CRYPTO_unblinded_sig_decref (struct GNUNET_CRYPTO_UnblindedSignature 
*ub_sig)
+{
+  GNUNET_assert (ub_sig->rc > 0);
+  ub_sig->rc--;
+  if (0 != ub_sig->rc)
+    return;
+  switch (ub_sig->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (NULL != ub_sig->details.rsa_signature)
+    {
+      GNUNET_CRYPTO_rsa_signature_free (ub_sig->details.rsa_signature);
+      ub_sig->details.rsa_signature = NULL;
+    }
+    ub_sig->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    ub_sig->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  }
+  GNUNET_free (ub_sig);
+}
+
+
+void
+GNUNET_CRYPTO_blinded_sig_decref (
+  struct GNUNET_CRYPTO_BlindedSignature *blind_sig)
+{
+  GNUNET_assert (blind_sig->rc > 0);
+  blind_sig->rc--;
+  if (0 != blind_sig->rc)
+    return;
+  switch (blind_sig->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (NULL != blind_sig->details.blinded_rsa_signature)
+    {
+      GNUNET_CRYPTO_rsa_signature_free (
+        blind_sig->details.blinded_rsa_signature);
+      blind_sig->details.blinded_rsa_signature = NULL;
+    }
+    blind_sig->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    blind_sig->cipher = GNUNET_CRYPTO_BSA_INVALID;
+    break;
+  }
+  GNUNET_free (blind_sig);
+}
+
+
+void
+GNUNET_CRYPTO_blinded_message_decref (
+  struct GNUNET_CRYPTO_BlindedMessage *bm)
+{
+  GNUNET_assert (bm->rc > 0);
+  bm->rc--;
+  if (0 != bm->rc)
+    return;
+  switch (bm->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    GNUNET_free (bm->details.rsa_blinded_message.blinded_msg);
+    break;
+  case GNUNET_CRYPTO_BSA_CS:
+    break;
+  }
+  GNUNET_free (bm);
+}
+
+
+struct GNUNET_CRYPTO_BlindedMessage *
+GNUNET_CRYPTO_blinded_message_incref (
+  struct GNUNET_CRYPTO_BlindedMessage *bm)
+{
+  bm->rc++;
+  return bm;
+}
+
+
+struct GNUNET_CRYPTO_BlindSignPublicKey *
+GNUNET_CRYPTO_bsign_pub_incref (struct GNUNET_CRYPTO_BlindSignPublicKey 
*bsign_pub)
+{
+  bsign_pub->rc++;
+  return bsign_pub;
+}
+
+
+struct GNUNET_CRYPTO_BlindSignPrivateKey *
+GNUNET_CRYPTO_bsign_priv_incref (struct GNUNET_CRYPTO_BlindSignPrivateKey 
*bsign_priv)
+{
+  bsign_priv->rc++;
+  return bsign_priv;
+}
+
+
+struct GNUNET_CRYPTO_UnblindedSignature *
+GNUNET_CRYPTO_ub_sig_incref (struct GNUNET_CRYPTO_UnblindedSignature *ub_sig)
+{
+  ub_sig->rc++;
+  return ub_sig;
+}
+
+
+struct GNUNET_CRYPTO_BlindedSignature *
+GNUNET_CRYPTO_blind_sig_incref (
+  struct GNUNET_CRYPTO_BlindedSignature *blind_sig)
+{
+  blind_sig->rc++;
+  return blind_sig;
+}
+
+
+int
+GNUNET_CRYPTO_bsign_pub_cmp (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bp1,
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bp2)
+{
+  if (bp1->cipher != bp2->cipher)
+    return (bp1->cipher > bp2->cipher) ? 1 : -1;
+  switch (bp1->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return 0;
+  case GNUNET_CRYPTO_BSA_RSA:
+    return GNUNET_memcmp (&bp1->pub_key_hash,
+                          &bp2->pub_key_hash);
+  case GNUNET_CRYPTO_BSA_CS:
+    return GNUNET_memcmp (&bp1->pub_key_hash,
+                          &bp2->pub_key_hash);
+  }
+  GNUNET_assert (0);
+  return -2;
+}
+
+
+int
+GNUNET_CRYPTO_ub_sig_cmp (
+  const struct GNUNET_CRYPTO_UnblindedSignature *sig1,
+  const struct GNUNET_CRYPTO_UnblindedSignature *sig2)
+{
+  if (sig1->cipher != sig2->cipher)
+    return (sig1->cipher > sig2->cipher) ? 1 : -1;
+  switch (sig1->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return 0;
+  case GNUNET_CRYPTO_BSA_RSA:
+    return GNUNET_CRYPTO_rsa_signature_cmp (sig1->details.rsa_signature,
+                                            sig2->details.rsa_signature);
+  case GNUNET_CRYPTO_BSA_CS:
+    return GNUNET_memcmp (&sig1->details.cs_signature,
+                          &sig2->details.cs_signature);
+  }
+  GNUNET_assert (0);
+  return -2;
+}
+
+
+int
+GNUNET_CRYPTO_blind_sig_cmp (
+  const struct GNUNET_CRYPTO_BlindedSignature *sig1,
+  const struct GNUNET_CRYPTO_BlindedSignature *sig2)
+{
+  if (sig1->cipher != sig2->cipher)
+    return (sig1->cipher > sig2->cipher) ? 1 : -1;
+  switch (sig1->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return 0;
+  case GNUNET_CRYPTO_BSA_RSA:
+    return GNUNET_CRYPTO_rsa_signature_cmp 
(sig1->details.blinded_rsa_signature,
+                                            
sig2->details.blinded_rsa_signature);
+  case GNUNET_CRYPTO_BSA_CS:
+    return GNUNET_memcmp (&sig1->details.blinded_cs_answer,
+                          &sig2->details.blinded_cs_answer);
+  }
+  GNUNET_assert (0);
+  return -2;
+}
+
+
+int
+GNUNET_CRYPTO_blinded_message_cmp (
+  const struct GNUNET_CRYPTO_BlindedMessage *bp1,
+  const struct GNUNET_CRYPTO_BlindedMessage *bp2)
+{
+  if (bp1->cipher != bp2->cipher)
+    return (bp1->cipher > bp2->cipher) ? 1 : -1;
+  switch (bp1->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return 0;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (bp1->details.rsa_blinded_message.blinded_msg_size !=
+        bp2->details.rsa_blinded_message.blinded_msg_size)
+      return (bp1->details.rsa_blinded_message.blinded_msg_size >
+              bp2->details.rsa_blinded_message.blinded_msg_size) ? 1 : -1;
+    return memcmp (bp1->details.rsa_blinded_message.blinded_msg,
+                   bp2->details.rsa_blinded_message.blinded_msg,
+                   bp1->details.rsa_blinded_message.blinded_msg_size);
+  case GNUNET_CRYPTO_BSA_CS:
+    return GNUNET_memcmp (&bp1->details.cs_blinded_message,
+                          &bp2->details.cs_blinded_message);
+  }
+  GNUNET_assert (0);
+  return -2;
+}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sign_keys_create (
+  struct GNUNET_CRYPTO_BlindSignPrivateKey **bsign_priv,
+  struct GNUNET_CRYPTO_BlindSignPublicKey **bsign_pub,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
+  ...)
+{
+  enum GNUNET_GenericReturnValue ret;
+  va_list ap;
+
+  va_start (ap,
+            cipher);
+  ret = GNUNET_CRYPTO_blind_sign_keys_create_va (bsign_priv,
+                                                 bsign_pub,
+                                                 cipher,
+                                                 ap);
+  va_end (ap);
+  return ret;
+}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sign_keys_create_va (
+  struct GNUNET_CRYPTO_BlindSignPrivateKey **bsign_priv,
+  struct GNUNET_CRYPTO_BlindSignPublicKey **bsign_pub,
+  enum GNUNET_CRYPTO_BlindSignatureAlgorithm cipher,
+  va_list ap)
+  {
+  struct GNUNET_CRYPTO_BlindSignPrivateKey *priv;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *pub;
+
+  priv = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPrivateKey);
+  priv->rc = 1;
+  priv->cipher = cipher;
+  *bsign_priv = priv;
+  pub = GNUNET_new (struct GNUNET_CRYPTO_BlindSignPublicKey);
+  pub->rc = 1;
+  pub->cipher = cipher;
+  *bsign_pub = pub;
+  switch (cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    break;
+  case GNUNET_CRYPTO_BSA_RSA:
+    {
+      unsigned int bits;
+
+      bits = va_arg (ap,
+                     unsigned int);
+      if (bits < 512)
+      {
+        GNUNET_break (0);
+        break;
+      }
+      priv->details.rsa_private_key
+        = GNUNET_CRYPTO_rsa_private_key_create (bits);
+    }
+    if (NULL == priv->details.rsa_private_key)
+    {
+      GNUNET_break (0);
+      break;
+    }
+    pub->details.rsa_public_key
+      = GNUNET_CRYPTO_rsa_private_key_get_public (
+          priv->details.rsa_private_key);
+    GNUNET_CRYPTO_rsa_public_key_hash (pub->details.rsa_public_key,
+                                       &pub->pub_key_hash);
+    return GNUNET_OK;
+  case GNUNET_CRYPTO_BSA_CS:
+    GNUNET_CRYPTO_cs_private_key_generate (&priv->details.cs_private_key);
+    GNUNET_CRYPTO_cs_private_key_get_public (
+      &priv->details.cs_private_key,
+      &pub->details.cs_public_key);
+    GNUNET_CRYPTO_hash (&pub->details.cs_public_key,
+                        sizeof(pub->details.cs_public_key),
+                        &pub->pub_key_hash);
+    return GNUNET_OK;
+  }
+  GNUNET_free (priv);
+  GNUNET_free (pub);
+  *bsign_priv = NULL;
+  *bsign_pub = NULL;
+  return GNUNET_SYSERR;
+}
+
+
+struct GNUNET_CRYPTO_BlindingInputValues *
+GNUNET_CRYPTO_get_blinding_input_values (
+  const struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
+  const char *salt)
+{
+  struct GNUNET_CRYPTO_BlindingInputValues *biv;
+
+  biv = GNUNET_new (struct GNUNET_CRYPTO_BlindingInputValues);
+  biv->cipher = bsign_priv->cipher;
+  biv->rc = 1;
+  switch (bsign_priv->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    GNUNET_free (biv);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    return biv;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      struct GNUNET_CRYPTO_CsRSecret cspriv[2];
+
+      GNUNET_CRYPTO_cs_r_derive (&nonce->cs_nonce,
+                                 salt,
+                                 &bsign_priv->details.cs_private_key,
+                                 cspriv);
+      GNUNET_CRYPTO_cs_r_get_public (&cspriv[0],
+                                     &biv->details.cs_values.r_pub[0]);
+      GNUNET_CRYPTO_cs_r_get_public (&cspriv[1],
+                                     &biv->details.cs_values.r_pub[1]);
+      return biv;
+    }
+  }
+  GNUNET_break (0);
+  GNUNET_free (biv);
+  return NULL;
+}
+
+
+struct GNUNET_CRYPTO_BlindedMessage *
+GNUNET_CRYPTO_message_blind_to_sign (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
+  const union GNUNET_CRYPTO_BlindSessionNonce *nonce,
+  const void *message,
+  size_t message_size,
+  const struct GNUNET_CRYPTO_BlindingInputValues *alg_values)
+{
+  struct GNUNET_CRYPTO_BlindedMessage *bm;
+
+  bm = GNUNET_new (struct GNUNET_CRYPTO_BlindedMessage);
+  bm->cipher = bsign_pub->cipher;
+  bm->rc = 1;
+  switch (bsign_pub->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    GNUNET_free (bm);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (GNUNET_YES !=
+        GNUNET_CRYPTO_rsa_blind (
+          message,
+          message_size,
+          &bks->rsa_bks,
+          bsign_pub->details.rsa_public_key,
+          &bm->details.rsa_blinded_message))
+    {
+      GNUNET_break (0);
+      GNUNET_free (bm);
+      return NULL;
+    }
+    return bm;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      struct GNUNET_CRYPTO_CSPublicRPairP blinded_r_pub;
+      struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
+
+      if (NULL == nonce)
+      {
+        GNUNET_break_op (0);
+        GNUNET_free (bm);
+        return NULL;
+      }
+      GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce,
+                                                bs);
+      GNUNET_CRYPTO_cs_calc_blinded_c (
+        bs,
+        alg_values->details.cs_values.r_pub,
+        &bsign_pub->details.cs_public_key,
+        message,
+        message_size,
+        bm->details.cs_blinded_message.c,
+        &blinded_r_pub);
+      bm->details.cs_blinded_message.nonce = nonce->cs_nonce;
+      (void) blinded_r_pub;
+      return bm;
+    }
+  }
+  GNUNET_break (0);
+  return NULL;
+}
+
+
+struct GNUNET_CRYPTO_BlindedSignature *
+GNUNET_CRYPTO_blind_sign (
+  const struct GNUNET_CRYPTO_BlindSignPrivateKey *bsign_priv,
+  const char *salt,
+  const struct GNUNET_CRYPTO_BlindedMessage *blinded_message)
+{
+  struct GNUNET_CRYPTO_BlindedSignature *blind_sig;
+
+  if (blinded_message->cipher != bsign_priv->cipher)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  blind_sig = GNUNET_new (struct GNUNET_CRYPTO_BlindedSignature);
+  blind_sig->cipher = bsign_priv->cipher;
+  blind_sig->rc = 1;
+  switch (bsign_priv->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    GNUNET_free (blind_sig);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    blind_sig->details.blinded_rsa_signature
+      = GNUNET_CRYPTO_rsa_sign_blinded (
+          bsign_priv->details.rsa_private_key,
+          &blinded_message->details.rsa_blinded_message);
+    if (NULL == blind_sig->details.blinded_rsa_signature)
+    {
+      GNUNET_break (0);
+      GNUNET_free (blind_sig);
+      return NULL;
+    }
+    return blind_sig;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      struct GNUNET_CRYPTO_CsRSecret r[2];
+
+      GNUNET_CRYPTO_cs_r_derive (
+        &blinded_message->details.cs_blinded_message.nonce,
+        salt,
+        &bsign_priv->details.cs_private_key,
+        r);
+      GNUNET_CRYPTO_cs_sign_derive (
+        &bsign_priv->details.cs_private_key,
+        r,
+        &blinded_message->details.cs_blinded_message,
+        &blind_sig->details.blinded_cs_answer);
+    }
+    return blind_sig;
+  }
+  GNUNET_break (0);
+  return NULL;
+}
+
+
+struct GNUNET_CRYPTO_UnblindedSignature *
+GNUNET_CRYPTO_blind_sig_unblind (
+  const struct GNUNET_CRYPTO_BlindedSignature *blinded_sig,
+  const union GNUNET_CRYPTO_BlindingSecretP *bks,
+  const void *message,
+  size_t message_size,
+  const struct GNUNET_CRYPTO_BlindingInputValues *alg_values,
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub){
+  struct GNUNET_CRYPTO_UnblindedSignature *ub_sig;
+  
+  if (blinded_sig->cipher != bsign_pub->cipher)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  if (blinded_sig->cipher != alg_values->cipher)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  ub_sig = GNUNET_new (struct GNUNET_CRYPTO_UnblindedSignature);
+  ub_sig->cipher = blinded_sig->cipher;
+  ub_sig->rc = 1;
+  switch (bsign_pub->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    GNUNET_free (ub_sig);
+    return NULL;
+  case GNUNET_CRYPTO_BSA_RSA:
+    ub_sig->details.rsa_signature
+      = GNUNET_CRYPTO_rsa_unblind (
+          blinded_sig->details.blinded_rsa_signature,
+          &bks->rsa_bks,
+          bsign_pub->details.rsa_public_key);
+    if (NULL == ub_sig->details.rsa_signature)
+    {
+      GNUNET_break (0);
+      GNUNET_free (ub_sig);
+      return NULL;
+    }
+    return ub_sig;
+  case GNUNET_CRYPTO_BSA_CS:
+    {
+      struct GNUNET_CRYPTO_CsBlindingSecret bs[2];
+      struct GNUNET_CRYPTO_CsC c[2];
+      struct GNUNET_CRYPTO_CSPublicRPairP r_pub_blind;
+      unsigned int b;
+
+      GNUNET_CRYPTO_cs_blinding_secrets_derive (&bks->nonce,
+                                                bs);
+      GNUNET_CRYPTO_cs_calc_blinded_c (
+        bs,
+        alg_values->details.cs_values.r_pub,
+        &bsign_pub->details.cs_public_key,
+        message,
+        message_size,
+        c,
+        &r_pub_blind);
+      b = blinded_sig->details.blinded_cs_answer.b;
+      ub_sig->details.cs_signature.r_point
+        = r_pub_blind.r_pub[b];
+      GNUNET_CRYPTO_cs_unblind 
(&blinded_sig->details.blinded_cs_answer.s_scalar,
+                                &bs[b],
+                                &ub_sig->details.cs_signature.s_scalar);
+      return ub_sig;
+    }
+  }
+  GNUNET_break (0);
+  GNUNET_free (ub_sig);
+  return NULL;
+}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_blind_sig_verify (
+  const struct GNUNET_CRYPTO_BlindSignPublicKey *bsign_pub,
+  const struct GNUNET_CRYPTO_UnblindedSignature *ub_sig,
+  const void *message,
+  size_t message_size)
+{
+  if (bsign_pub->cipher != ub_sig->cipher)
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  switch (bsign_pub->cipher)
+  {
+  case GNUNET_CRYPTO_BSA_INVALID:
+    GNUNET_break (0);
+    return GNUNET_NO;
+  case GNUNET_CRYPTO_BSA_RSA:
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_rsa_verify (message,
+                                  message_size,
+                                  ub_sig->details.rsa_signature,
+                                  bsign_pub->details.rsa_public_key))
+    {
+      GNUNET_break_op (0);
+      return GNUNET_NO;
+    }
+    return GNUNET_YES;
+  case GNUNET_CRYPTO_BSA_CS:
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_cs_verify (&ub_sig->details.cs_signature,
+                                 &bsign_pub->details.cs_public_key,
+                                 message,
+                                 message_size))
+    {
+      GNUNET_break_op (0);
+      return GNUNET_NO;
+    }
+    return GNUNET_YES;
+  }
+  GNUNET_break (0);
+  return GNUNET_NO;
+}
+
+
+/* end of crypto_blind_sign.c */
diff --git a/src/lib/util/crypto_cs.c b/src/lib/util/crypto_cs.c
index 8506c7fa6..049f63062 100644
--- a/src/lib/util/crypto_cs.c
+++ b/src/lib/util/crypto_cs.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2014,2016,2019 GNUnet e.V.
+   Copyright (C) 2014,2016,2019, 2023 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
@@ -53,8 +53,9 @@ 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));
+  GNUNET_assert (0 ==
+                 crypto_scalarmult_ed25519_base_noclamp (pub->point.y,
+                                                         priv->scalar.d));
 }
 
 
@@ -75,7 +76,7 @@ map_to_scalar_subgroup (struct GNUNET_CRYPTO_Cs25519Scalar 
*scalar)
 
 
 void
-GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce *nonce,
+GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
                            const char *seed,
                            const struct GNUNET_CRYPTO_CsPrivateKey *lts,
                            struct GNUNET_CRYPTO_CsRSecret r[2])
@@ -84,7 +85,7 @@ GNUNET_CRYPTO_cs_r_derive (const struct GNUNET_CRYPTO_CsNonce 
*nonce,
     GNUNET_YES ==
     GNUNET_CRYPTO_kdf (
       r,     sizeof (struct GNUNET_CRYPTO_CsRSecret) * 2,
-      seed,   strlen (seed),
+      seed,  strlen (seed),
       lts,   sizeof (*lts),
       nonce, sizeof (*nonce),
       NULL,  0));
@@ -97,14 +98,15 @@ 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));
+  GNUNET_assert (0 ==
+                 crypto_scalarmult_ed25519_base_noclamp (r_pub->point.y,
+                                                         r_priv->scalar.d));
 }
 
 
 void
 GNUNET_CRYPTO_cs_blinding_secrets_derive (
-  const struct GNUNET_CRYPTO_CsNonce *blind_seed,
+  const struct GNUNET_CRYPTO_CsBlindingNonce *blind_seed,
   struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
 {
   GNUNET_assert (
@@ -156,8 +158,12 @@ cs_full_domain_hash (const struct GNUNET_CRYPTO_CsRPublic 
*r_dash,
   // 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);
+  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,
@@ -208,22 +214,26 @@ calc_r_dash (const struct GNUNET_CRYPTO_CsBlindingSecret 
*bs,
 {
   // R'i = Ri + alpha i*G + beta i*pub
   struct GNUNET_CRYPTO_Cs25519Point alpha_mul_base;
-  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
+  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));
+  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));
+  GNUNET_assert (0 ==
+                 crypto_core_ed25519_add (
+                   blinded_r_pub->point.y,
+                   r_pub->point.y,
+                   alpha_mul_base_plus_beta_mul_pub.y));
 }
 
 
@@ -235,19 +245,33 @@ GNUNET_CRYPTO_cs_calc_blinded_c (
   const void *msg,
   size_t msg_len,
   struct GNUNET_CRYPTO_CsC blinded_c[2],
-  struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
+  struct GNUNET_CRYPTO_CSPublicRPairP *r_pub_blind)
 {
-  // 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)
+  /* for i 0/1: R'i = Ri + alpha i*G + beta i*pub */
+  calc_r_dash (&bs[0],
+               &r_pub[0],
+               pub,
+               &r_pub_blind->r_pub[0]);
+  calc_r_dash (&bs[1],
+               &r_pub[1],
+               pub,
+               &r_pub_blind->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);
+  cs_full_domain_hash (&r_pub_blind->r_pub[0],
+                       msg,
+                       msg_len,
+                       pub,
+                       &c_dash_0);
+  cs_full_domain_hash (&r_pub_blind->r_pub[1],
+                       msg,
+                       msg_len,
+                       pub,
+                       &c_dash_1);
 
-  // for i 0/1: ci = c'i + beta i mod p
+  /* 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);
@@ -257,17 +281,17 @@ GNUNET_CRYPTO_cs_calc_blinded_c (
 }
 
 
-unsigned int
+void
 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)
+  const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
+  struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
 {
+  struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
   uint32_t hkdf_out;
 
-  // derive clause session identifier b (random bit)
+  /* derive clause session identifier b (random bit) */
   GNUNET_assert (GNUNET_YES ==
                  GNUNET_CRYPTO_hkdf (&hkdf_out,
                                      sizeof (hkdf_out),
@@ -277,22 +301,19 @@ GNUNET_CRYPTO_cs_sign_derive (
                                      strlen ("b"),
                                      priv,
                                      sizeof (*priv),
-                                     nonce,
-                                     sizeof (*nonce),
+                                     &bm->nonce,
+                                     sizeof (bm->nonce),
                                      NULL,
                                      0));
-  unsigned int b = hkdf_out % 2;
+  cs_blind_sig->b = hkdf_out % 2;
 
-  // s = r_b + c_b priv
-  struct GNUNET_CRYPTO_Cs25519Scalar c_b_mul_priv;
+  /* s = r_b + c_b * priv */
   crypto_core_ed25519_scalar_mul (c_b_mul_priv.d,
-                                  c[b].scalar.d,
+                                  bm->c[cs_blind_sig->b].scalar.d,
                                   priv->scalar.d);
-  crypto_core_ed25519_scalar_add (blinded_signature_scalar->scalar.d,
-                                  r[b].scalar.d,
+  crypto_core_ed25519_scalar_add (cs_blind_sig->s_scalar.scalar.d,
+                                  r[cs_blind_sig->b].scalar.d,
                                   c_b_mul_priv.d);
-
-  return b;
 }
 
 
@@ -325,7 +346,8 @@ GNUNET_CRYPTO_cs_verify (const struct 
GNUNET_CRYPTO_CsSignature *sig,
 
   // s'G ?= R' + c' pub
   struct GNUNET_CRYPTO_Cs25519Point sig_scal_mul_base;
-  GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
+  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;
diff --git a/src/lib/util/crypto_rsa.c b/src/lib/util/crypto_rsa.c
index 2c446d21a..aeae3de8f 100644
--- a/src/lib/util/crypto_rsa.c
+++ b/src/lib/util/crypto_rsa.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2014,2016,2019 GNUnet e.V.
+   Copyright (C) 2014,2016,2019,2023 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
@@ -178,9 +178,9 @@ GNUNET_CRYPTO_rsa_private_key_free (struct 
GNUNET_CRYPTO_RsaPrivateKey *key)
 
 
 size_t
-GNUNET_CRYPTO_rsa_private_key_encode (const struct
-                                      GNUNET_CRYPTO_RsaPrivateKey *key,
-                                      void **buffer)
+GNUNET_CRYPTO_rsa_private_key_encode (
+  const struct GNUNET_CRYPTO_RsaPrivateKey *key,
+  void **buffer)
 {
   size_t n;
   char *b;
@@ -745,24 +745,33 @@ numeric_mpi_alloc_n_print (gcry_mpi_t v,
  *   https://eprint.iacr.org/2001/002.pdf
  *   http://www.di.ens.fr/~pointche/Documents/Papers/2001_fcA.pdf
  *
- * @param hash initial hash of the message to sign
+ * @param message the message to sign
+ * @param message_size number of bytes in @a message
  * @param pkey the public key of the signer
  * @param rsize If not NULL, the number of bytes actually stored in buffer
  * @return MPI value set to the FDH, NULL if RSA key is malicious
  */
 static gcry_mpi_t
 rsa_full_domain_hash (const struct GNUNET_CRYPTO_RsaPublicKey *pkey,
-                      const struct GNUNET_HashCode *hash)
+                      const void *message,
+                      size_t message_size)
 {
-  gcry_mpi_t r, n;
+  gcry_mpi_t r;
+  gcry_mpi_t n;
   void *xts;
   size_t xts_len;
   int ok;
 
   /* Extract the composite n from the RSA public key */
-  GNUNET_assert (0 == key_from_sexp (&n, pkey->sexp, "rsa", "n"));
+  GNUNET_assert (0 ==
+                 key_from_sexp (&n,
+                                pkey->sexp,
+                                "rsa",
+                                "n"));
   /* Assert that it at least looks like an RSA key */
-  GNUNET_assert (0 == gcry_mpi_get_flag (n, GCRYMPI_FLAG_OPAQUE));
+  GNUNET_assert (0 ==
+                 gcry_mpi_get_flag (n,
+                                    GCRYMPI_FLAG_OPAQUE));
 
   /* We key with the public denomination key as a homage to RSA-PSS by  *
   * Mihir Bellare and Phillip Rogaway.  Doing this lowers the degree   *
@@ -774,7 +783,7 @@ rsa_full_domain_hash (const struct 
GNUNET_CRYPTO_RsaPublicKey *pkey,
   GNUNET_CRYPTO_kdf_mod_mpi (&r,
                              n,
                              xts, xts_len,
-                             hash, sizeof(*hash),
+                             message, message_size,
                              "RSA-FDA FTpsW!");
   GNUNET_free (xts);
   ok = rsa_gcd_validate (r, n);
@@ -786,12 +795,20 @@ rsa_full_domain_hash (const struct 
GNUNET_CRYPTO_RsaPublicKey *pkey,
 }
 
 
+void
+GNUNET_CRYPTO_rsa_blinded_message_free (
+  struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
+{
+  GNUNET_free (bm->blinded_msg);
+}
+
+
 enum GNUNET_GenericReturnValue
-GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode *hash,
+GNUNET_CRYPTO_rsa_blind (const void *message,
+                         size_t message_size,
                          const struct GNUNET_CRYPTO_RsaBlindingKeySecret *bks,
                          struct GNUNET_CRYPTO_RsaPublicKey *pkey,
-                         void **buf,
-                         size_t *buf_size)
+                         struct GNUNET_CRYPTO_RsaBlindedMessage *bm)
 {
   struct RsaBlindingKey *bkey;
   gcry_mpi_t data;
@@ -801,31 +818,36 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode 
*hash,
   int ret;
 
   BENCHMARK_START (rsa_blind);
-
-  GNUNET_assert (buf != NULL);
-  GNUNET_assert (buf_size != NULL);
-  ret = key_from_sexp (ne, pkey->sexp, "public-key", "ne");
+  ret = key_from_sexp (ne,
+                       pkey->sexp,
+                       "public-key",
+                       "ne");
   if (0 != ret)
-    ret = key_from_sexp (ne, pkey->sexp, "rsa", "ne");
+    ret = key_from_sexp (ne,
+                         pkey->sexp,
+                         "rsa",
+                         "ne");
   if (0 != ret)
   {
     GNUNET_break (0);
-    *buf = NULL;
-    *buf_size = 0;
+    bm->blinded_msg = NULL;
+    bm->blinded_msg_size = 0;
+    BENCHMARK_END (rsa_blind);
     return GNUNET_NO;
   }
 
-  data = rsa_full_domain_hash (pkey, hash);
+  data = rsa_full_domain_hash (pkey,
+                               message,
+                               message_size);
   if (NULL == data)
     goto rsa_gcd_validate_failure;
-
-  bkey = rsa_blinding_key_derive (pkey, bks);
+  bkey = rsa_blinding_key_derive (pkey,
+                                  bks);
   if (NULL == bkey)
   {
     gcry_mpi_release (data);
     goto rsa_gcd_validate_failure;
   }
-
   r_e = gcry_mpi_new (0);
   gcry_mpi_powm (r_e,
                  bkey->r,
@@ -842,12 +864,12 @@ GNUNET_CRYPTO_rsa_blind (const struct GNUNET_HashCode 
*hash,
   gcry_mpi_release (r_e);
   rsa_blinding_key_free (bkey);
 
-  *buf_size = numeric_mpi_alloc_n_print (data_r_e,
-                                         (char **) buf);
+  bm->blinded_msg_size
+    = numeric_mpi_alloc_n_print (data_r_e,
+                                 (char **) &bm->blinded_msg);
   gcry_mpi_release (data_r_e);
 
   BENCHMARK_END (rsa_blind);
-
   return GNUNET_YES;
 
 rsa_gcd_validate_failure:
@@ -855,8 +877,9 @@ rsa_gcd_validate_failure:
   /* GNUNET_break_op (0); */
   gcry_mpi_release (ne[0]);
   gcry_mpi_release (ne[1]);
-  *buf = NULL;
-  *buf_size = 0;
+  bm->blinded_msg = NULL;
+  bm->blinded_msg_size = 0;
+  BENCHMARK_END (rsa_blind);
   return GNUNET_NO;
 }
 
@@ -945,22 +968,20 @@ rsa_sign_mpi (const struct GNUNET_CRYPTO_RsaPrivateKey 
*key,
 
 struct GNUNET_CRYPTO_RsaSignature *
 GNUNET_CRYPTO_rsa_sign_blinded (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                                const void *msg,
-                                size_t msg_len)
+                                const struct GNUNET_CRYPTO_RsaBlindedMessage 
*bm)
 {
   gcry_mpi_t v = NULL;
   struct GNUNET_CRYPTO_RsaSignature *sig;
 
   BENCHMARK_START (rsa_sign_blinded);
-
   GNUNET_assert (0 ==
                  gcry_mpi_scan (&v,
                                 GCRYMPI_FMT_USG,
-                                msg,
-                                msg_len,
+                                bm->blinded_msg,
+                                bm->blinded_msg_size,
                                 NULL));
-
-  sig = rsa_sign_mpi (key, v);
+  sig = rsa_sign_mpi (key,
+                      v);
   gcry_mpi_release (v);
   BENCHMARK_END (rsa_sign_blinded);
   return sig;
@@ -969,14 +990,17 @@ GNUNET_CRYPTO_rsa_sign_blinded (const struct 
GNUNET_CRYPTO_RsaPrivateKey *key,
 
 struct GNUNET_CRYPTO_RsaSignature *
 GNUNET_CRYPTO_rsa_sign_fdh (const struct GNUNET_CRYPTO_RsaPrivateKey *key,
-                            const struct GNUNET_HashCode *hash)
+                            const void *message,
+                            size_t message_size)
 {
   struct GNUNET_CRYPTO_RsaPublicKey *pkey;
   gcry_mpi_t v = NULL;
   struct GNUNET_CRYPTO_RsaSignature *sig;
 
   pkey = GNUNET_CRYPTO_rsa_private_key_get_public (key);
-  v = rsa_full_domain_hash (pkey, hash);
+  v = rsa_full_domain_hash (pkey,
+                            message,
+                            message_size);
   GNUNET_CRYPTO_rsa_public_key_free (pkey);
   if (NULL == v)   /* rsa_gcd_validate failed meaning */
     return NULL;   /* our *own* RSA key is malicious. */
@@ -1172,7 +1196,8 @@ GNUNET_CRYPTO_rsa_unblind (const struct 
GNUNET_CRYPTO_RsaSignature *sig,
 
 
 enum GNUNET_GenericReturnValue
-GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode *hash,
+GNUNET_CRYPTO_rsa_verify (const void *message,
+                          size_t message_size,
                           const struct GNUNET_CRYPTO_RsaSignature *sig,
                           const struct GNUNET_CRYPTO_RsaPublicKey *pkey)
 {
@@ -1182,7 +1207,9 @@ GNUNET_CRYPTO_rsa_verify (const struct GNUNET_HashCode 
*hash,
 
   BENCHMARK_START (rsa_verify);
 
-  r = rsa_full_domain_hash (pkey, hash);
+  r = rsa_full_domain_hash (pkey,
+                            message,
+                            message_size);
   if (NULL == r)
   {
     GNUNET_break_op (0);
@@ -1260,4 +1287,4 @@ GNUNET_CRYPTO_rsa_signature_dup (const struct 
GNUNET_CRYPTO_RsaSignature *sig)
 }
 
 
-/* end of util/rsa.c */
+/* end of crypto_rsa.c */
diff --git a/src/lib/util/perf_crypto_rsa.c b/src/lib/util/perf_crypto_rsa.c
index ab9f362cf..721973b1a 100644
--- a/src/lib/util/perf_crypto_rsa.c
+++ b/src/lib/util/perf_crypto_rsa.c
@@ -45,9 +45,8 @@ eval (unsigned int len)
   struct GNUNET_CRYPTO_RsaBlindingKeySecret bsec[10];
   unsigned int i;
   char sbuf[128];
-  void *bbuf;
-  size_t bbuf_len;
   struct GNUNET_HashCode hc;
+  struct GNUNET_CRYPTO_RsaBlindedMessage bm;
 
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < 10; i++)
@@ -95,17 +94,17 @@ eval (unsigned int len)
   for (i = 0; i < 10; i++)
   {
     GNUNET_CRYPTO_rsa_blind (&hc,
+                             sizeof (hc),
                              &bsec[i],
                              public_key,
-                             &bbuf,
-                             &bbuf_len);
-    GNUNET_free (bbuf);
+                             &bm);
+    GNUNET_CRYPTO_rsa_blinded_message_free (&bm);
   }
   printf ("10x %u-blinding took %s\n",
           len,
           GNUNET_STRINGS_relative_time_to_string (
             GNUNET_TIME_absolute_get_duration (start),
-            GNUNET_YES));
+            true));
   GNUNET_snprintf (sbuf,
                    sizeof(sbuf),
                    "RSA %u-blinding",
@@ -116,16 +115,15 @@ eval (unsigned int len)
                        + GNUNET_TIME_absolute_get_duration
                          (start).rel_value_us / 1000LL), "ops/ms");
   GNUNET_CRYPTO_rsa_blind (&hc,
+                           sizeof (hc),
                            &bsec[0],
                            public_key,
-                           &bbuf,
-                           &bbuf_len);
+                           &bm);
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < 10; i++)
   {
     sig = GNUNET_CRYPTO_rsa_sign_blinded (private_key,
-                                          bbuf,
-                                          bbuf_len);
+                                          &bm);
     GNUNET_CRYPTO_rsa_signature_free (sig);
   }
   printf ("10x %u-signing took %s\n",
@@ -143,8 +141,7 @@ eval (unsigned int len)
                        + GNUNET_TIME_absolute_get_duration
                          (start).rel_value_us / 1000LL), "ops/ms");
   sig = GNUNET_CRYPTO_rsa_sign_blinded (private_key,
-                                        bbuf,
-                                        bbuf_len);
+                                        &bm);
   start = GNUNET_TIME_absolute_get ();
   for (i = 0; i < 10; i++)
   {
@@ -157,7 +154,7 @@ eval (unsigned int len)
           len,
           GNUNET_STRINGS_relative_time_to_string (
             GNUNET_TIME_absolute_get_duration (start),
-            GNUNET_YES));
+            true));
   GNUNET_snprintf (sbuf,
                    sizeof(sbuf),
                    "RSA %u-unblinding",
@@ -175,6 +172,7 @@ eval (unsigned int len)
   {
     GNUNET_assert (GNUNET_OK ==
                    GNUNET_CRYPTO_rsa_verify (&hc,
+                                             sizeof (hc),
                                              rsig,
                                              public_key));
   }
@@ -195,7 +193,7 @@ eval (unsigned int len)
   GNUNET_CRYPTO_rsa_signature_free (sig);
   GNUNET_CRYPTO_rsa_public_key_free (public_key);
   GNUNET_CRYPTO_rsa_private_key_free (private_key);
-  GNUNET_free (bbuf);
+  GNUNET_CRYPTO_rsa_blinded_message_free (&bm);
 }
 
 
diff --git a/src/lib/util/test_crypto_blind.c b/src/lib/util/test_crypto_blind.c
new file mode 100644
index 000000000..d7efd79ea
--- /dev/null
+++ b/src/lib/util/test_crypto_blind.c
@@ -0,0 +1,86 @@
+/*
+   This file is part of GNUnet
+   Copyright (C) 2014, 2015, 2023 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/test_crypto_blind.c
+ * @brief testcase for utility functions for blind signatures
+ * @author Christian Grothoff <grothoff@gnunet.org>
+ */
+#include "platform.h"
+#include <gcrypt.h>
+#include "gnunet_util_lib.h"
+
+
+int
+main (int argc,
+      char *argv[])
+{
+  struct GNUNET_CRYPTO_BlindSignPrivateKey *priv;
+  struct GNUNET_CRYPTO_BlindSignPublicKey *pub;
+  struct GNUNET_CRYPTO_BlindingInputValues *biv;
+  struct GNUNET_CRYPTO_BlindedMessage *bm;
+  struct GNUNET_CRYPTO_BlindedSignature *bsig;
+  struct GNUNET_CRYPTO_UnblindedSignature *sig;
+  union GNUNET_CRYPTO_BlindingSecretP bsec;
+  union GNUNET_CRYPTO_BlindSessionNonce nonce;
+
+  GNUNET_log_setup ("test-crypto-blind",
+                    "WARNING",
+                    NULL);
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &bsec,
+                              sizeof (bsec));
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &nonce,
+                              sizeof (nonce));
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_blind_sign_keys_create (&priv,
+                                                       &pub,
+                                                       GNUNET_CRYPTO_BSA_CS));
+  biv = GNUNET_CRYPTO_get_blinding_input_values (priv,
+                                                 &nonce,
+                                                 "salt");
+  bm = GNUNET_CRYPTO_message_blind_to_sign (pub,
+                                            &bsec,
+                                            &nonce,
+                                            "hello",
+                                            5,
+                                            biv);
+  bsig = GNUNET_CRYPTO_blind_sign (priv,
+                                   "salt",
+                                   bm);
+  sig = GNUNET_CRYPTO_blind_sig_unblind (bsig,
+                                         &bsec,
+                                         "hello",
+                                         5,
+                                         biv,
+                                         pub);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CRYPTO_blind_sig_verify (pub,
+                                                 sig,
+                                                 "hello",
+                                                 5));
+  GNUNET_CRYPTO_blinded_sig_decref (bsig);
+  GNUNET_CRYPTO_unblinded_sig_decref (sig);
+  GNUNET_CRYPTO_blinded_message_decref (bm);
+  GNUNET_CRYPTO_blind_sign_priv_decref (priv);
+  GNUNET_CRYPTO_blind_sign_pub_decref (pub);
+  return 0;
+}
diff --git a/src/lib/util/test_crypto_cs.c b/src/lib/util/test_crypto_cs.c
index 6fd2361fb..ee68db72f 100644
--- a/src/lib/util/test_crypto_cs.c
+++ b/src/lib/util/test_crypto_cs.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2021,2022 GNUnet e.V.
+   Copyright (C) 2021,2022, 2023 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
@@ -31,6 +31,7 @@
 
 #define ITER 25
 
+
 static void
 test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
 {
@@ -39,8 +40,10 @@ test_create_priv (struct GNUNET_CRYPTO_CsPrivateKey *priv)
    */
   struct GNUNET_CRYPTO_CsPrivateKey other_priv;
 
-  other_priv = *priv;
   GNUNET_CRYPTO_cs_private_key_generate (priv);
+  memset (&other_priv,
+          42,
+          sizeof (other_priv));
   GNUNET_assert (0 !=
                  GNUNET_memcmp (&other_priv.scalar,
                                 &priv->scalar));
@@ -56,9 +59,11 @@ test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey 
*priv,
    */
   struct GNUNET_CRYPTO_CsPublicKey other_pub;
 
-  other_pub = *pub;
   GNUNET_CRYPTO_cs_private_key_get_public (priv,
                                            pub);
+  memset (&other_pub,
+          42,
+          sizeof (other_pub));
   GNUNET_assert (0 !=
                  GNUNET_memcmp (&other_pub.point,
                                 &pub->point));
@@ -85,7 +90,7 @@ test_generate_pub (const struct GNUNET_CRYPTO_CsPrivateKey 
*priv,
 
 
 static void
-test_derive_rsecret (const struct GNUNET_CRYPTO_CsNonce *nonce,
+test_derive_rsecret (const struct GNUNET_CRYPTO_CsSessionNonce *nonce,
                      const struct GNUNET_CRYPTO_CsPrivateKey *priv,
                      struct GNUNET_CRYPTO_CsRSecret r[2])
 {
@@ -164,7 +169,7 @@ test_generate_rpublic (const struct GNUNET_CRYPTO_CsRSecret 
*r_priv,
 
 
 static void
-test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsNonce *blind_seed,
+test_derive_blindingsecrets (const struct GNUNET_CRYPTO_CsBlindingNonce 
*blind_seed,
                              struct GNUNET_CRYPTO_CsBlindingSecret bs[2])
 {
   /* TEST 1
@@ -176,7 +181,8 @@ test_derive_blindingsecrets (const struct 
GNUNET_CRYPTO_CsNonce *blind_seed,
           bs,
           sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
 
-  GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
+  GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed,
+                                            bs);
 
   GNUNET_assert (0 !=
                  memcmp (other_bs,
@@ -193,7 +199,8 @@ test_derive_blindingsecrets (const struct 
GNUNET_CRYPTO_CsNonce *blind_seed,
           sizeof(struct GNUNET_CRYPTO_CsBlindingSecret) * 2);
   for (unsigned int i = 0; i<ITER; i++)
   {
-    GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed, bs);
+    GNUNET_CRYPTO_cs_blinding_secrets_derive (blind_seed,
+                                              bs);
     GNUNET_assert (0 == memcmp (&other_bs[0],
                                 &bs[0],
                                 sizeof(struct GNUNET_CRYPTO_CsBlindingSecret)
@@ -209,7 +216,7 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
                     const void *msg,
                     size_t msg_len,
                     struct GNUNET_CRYPTO_CsC blinded_cs[2],
-                    struct GNUNET_CRYPTO_CsRPublic blinded_r_pub[2])
+                    struct GNUNET_CRYPTO_CSPublicRPairP *blinded_r_pub)
 {
   /* TEST 1
    * Check that the blinded c's and blinded r's
@@ -220,10 +227,8 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
           &blinded_cs[0],
           sizeof(struct GNUNET_CRYPTO_CsC) * 2);
 
-  struct GNUNET_CRYPTO_CsRPublic other_blinded_r_pub[2];
-  memcpy (&other_blinded_r_pub[0],
-          &blinded_r_pub[0],
-          sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
+  struct GNUNET_CRYPTO_CSPublicRPairP other_blinded_pub;
+  other_blinded_pub = *blinded_r_pub;
 
   GNUNET_CRYPTO_cs_calc_blinded_c (bs,
                                    r_pub,
@@ -236,9 +241,9 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
   GNUNET_assert (0 != memcmp (&other_blinded_c[0],
                               &blinded_cs[0],
                               sizeof(struct GNUNET_CRYPTO_CsC) * 2));
-  GNUNET_assert (0 != memcmp (&other_blinded_r_pub[0],
-                              &blinded_r_pub[0],
-                              sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
+  GNUNET_assert (0 !=
+                 GNUNET_memcmp (&other_blinded_pub,
+                                blinded_r_pub));
 
   /* TEST 2
    * Check if R' - aG -bX = R for b = 0
@@ -251,37 +256,41 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
     struct GNUNET_CRYPTO_Cs25519Point r_min_aG;
     struct GNUNET_CRYPTO_CsRPublic res;
 
-    GNUNET_assert (0 == crypto_scalarmult_ed25519_base_noclamp (
+    GNUNET_assert (0 ==
+                   crypto_scalarmult_ed25519_base_noclamp (
                      aG.y,
                      bs[b].alpha.d));
-
-    GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (
+    GNUNET_assert (0 ==
+                   crypto_scalarmult_ed25519_noclamp (
                      bX.y,
                      bs[b].beta.d,
                      pub->point.y));
-
-    GNUNET_assert (0 == crypto_core_ed25519_sub (
+    GNUNET_assert (0 ==
+                   crypto_core_ed25519_sub (
                      r_min_aG.y,
-                     blinded_r_pub[b].point.y,
+                     blinded_r_pub->r_pub[b].point.y,
                      aG.y));
-
     GNUNET_assert (0 == crypto_core_ed25519_sub (
                      res.point.y,
                      r_min_aG.y,
                      bX.y));
 
-    GNUNET_assert (0 == memcmp (&res, &r_pub[b], sizeof(struct
-                                                        
GNUNET_CRYPTO_CsRPublic)));
+    GNUNET_assert (0 ==
+                   memcmp (&res,
+                           &r_pub[b],
+                           sizeof(struct GNUNET_CRYPTO_CsRPublic)));
   }
 
 
   /* TEST 3
    * Check that the blinded r_pubs' are valid points
    */
-  GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
-                   blinded_r_pub[0].point.y));
-  GNUNET_assert (1 == crypto_core_ed25519_is_valid_point (
-                   blinded_r_pub[1].point.y));
+  GNUNET_assert (1 ==
+                 crypto_core_ed25519_is_valid_point (
+                   blinded_r_pub->r_pub[0].point.y));
+  GNUNET_assert (1 ==
+                 crypto_core_ed25519_is_valid_point (
+                   blinded_r_pub->r_pub[1].point.y));
 
   /* TEST 4
    * Check if function gives the same result for the same input.
@@ -289,9 +298,7 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
   memcpy (&other_blinded_c[0],
           &blinded_cs[0],
           sizeof(struct GNUNET_CRYPTO_CsC) * 2);
-  memcpy (&other_blinded_r_pub[0],
-          &blinded_r_pub[0],
-          sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2);
+  other_blinded_pub = *blinded_r_pub;
 
   for (unsigned int i = 0; i<ITER; i++)
   {
@@ -302,40 +309,37 @@ test_calc_blindedc (const struct 
GNUNET_CRYPTO_CsBlindingSecret bs[2],
                                      msg_len,
                                      blinded_cs,
                                      blinded_r_pub);
-    GNUNET_assert (0 == memcmp (&other_blinded_c[0],
-                                &blinded_cs[0],
-                                sizeof(struct GNUNET_CRYPTO_CsC) * 2));
-    GNUNET_assert (0 == memcmp (&other_blinded_r_pub[0],
-                                &blinded_r_pub[0],
-                                sizeof(struct GNUNET_CRYPTO_CsRPublic) * 2));
+    GNUNET_assert (0 ==
+                   memcmp (&other_blinded_c[0],
+                           &blinded_cs[0],
+                           sizeof(struct GNUNET_CRYPTO_CsC) * 2));
+    GNUNET_assert (0 ==
+                   GNUNET_memcmp (&other_blinded_pub,
+                                  blinded_r_pub));
   }
 }
 
 
 static void
-test_blind_sign (unsigned int *b,
-                 const struct GNUNET_CRYPTO_CsPrivateKey *priv,
+test_blind_sign (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_s)
+                 const struct GNUNET_CRYPTO_CsBlindedMessage *bm,
+                 struct GNUNET_CRYPTO_CsBlindSignature *cs_blind_sig)
 {
   /* TEST 1
    * Check that blinded_s is set
    */
-  struct GNUNET_CRYPTO_CsC other_blinded_s;
-  memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
-
-  *b = GNUNET_CRYPTO_cs_sign_derive (priv,
-                                     r,
-                                     c,
-                                     nonce,
-                                     blinded_s);
-
-  GNUNET_assert (0 == *b || 1 == *b);
-  GNUNET_assert (0 != memcmp (&other_blinded_s,
-                              blinded_s,
-                              sizeof(struct GNUNET_CRYPTO_CsBlindS)));
+  struct GNUNET_CRYPTO_CsBlindSignature other_blind_sig;
+
+  memset (&other_blind_sig,
+          44,
+          sizeof (other_blind_sig));
+  GNUNET_CRYPTO_cs_sign_derive (priv,
+                                r,
+                                bm,
+                                &other_blind_sig);
+  GNUNET_assert (0 == other_blind_sig.b ||
+                 1 == other_blind_sig.b);
 
   /* TEST 2
    * Check if s := rb + cbX
@@ -343,32 +347,29 @@ test_blind_sign (unsigned int *b,
    */
   struct GNUNET_CRYPTO_Cs25519Scalar cb_mul_x;
   struct GNUNET_CRYPTO_Cs25519Scalar s_min_rb;
-
+ 
   crypto_core_ed25519_scalar_mul (cb_mul_x.d,
-                                  c[*b].scalar.d,
+                                  bm->c[other_blind_sig.b].scalar.d,
                                   priv->scalar.d);
-
   crypto_core_ed25519_scalar_sub (s_min_rb.d,
-                                  blinded_s->scalar.d,
-                                  r[*b].scalar.d);
-
-  GNUNET_assert (0 == memcmp (&s_min_rb, &cb_mul_x, sizeof(struct
-                                                           
GNUNET_CRYPTO_Cs25519Scalar)));
+                                  other_blind_sig.s_scalar.scalar.d,
+                                  r[other_blind_sig.b].scalar.d);
+  GNUNET_assert (0 ==
+                 GNUNET_memcmp (&s_min_rb,
+                                &cb_mul_x));
 
   /* TEST 3
    * Check if function gives the same result for the same input.
    */
-  memcpy (&other_blinded_s, blinded_s, sizeof(struct GNUNET_CRYPTO_CsBlindS));
   for (unsigned int i = 0; i<ITER; i++)
   {
-    unsigned int other_b;
-
-    other_b = GNUNET_CRYPTO_cs_sign_derive (priv, r, c, nonce, blinded_s);
-
-    GNUNET_assert (other_b == *b);
-    GNUNET_assert (0 == memcmp (&other_blinded_s,
-                                blinded_s,
-                                sizeof(struct GNUNET_CRYPTO_CsBlindS)));
+    GNUNET_CRYPTO_cs_sign_derive (priv,
+                                  r,
+                                  bm,
+                                  cs_blind_sig);
+    GNUNET_assert (0 ==
+                   GNUNET_memcmp (&other_blind_sig,
+                                  cs_blind_sig));
   }
 }
 
@@ -386,7 +387,9 @@ test_unblinds (const struct GNUNET_CRYPTO_CsBlindS 
*blinded_signature_scalar,
           signature_scalar,
           sizeof(struct GNUNET_CRYPTO_CsS));
 
-  GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar, bs, signature_scalar);
+  GNUNET_CRYPTO_cs_unblind (blinded_signature_scalar,
+                            bs,
+                            signature_scalar);
 
   GNUNET_assert (0 != memcmp (&other_signature_scalar,
                               signature_scalar,
@@ -431,23 +434,24 @@ test_blind_verify (const struct GNUNET_CRYPTO_CsSignature 
*sig,
    * Test verifies the blinded signature sG == Rb + cbX
    */
   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_mul_pub;
-  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (c_mul_pub.y,
-                                                         c->scalar.d,
-                                                         pub->point.y));
-
   struct GNUNET_CRYPTO_Cs25519Point r_add_c_mul_pub;
-  GNUNET_assert (0 == crypto_core_ed25519_add (r_add_c_mul_pub.y,
-                                               sig->r_point.point.y,
-                                               c_mul_pub.y));
 
-  GNUNET_assert (0 == memcmp (sig_scal_mul_base.y,
-                              r_add_c_mul_pub.y,
-                              sizeof(struct GNUNET_CRYPTO_Cs25519Point)));
+  GNUNET_assert (0 ==
+                 crypto_scalarmult_ed25519_base_noclamp (
+                   sig_scal_mul_base.y,
+                   sig->s_scalar.scalar.d));
+  GNUNET_assert (0 ==
+                 crypto_scalarmult_ed25519_noclamp (c_mul_pub.y,
+                                                    c->scalar.d,
+                                                    pub->point.y));
+  GNUNET_assert (0 ==
+                 crypto_core_ed25519_add (r_add_c_mul_pub.y,
+                                          sig->r_point.point.y,
+                                          c_mul_pub.y));
+  GNUNET_assert (0 ==
+                 GNUNET_memcmp (sig_scal_mul_base.y,
+                                r_add_c_mul_pub.y));
 }
 
 
@@ -490,6 +494,9 @@ main (int argc,
 
   struct GNUNET_CRYPTO_CsPrivateKey priv;
 
+  GNUNET_log_setup ("test-crypto-cs",
+                    "INFO",
+                    NULL);
   memset (&priv,
           42,
           sizeof (priv));
@@ -503,11 +510,11 @@ main (int argc,
   test_generate_pub (&priv,
                      &pub);
 
-  // derive nonce
-  struct GNUNET_CRYPTO_CsNonce nonce;
+  // set nonce
+  struct GNUNET_CRYPTO_CsSessionNonce nonce;
   GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CRYPTO_kdf (nonce.nonce,
-                                    sizeof(nonce.nonce),
+                 GNUNET_CRYPTO_kdf (&nonce,
+                                    sizeof(nonce),
                                     "nonce",
                                     strlen ("nonce"),
                                     "nonce_secret",
@@ -539,21 +546,26 @@ main (int argc,
 
   // generate blinding secrets
   struct GNUNET_CRYPTO_CsBlindingSecret blindingsecrets[2];
+  struct GNUNET_CRYPTO_CsBlindingNonce bnonce;
 
+  memset (&bnonce,
+          42,
+          sizeof (bnonce));
   memset (blindingsecrets,
           42,
           sizeof (blindingsecrets));
-  test_derive_blindingsecrets (&nonce,
+  test_derive_blindingsecrets (&bnonce,
                                blindingsecrets);
 
   // calculate blinded c's
+  struct GNUNET_CRYPTO_CsBlindedMessage bm; 
   struct GNUNET_CRYPTO_CsC blinded_cs[2];
-  struct GNUNET_CRYPTO_CsRPublic blinded_r_pubs[2];
+  struct GNUNET_CRYPTO_CSPublicRPairP blinded_r_pubs;
 
   memset (blinded_cs,
           42,
           sizeof (blinded_cs));
-  memset (blinded_r_pubs,
+  memset (&blinded_r_pubs,
           42,
           sizeof (blinded_r_pubs));
   test_calc_blindedc (blindingsecrets,
@@ -562,31 +574,30 @@ main (int argc,
                       message,
                       message_len,
                       blinded_cs,
-                      blinded_r_pubs);
+                      &blinded_r_pubs);
 
   // ---------- actions performed by signer
   // sign blinded c's and get b and s in return
-  unsigned int b;
-  struct GNUNET_CRYPTO_CsBlindS blinded_s;
+  struct GNUNET_CRYPTO_CsBlindSignature blinded_s;
 
   memset (&blinded_s,
           42,
           sizeof (blinded_s));
-  test_blind_sign (&b,
-                   &priv,
+  bm.c[0] = blinded_cs[0];
+  bm.c[1] = blinded_cs[1];
+  bm.nonce = nonce;
+  test_blind_sign (&priv,
                    r_secrets,
-                   blinded_cs,
-                   &nonce,
+                   &bm,
                    &blinded_s);
-
   // verify blinded signature
   struct GNUNET_CRYPTO_CsSignature blinded_signature;
 
-  blinded_signature.r_point = r_publics[b];
-  blinded_signature.s_scalar.scalar = blinded_s.scalar;
+  blinded_signature.r_point = r_publics[blinded_s.b];
+  blinded_signature.s_scalar.scalar = blinded_s.s_scalar.scalar;
   test_blind_verify (&blinded_signature,
                      &pub,
-                     &blinded_cs[b]);
+                     &blinded_cs[blinded_s.b]);
 
   // ---------- actions performed by user
   struct GNUNET_CRYPTO_CsS sig_scalar;
@@ -594,13 +605,13 @@ main (int argc,
   memset (&sig_scalar,
           42,
           sizeof (sig_scalar));
-  test_unblinds (&blinded_s,
-                 &blindingsecrets[b],
+  test_unblinds (&blinded_s.s_scalar,
+                 &blindingsecrets[blinded_s.b],
                  &sig_scalar);
 
   // verify unblinded signature
   struct GNUNET_CRYPTO_CsSignature signature;
-  signature.r_point = blinded_r_pubs[b];
+  signature.r_point = blinded_r_pubs.r_pub[blinded_s.b];
   signature.s_scalar = sig_scalar;
   test_verify (&signature,
                &pub,
diff --git a/src/lib/util/test_crypto_rsa.c b/src/lib/util/test_crypto_rsa.c
index 9f2ddb66e..c513a68fe 100644
--- a/src/lib/util/test_crypto_rsa.c
+++ b/src/lib/util/test_crypto_rsa.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet
-   Copyright (C) 2014,2015 GNUnet e.V.
+   Copyright (C) 2014, 2015, 2023 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
@@ -47,10 +47,10 @@ main (int argc,
   struct GNUNET_CRYPTO_RsaSignature *bsig;
   struct GNUNET_CRYPTO_RsaBlindingKeySecret bsec;
   struct GNUNET_HashCode hash;
-  void *blind_buf;
-  size_t bsize;
 
-  GNUNET_log_setup ("test-rsa", "WARNING", NULL);
+  GNUNET_log_setup ("test-crypto-rsa",
+                    "WARNING",
+                    NULL);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               rnd_blk,
                               RND_BLK_SIZE);
@@ -60,36 +60,48 @@ main (int argc,
   priv = GNUNET_CRYPTO_rsa_private_key_create (KEY_SIZE);
   priv_copy = GNUNET_CRYPTO_rsa_private_key_dup (priv);
   GNUNET_assert (NULL != priv_copy);
-  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv, priv_copy));
+  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_private_key_cmp (priv,
+                                                         priv_copy));
   pub = GNUNET_CRYPTO_rsa_private_key_get_public (priv);
 
   /* Encoding */
   size_t size;
   void *enc;
   enc = NULL;
-  size = GNUNET_CRYPTO_rsa_private_key_encode (priv, &enc);
+  size = GNUNET_CRYPTO_rsa_private_key_encode (priv,
+                                               &enc);
 
   /* Decoding */
   GNUNET_CRYPTO_rsa_private_key_free (priv);
   priv = NULL;
-  priv = GNUNET_CRYPTO_rsa_private_key_decode (enc, size);
+  priv = GNUNET_CRYPTO_rsa_private_key_decode (enc,
+                                               size);
   GNUNET_assert (NULL != priv);
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
-                              enc, size);
-  GNUNET_assert (NULL == GNUNET_CRYPTO_rsa_private_key_decode (enc, size));
-  (void) fprintf (stderr, "The above warning is expected.\n");
+                              enc,
+                              size);
+  GNUNET_assert (NULL ==
+                 GNUNET_CRYPTO_rsa_private_key_decode (enc,
+                                                       size));
+  (void) fprintf (stderr,
+                  "The above warning is expected.\n");
   GNUNET_free (enc);
 
   /* try ordinary sig first */
   sig = GNUNET_CRYPTO_rsa_sign_fdh (priv,
-                                    &hash);
+                                    &hash,
+                                    sizeof (hash));
   sig_copy = GNUNET_CRYPTO_rsa_signature_dup (sig);
   GNUNET_assert (NULL != sig);
-  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig, sig_copy));
+  GNUNET_assert (0 == GNUNET_CRYPTO_rsa_signature_cmp (sig,
+                                                       sig_copy));
   pub_copy = GNUNET_CRYPTO_rsa_public_key_dup (pub);
   GNUNET_assert (NULL != pub_copy);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub_copy));
+                 GNUNET_CRYPTO_rsa_verify (&hash,
+                                           sizeof (hash),
+                                           sig,
+                                           pub_copy));
   {
     void *buf;
     size_t buf_size;
@@ -107,38 +119,48 @@ main (int argc,
                                                buf_size);
     GNUNET_free (buf);
     GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CRYPTO_rsa_verify (&hash, sig2, pub2));
+                   GNUNET_CRYPTO_rsa_verify (&hash,
+                                             sizeof (hash),
+                                             sig2,
+                                             pub2));
     GNUNET_CRYPTO_rsa_public_key_free (pub2);
     GNUNET_CRYPTO_rsa_signature_free (sig2);
   }
   /* corrupt our hash and see if the signature is still valid */
-  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, &hash,
-                              sizeof(struct GNUNET_HashCode));
-  GNUNET_assert (GNUNET_OK != GNUNET_CRYPTO_rsa_verify (&hash,
-                                                        sig,
-                                                        pub));
-  (void) fprintf (stderr, "The above warning is expected.\n");
+  GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
+                              &hash,
+                              sizeof(hash));
+  GNUNET_assert (GNUNET_OK !=
+                 GNUNET_CRYPTO_rsa_verify (&hash,
+                                           sizeof (hash),
+                                           sig,
+                                           pub));
+  (void) fprintf (stderr,
+                  "The above warning is expected.\n");
   GNUNET_CRYPTO_rsa_signature_free (sig);
 
   /* test blind signing */
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
                               &bsec,
                               sizeof(bsec));
+  struct GNUNET_CRYPTO_RsaBlindedMessage bm;
   GNUNET_CRYPTO_rsa_blind (&hash,
+                           sizeof (hash),
                            &bsec,
                            pub,
-                           &blind_buf, &bsize);
-  GNUNET_assert (0 != bsize);
+                           &bm);
   bsig = GNUNET_CRYPTO_rsa_sign_blinded (priv,
-                                         blind_buf,
-                                         bsize);
-  GNUNET_free (blind_buf);
+                                         &bm);
+  GNUNET_CRYPTO_rsa_blinded_message_free (&bm);
   sig = GNUNET_CRYPTO_rsa_unblind (bsig,
                                    &bsec,
                                    pub);
   GNUNET_CRYPTO_rsa_signature_free (bsig);
   GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CRYPTO_rsa_verify (&hash, sig, pub));
+                 GNUNET_CRYPTO_rsa_verify (&hash,
+                                           sizeof (hash),
+                                           sig,
+                                           pub));
   GNUNET_CRYPTO_rsa_signature_free (sig);
   GNUNET_CRYPTO_rsa_signature_free (sig_copy);
   GNUNET_CRYPTO_rsa_private_key_free (priv);

-- 
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]