gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] 07/11: WiP: age-withdraw, added TALER_age_restriction_c


From: gnunet
Subject: [taler-exchange] 07/11: WiP: age-withdraw, added TALER_age_restriction_commit_from_base, 6/n
Date: Mon, 13 Mar 2023 00:33:03 +0100

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

oec pushed a commit to branch master
in repository exchange.

commit 9c66f270340336c263cdbe1a69fd0bfa7d75ca05
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Sun Mar 12 17:21:33 2023 +0100

    WiP: age-withdraw, added TALER_age_restriction_commit_from_base, 6/n
    
    Added TALER_age_restriction_commit_from_base in util/age_restriction.c,
    to create a age commitment and proof from a coin's private key as
    defined in
    https://docs.taler.net/core/api-exchange.html#withdraw-with-age-restriction
---
 .../taler-exchange-httpd_age-withdraw_reveal.c     |  21 +-
 src/include/taler_crypto_lib.h                     |  39 +++
 src/util/age_restriction.c                         | 268 ++++++++++++++++-----
 3 files changed, 245 insertions(+), 83 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c 
b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
index 7ecd0b37..b378e0e2 100644
--- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
+++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
@@ -28,22 +28,6 @@
 #include "taler-exchange-httpd_responses.h"
 #include "taler-exchange-httpd_keys.h"
 
-/**
- * Clients have to prove that the public keys for all age groups larger than
- * the allowed maximum age group are derived by scalar multiplication from this
- * Edx25519 public key (in Crockford Base32 encoding):
- *
- *       DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG
- *
- * The private key was chosen randomly and then deleted.
- */
-static struct GNUNET_CRYPTO_Edx25519PublicKey publishedBaseKey = {
-  .q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
-           0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
-           0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
-           0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
-};
-
 /**
  * State for an /age-withdraw/$ACH/reveal operation.
  */
@@ -360,17 +344,15 @@ denomination_is_valid (
     connection,
     result);
 
-  /* Does the denomination exist? */
   if (NULL == dks)
   {
+    /* The denomination doesn't exist */
     GNUNET_assert (result != NULL);
     /* Note: a HTTP-response has been queued and result has been set by
      * TEH_keys_denominations_by_hash2 */
     return false;
   }
 
-  /* Is the denomation still and already valid? */
-
   if (GNUNET_TIME_absolute_is_past (dks->meta.expire_withdraw.abs_time))
   {
     /* This denomination is past the expiration time for withdraws */
@@ -582,6 +564,7 @@ verify_commitment_and_max_age (
   for (uint32_t i = 0; i < num_coins; i++)
   {
     /* FIXME:oec:  Calculate new coins and blinded hashes */
+    /*TALER_age_restriction_commit_from_base(); */
   }
 
   return GNUNET_SYSERR;
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index c285a38e..f7462d09 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -18,6 +18,7 @@
  * @brief taler-specific crypto functions
  * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  * @author Christian Grothoff <christian@grothoff.org>
+ * @author Özgür Kesim <oec-taler@kesim.org>
  */
 #if ! defined (__TALER_UTIL_LIB_H_INSIDE__)
 #error "Only <taler_util.h> can be included directly."
@@ -5926,4 +5927,42 @@ void
 TALER_age_commitment_proof_free (
   struct TALER_AgeCommitmentProof *p);
 
+
+/**
+ * @brief For age-withdraw, clients have to prove that the public keys for all
+ * age groups larger than the allowed maximum age group are derived by scalar
+ * multiplication from this Edx25519 public key (in Crockford Base32 encoding):
+ *
+ *       DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG
+ *
+ * Its private key was chosen randomly and then deleted.
+ */
+extern struct
+#ifndef AGE_RESTRICTION_WITH_ECDSA
+GNUNET_CRYPTO_Edx25519PublicKey
+#else
+GNUNET_CRYPTO_EcdsaPublicKey
+#endif
+TALER_age_commitment_base_public_key;
+
+/**
+ * @brief Similiar to TALER_age_restriction_commit, but takes the coin's
+ * private key as seed input and calculates the public keys in the slots larger
+ * than the given age as derived from TALER_age_commitment_base_public_key.
+ *
+ * See 
https://docs.taler.net/core/api-exchange.html#withdraw-with-age-restriction
+ *
+ * @param mask The age mask, defining the age groups
+ * @param max_age The maximum age for this coin.
+ * @param coin_priv The private key of the coin from which we derive the age 
restriction
+ * @param[out] comm_proof The commitment and proof for age restriction for age 
@a max_age
+ */
+enum GNUNET_GenericReturnValue
+TALER_age_restriction_commit_from_base (
+  const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+  const struct TALER_AgeMask *mask,
+  uint8_t max_age,
+  struct TALER_AgeCommitmentProof *comm_proof);
+
+
 #endif
diff --git a/src/util/age_restriction.c b/src/util/age_restriction.c
index f4ac9abe..594e1d46 100644
--- a/src/util/age_restriction.c
+++ b/src/util/age_restriction.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2022 Taler Systems SA
+  Copyright (C) 2022-2023 Taler Systems SA
 
   TALER 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
@@ -24,6 +24,19 @@
 #include <gnunet/gnunet_json_lib.h>
 #include <gcrypt.h>
 
+struct
+#ifndef AGE_RESTRICTION_WITH_ECDSA
+GNUNET_CRYPTO_Edx25519PublicKey
+#else
+GNUNET_CRYPTO_EcdsaPublicKey
+#endif
+TALER_age_commitment_base_public_key = {
+  .q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
+           0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
+           0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
+           0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
+};
+
 void
 TALER_age_commitment_hash (
   const struct TALER_AgeCommitment *commitment,
@@ -82,36 +95,78 @@ get_age_group (
 }
 
 
+#ifdef AGE_RESTRICTION_WITH_ECDSA
+/* @brief Helper function to generate a ECDSA private key
+ *
+ * @param seed Input seed
+ * @param size Size of the seed in bytes
+ * @param[out] pkey ECDSA private key
+ * @return GNUNET_OK on success
+ */
+static enum GNUNET_GenericReturnValue
+ecdsa_create_from_seed (
+  const void *seed,
+  size_t seed_size,
+  struct GNUNET_CRYPTO_EcdsaPrivateKey *key)
+{
+  enum GNUNET_GenericReturnValue ret;
+  ret = GNUNET_CRYPTO_kdf (key,
+                           sizeof (*key),
+                           &seed,
+                           seed_size,
+                           "age commitment",
+                           sizeof ("age commitment") - 1,
+                           NULL, 0);
+  if (GNUNET_OK != ret)
+    return ret;
+
+  /* See GNUNET_CRYPTO_ecdsa_key_create */
+  key->d[0] &= 248;
+  key->d[31] &= 127;
+  key->d[31] |= 64;
+
+  return GNUNET_OK;
+}
+
+
+#endif
+
+
 enum GNUNET_GenericReturnValue
 TALER_age_restriction_commit (
   const struct TALER_AgeMask *mask,
   const uint8_t age,
   const struct GNUNET_HashCode *seed,
-  struct TALER_AgeCommitmentProof *new)
+  struct TALER_AgeCommitmentProof *ncp)
 {
   struct GNUNET_HashCode seed_i;
-  uint8_t num_pub = __builtin_popcount (mask->bits) - 1;
-  uint8_t num_priv = get_age_group (mask, age);
+  uint8_t num_pub;
+  uint8_t num_priv;
   size_t i;
 
+  GNUNET_assert (NULL != mask);
   GNUNET_assert (NULL != seed);
-  GNUNET_assert (NULL != new);
+  GNUNET_assert (NULL != ncp);
   GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
+
+  num_pub = __builtin_popcount (mask->bits) - 1;
+  num_priv = get_age_group (mask, age);
+
   GNUNET_assert (31 > num_priv);
   GNUNET_assert (num_priv <= num_pub);
 
   seed_i = *seed;
-  new->commitment.mask.bits = mask->bits;
-  new->commitment.num = num_pub;
-  new->proof.num = num_priv;
-  new->proof.keys = NULL;
+  ncp->commitment.mask.bits = mask->bits;
+  ncp->commitment.num = num_pub;
+  ncp->proof.num = num_priv;
+  ncp->proof.keys = NULL;
 
-  new->commitment.keys = GNUNET_new_array (
+  ncp->commitment.keys = GNUNET_new_array (
     num_pub,
     struct TALER_AgeCommitmentPublicKeyP);
 
   if (0 < num_priv)
-    new->proof.keys = GNUNET_new_array (
+    ncp->proof.keys = GNUNET_new_array (
       num_priv,
       struct TALER_AgeCommitmentPrivateKeyP);
 
@@ -126,47 +181,33 @@ TALER_age_restriction_commit (
 
     /* Only save the private keys for age groups less than num_priv */
     if (i < num_priv)
-      pkey = &new->proof.keys[i];
+      pkey = &ncp->proof.keys[i];
 
 #ifndef AGE_RESTRICTION_WITH_ECDSA
     GNUNET_CRYPTO_edx25519_key_create_from_seed (&seed_i,
                                                  sizeof(seed_i),
                                                  &pkey->priv);
     GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
-                                           &new->commitment.keys[i].pub);
-    seed_i.bits[0] += 1;
-  }
-
-  return GNUNET_OK;
+                                           &ncp->commitment.keys[i].pub);
 #else
-    if  (GNUNET_OK !=
-         GNUNET_CRYPTO_kdf (pkey,
-                            sizeof (*pkey),
-                            &salti,
-                            sizeof (salti),
-                            "age commitment",
-                            strlen ("age commitment"),
-                            NULL, 0))
-      goto FAIL;
-
-    /* See GNUNET_CRYPTO_ecdsa_key_create */
-    pkey->priv.d[0] &= 248;
-    pkey->priv.d[31] &= 127;
-    pkey->priv.d[31] |= 64;
+    if (GNUNET_OK !=
+        ecdsa_create_from_seed (&seed_i,
+                                sizeof(seed_i),
+                                &pkey->priv))
+    {
+      GNUNET_free (ncp->commitment.keys);
+      GNUNET_free (ncp->proof.keys);
+      return GNUNET_SYSERR;
+    }
 
     GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
-                                        &new->commitment.keys[i].pub);
+                                        &ncp->commitment.keys[i].pub);
+#endif
 
+    seed_i.bits[0] += 1;
   }
 
   return GNUNET_OK;
-
-FAIL:
-  GNUNET_free (new->commitment.keys);
-  if (NULL != new->proof.keys)
-    GNUNET_free (new->proof.keys);
-  return GNUNET_SYSERR;
-#endif
 }
 
 
@@ -216,33 +257,30 @@ TALER_age_commitment_derive (
       &newacp->proof.keys[i].priv);
   }
 #else
-  char label[sizeof(uint64_t) + 1] = {0};
-
-  /* Because GNUNET_CRYPTO_ecdsa_public_key_derive expects char * (and calls
-   * strlen on it), we must avoid 0's in the label.  */
-  uint64_t nz_salt = salt | 0x8040201008040201;
-  memcpy (label, &nz_salt, sizeof(nz_salt));
-
-  /* 1. Derive the public keys */
-  for (size_t i = 0; i < orig->commitment.num; i++)
   {
-    GNUNET_CRYPTO_ecdsa_public_key_derive (
-      &orig->commitment.keys[i].pub,
-      label,
-      "age commitment derive",
-      &newacp->commitment.keys[i].pub);
-  }
+    const char *label = GNUNET_h2s (salt);
 
-  /* 2. Derive the private keys */
-  for (size_t i = 0; i < orig->proof.num; i++)
-  {
-    struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
-    priv = GNUNET_CRYPTO_ecdsa_private_key_derive (
-      &orig->proof.keys[i].priv,
-      label,
-      "age commitment derive");
-    newacp->proof.keys[i].priv = *priv;
-    GNUNET_free (priv);
+    /* 1. Derive the public keys */
+    for (size_t i = 0; i < orig->commitment.num; i++)
+    {
+      GNUNET_CRYPTO_ecdsa_public_key_derive (
+        &orig->commitment.keys[i].pub,
+        label,
+        "age commitment derive",
+        &newacp->commitment.keys[i].pub);
+    }
+
+    /* 2. Derive the private keys */
+    for (size_t i = 0; i < orig->proof.num; i++)
+    {
+      struct GNUNET_CRYPTO_EcdsaPrivateKey *priv;
+      priv = GNUNET_CRYPTO_ecdsa_private_key_derive (
+        &orig->proof.keys[i].priv,
+        label,
+        "age commitment derive");
+      newacp->proof.keys[i].priv = *priv;
+      GNUNET_free (priv);
+    }
   }
 #endif
 
@@ -546,4 +584,106 @@ TALER_age_mask_to_string (
 }
 
 
+enum GNUNET_GenericReturnValue
+TALER_age_restriction_commit_from_base (
+  const struct TALER_CoinSpendPrivateKeyP *coin_priv,
+  const struct TALER_AgeMask *mask,
+  uint8_t max_age,
+  struct TALER_AgeCommitmentProof *ncp)
+{
+  struct GNUNET_HashCode seed_i = {0};
+  uint8_t num_pub;
+  uint8_t num_priv;
+
+  GNUNET_assert (NULL != mask);
+  GNUNET_assert (NULL != coin_priv);
+  GNUNET_assert (NULL != ncp);
+  GNUNET_assert (mask->bits & 1); /* fist bit must have been set */
+
+  num_pub = __builtin_popcount (mask->bits) - 1;
+  num_priv = get_age_group (mask, max_age);
+
+  GNUNET_assert (31 > num_priv);
+  GNUNET_assert (num_priv <= num_pub);
+
+  ncp->commitment.mask.bits = mask->bits;
+  ncp->commitment.num = num_pub;
+  ncp->proof.num = num_priv;
+  ncp->proof.keys = NULL;
+
+  ncp->commitment.keys = GNUNET_new_array (
+    num_pub,
+    struct TALER_AgeCommitmentPublicKeyP);
+
+  if (0 < num_priv)
+    ncp->proof.keys = GNUNET_new_array (
+      num_priv,
+      struct TALER_AgeCommitmentPrivateKeyP);
+
+  /* Create as many private keys as allow with max_age and derive the
+   * corresponding public keys.  The rest of the needed public keys are created
+   * by scalar mulitplication with the TALER_age_commitment_base_public_key. */
+  for (size_t i = 0; i < num_pub; i++)
+  {
+    enum GNUNET_GenericReturnValue ret;
+    const char *label = i < num_priv ? "age-commitment" : "age-factor";
+
+    ret = GNUNET_CRYPTO_kdf (&seed_i, sizeof(seed_i),
+                             coin_priv, sizeof(*coin_priv),
+                             label, strlen (label),
+                             &i, sizeof(i),
+                             NULL, 0);
+    GNUNET_assert (GNUNET_OK == ret);
+
+    /* Only generate and save the private keys and public keys for age groups
+     * less than num_priv */
+    if (i < num_priv)
+    {
+      struct TALER_AgeCommitmentPrivateKeyP *pkey = &ncp->proof.keys[i];
+
+#ifndef AGE_RESTRICTION_WITH_ECDSA
+      GNUNET_CRYPTO_edx25519_key_create_from_seed (&seed_i,
+                                                   sizeof(seed_i),
+                                                   &pkey->priv);
+      GNUNET_CRYPTO_edx25519_key_get_public (&pkey->priv,
+                                             &ncp->commitment.keys[i].pub);
+#else
+      if (GNUNET_OK != ecdsa_create_from_seed (&seed_i,
+                                               sizeof(seed_i),
+                                               &pkey->priv))
+      {
+        GNUNET_free (ncp->commitment.keys);
+        GNUNET_free (ncp->proof.keys);
+        return GNUNET_SYSERR;
+      }
+      GNUNET_CRYPTO_ecdsa_key_get_public (&pkey->priv,
+                                          &ncp->commitment.keys[i].pub);
+#endif
+    }
+    else
+    {
+      /* For all indices larger than num_priv, derive a public key from
+       * TALER_age_commitment_base_public_key by scalar multiplication */
+#ifndef AGE_RESTRICTION_WITH_ECDSA
+      GNUNET_CRYPTO_edx25519_public_key_derive (
+        &TALER_age_commitment_base_public_key,
+        &seed_i,
+        sizeof(seed_i),
+        &ncp->commitment.keys[i].pub);
+#else
+
+      GNUNET_CRYPTO_ecdsa_public_key_derive (
+        &TALER_age_commitment_base_public_key,
+        GNUNET_h2s (&seed_i),
+        "age withdraw",
+        &ncp->commitment.keys[i].pub);
+#endif
+    }
+  }
+
+  return GNUNET_OK;
+
+}
+
+
 /* end util/age_restriction.c */

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