gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: age commitment: json parser help


From: gnunet
Subject: [taler-exchange] branch master updated: age commitment: json parser helper and support for purses added
Date: Mon, 27 Jun 2022 17:39:11 +0200

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

oec pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new cddfaf00 age commitment: json parser helper and support for purses 
added
cddfaf00 is described below

commit cddfaf007f4ac22e224f3df5f0151a0d620fb131
Author: Özgür Kesim <oec-taler@kesim.org>
AuthorDate: Mon Jun 27 17:38:11 2022 +0200

    age commitment: json parser helper and support for purses added
---
 src/exchange/taler-exchange-httpd_purses_create.c  |  57 +++++++++++-
 src/exchange/taler-exchange-httpd_purses_deposit.c |  57 +++++++++++-
 src/include/taler_json_lib.h                       |  23 +++++
 src/json/json_helper.c                             | 103 +++++++++++++++++++++
 src/json/json_pack.c                               |  34 +++++++
 src/lib/exchange_api_purse_deposit.c               |  44 ++++-----
 6 files changed, 289 insertions(+), 29 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_purses_create.c 
b/src/exchange/taler-exchange-httpd_purses_create.c
index a981ba58..2c803234 100644
--- a/src/exchange/taler-exchange-httpd_purses_create.c
+++ b/src/exchange/taler-exchange-httpd_purses_create.c
@@ -456,6 +456,10 @@ parse_coin (struct MHD_Connection *connection,
             struct Coin *coin,
             const json_t *jcoin)
 {
+  struct TALER_AgeAttestation attest = {0};
+  bool no_attest = true;
+  struct TALER_AgeCommitment age_commitment = {0};
+  bool no_age_commitment = true;
   struct GNUNET_JSON_Specification spec[] = {
     TALER_JSON_spec_amount ("amount",
                             TEH_currency,
@@ -465,10 +469,13 @@ parse_coin (struct MHD_Connection *connection,
     TALER_JSON_spec_denom_sig ("ub_sig",
                                &coin->cpi.denom_sig),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &coin->cpi.h_age_commitment),
-      &coin->cpi.no_age_commitment),
-    // FIXME-Oec: proof of age is missing.
+      GNUNET_JSON_spec_fixed_auto ("attest",
+                                   &attest),
+      &no_attest),
+    GNUNET_JSON_spec_mark_optional (
+      TALER_JSON_spec_age_commitment ("age_commitment",
+                                      &age_commitment),
+      &no_age_commitment),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                  &coin->coin_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
@@ -591,6 +598,48 @@ parse_coin (struct MHD_Connection *connection,
                    TALER_amount_subtract (&coin->amount_minus_fee,
                                           &coin->amount,
                                           &coin->deposit_fee));
+
+    // Check and verify the age restriction.  Needs to happen before
+    // coin-signature check, because we set the h_age_commitment here.
+    {
+      if (no_attest != no_age_commitment)
+
+      {
+        GNUNET_break (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           /* FIXME: other error code? */
+                                           
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
+                                           "mismatch of attest and 
age_commitment");
+      }
+
+      if (! no_age_commitment)
+      {
+        // attestation must be valid.
+        if (GNUNET_OK !=
+            TALER_age_commitment_verify (
+              &age_commitment,
+              pcc->min_age,
+              &attest))
+        {
+          GNUNET_break (0);
+          return TALER_MHD_reply_with_error (connection,
+                                             MHD_HTTP_BAD_REQUEST,
+                                             /* FIXME: other error code? */
+                                             
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
+                                             "invalid attest for minimum age");
+        }
+
+        // Save the hash of the age commitment in the coin's public info, so we
+        // can verify the signature later.
+        TALER_age_commitment_hash (&age_commitment,
+                                   &coin->cpi.h_age_commitment);
+        coin->cpi.no_age_commitment = false;
+
+      }
+    }
+
+
     /* check coin signature */
     switch (dk->denom_pub.cipher)
     {
diff --git a/src/exchange/taler-exchange-httpd_purses_deposit.c 
b/src/exchange/taler-exchange-httpd_purses_deposit.c
index 50ed582a..d65610dc 100644
--- a/src/exchange/taler-exchange-httpd_purses_deposit.c
+++ b/src/exchange/taler-exchange-httpd_purses_deposit.c
@@ -300,6 +300,10 @@ parse_coin (struct MHD_Connection *connection,
             struct Coin *coin,
             const json_t *jcoin)
 {
+  struct TALER_AgeAttestation attest = {0};
+  bool no_attest = true;
+  struct TALER_AgeCommitment age_commitment = {0};
+  bool no_age_commitment = true;
   struct GNUNET_JSON_Specification spec[] = {
     TALER_JSON_spec_amount ("amount",
                             TEH_currency,
@@ -309,10 +313,13 @@ parse_coin (struct MHD_Connection *connection,
     TALER_JSON_spec_denom_sig ("ub_sig",
                                &coin->cpi.denom_sig),
     GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_fixed_auto ("h_age_commitment",
-                                   &coin->cpi.h_age_commitment),
-      &coin->cpi.no_age_commitment),
-    // FIXME-Oec: proof of age is missing!
+      GNUNET_JSON_spec_fixed_auto ("attest",
+                                   &attest),
+      &no_attest),
+    GNUNET_JSON_spec_mark_optional (
+      TALER_JSON_spec_age_commitment ("age_commitment",
+                                      &age_commitment),
+      &no_age_commitment),
     GNUNET_JSON_spec_fixed_auto ("coin_sig",
                                  &coin->coin_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
@@ -433,6 +440,47 @@ parse_coin (struct MHD_Connection *connection,
                    TALER_amount_subtract (&coin->amount_minus_fee,
                                           &coin->amount,
                                           &coin->deposit_fee));
+
+    // Check and verify the age restriction.  Needs to happen before
+    // coin-signature check, because we set the h_age_commitment here.
+    {
+      if (no_attest != no_age_commitment)
+
+      {
+        GNUNET_break (0);
+        return TALER_MHD_reply_with_error (connection,
+                                           MHD_HTTP_BAD_REQUEST,
+                                           /* FIXME: other error code? */
+                                           
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
+                                           "mismatch of attest and 
age_commitment");
+      }
+
+      if (! no_age_commitment)
+      {
+        // attestation must be valid.
+        if (GNUNET_OK !=
+            TALER_age_commitment_verify (
+              &age_commitment,
+              pcc->min_age,
+              &attest))
+        {
+          GNUNET_break (0);
+          return TALER_MHD_reply_with_error (connection,
+                                             MHD_HTTP_BAD_REQUEST,
+                                             /* FIXME: other error code? */
+                                             
TALER_EC_EXCHANGE_GENERIC_COIN_CONFLICTING_AGE_HASH,
+                                             "invalid attest for minimum age");
+        }
+
+        // Save the hash of the age commitment in the coin's public info, so we
+        // can verify the signature later.
+        TALER_age_commitment_hash (&age_commitment,
+                                   &coin->cpi.h_age_commitment);
+        coin->cpi.no_age_commitment = false;
+
+      }
+    }
+
     /* check coin signature */
     switch (dk->denom_pub.cipher)
     {
@@ -470,6 +518,7 @@ parse_coin (struct MHD_Connection *connection,
                                          "total deposit contribution");
     }
   }
+
   {
     MHD_RESULT mhd_ret = MHD_NO;
     enum GNUNET_DB_QueryStatus qs;
diff --git a/src/include/taler_json_lib.h b/src/include/taler_json_lib.h
index 1300f875..d8912e52 100644
--- a/src/include/taler_json_lib.h
+++ b/src/include/taler_json_lib.h
@@ -215,6 +215,18 @@ TALER_JSON_pack_econtract (
   const char *name,
   const struct TALER_EncryptedContract *econtract);
 
+/**
+ * Generate packer instruction for a JSON field of type age_commitment
+ *
+ * @param name name of the field to add to the object
+ * @param age_commitment age commitment to add
+ * @return json pack specification
+ */
+struct GNUNET_JSON_PackSpec
+TALER_JSON_pack_age_commitment (
+  const char *name,
+  const struct TALER_AgeCommitment *age_commitment);
+
 
 /**
  * Convert a TALER amount to a JSON object.
@@ -294,6 +306,17 @@ TALER_JSON_spec_econtract (const char *name,
                            struct TALER_EncryptedContract *econtract);
 
 
+/**
+ * Provide specification to parse a given JSON object to an age commitment.
+ *
+ * @param name name of the age commitment field in the JSON
+ * @param[out] age_commitment where to store the age commitment
+ * @return spec for parsing an age commitment
+ */
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_age_commitment (const char *name,
+                                struct TALER_AgeCommitment *age_commitment);
+
 /**
  * Provide specification to parse given JSON object to an amount
  * in any currency in network byte order.
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 202caf6f..cf169384 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -401,6 +401,109 @@ TALER_JSON_spec_econtract (const char *name,
 }
 
 
+/**
+ * Parse given JSON object to an age commitmnet
+ *
+ * @param cls closure, NULL
+ * @param root the json object representing data
+ * @param[out] spec where to write the data
+ * @return #GNUNET_OK upon successful parsing; #GNUNET_SYSERR upon error
+ */
+static enum GNUNET_GenericReturnValue
+parse_age_commitment (void *cls,
+                      json_t *root,
+                      struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_AgeCommitment *age_commitment = spec->ptr;
+  json_t *pk;
+  unsigned int idx;
+  size_t num;
+
+  if (NULL == root || ! json_is_array (root))
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  num = json_array_size (root);
+  if (32 <= num || 0 == num)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+
+  age_commitment->num = num;
+  age_commitment->keys =
+    GNUNET_new_array (num,
+                      struct TALER_AgeCommitmentPublicKeyP);
+
+  json_array_foreach (root, idx, pk) {
+    const char *emsg;
+    unsigned int eline;
+    struct GNUNET_JSON_Specification pkspec[] = {
+      GNUNET_JSON_spec_fixed_auto (
+        NULL,
+        &age_commitment->keys[idx].pub),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (pk,
+                           pkspec,
+                           &emsg,
+                           &eline))
+    {
+      GNUNET_break_op (0);
+      GNUNET_JSON_parse_free (spec);
+      return GNUNET_SYSERR;
+    }
+  };
+
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleanup data left fom parsing age commitment
+ *
+ * @param cls closure, NULL
+ * @param[out] spec where to free the data
+ */
+static void
+clean_age_commitment (void *cls,
+                      struct GNUNET_JSON_Specification *spec)
+{
+  struct TALER_AgeCommitment *age_commitment = spec->ptr;
+
+  (void) cls;
+
+  if (NULL == age_commitment ||
+      NULL == age_commitment->keys)
+    return;
+
+  age_commitment->num = 0;
+  GNUNET_free (age_commitment->keys);
+}
+
+
+struct GNUNET_JSON_Specification
+TALER_JSON_spec_age_commitment (const char *name,
+                                struct TALER_AgeCommitment *age_commitment)
+{
+  struct GNUNET_JSON_Specification ret = {
+    .parser = &parse_age_commitment,
+    .cleaner = &clean_age_commitment,
+    .cls = NULL,
+    .field = name,
+    .ptr = age_commitment,
+    .ptr_size = 0,
+    .size_ptr = NULL
+  };
+
+  return ret;
+}
+
+
 /**
  * Parse given JSON object to denomination public key.
  *
diff --git a/src/json/json_pack.c b/src/json/json_pack.c
index bb52eeb0..ec036f69 100644
--- a/src/json/json_pack.c
+++ b/src/json/json_pack.c
@@ -71,6 +71,40 @@ TALER_JSON_pack_econtract (
 }
 
 
+struct GNUNET_JSON_PackSpec
+TALER_JSON_pack_age_commitment (
+  const char *name,
+  const struct TALER_AgeCommitment *age_commitment)
+{
+  struct GNUNET_JSON_PackSpec ps = {
+    .field_name = name,
+  };
+  json_t *keys;
+
+  if (NULL == age_commitment ||
+      0 == age_commitment->num)
+    return ps;
+
+  GNUNET_assert (NULL !=
+                 (keys = json_array ()));
+
+  for (size_t i = 0;
+       i < age_commitment->num;
+       i++)
+  {
+    json_t *val;
+    val = GNUNET_JSON_from_data (&age_commitment->keys[i],
+                                 sizeof(age_commitment->keys[i]));
+    GNUNET_assert (NULL != val);
+    GNUNET_assert (0 ==
+                   json_array_append_new (keys, val));
+  }
+
+  ps.object = keys;
+  return ps;
+}
+
+
 struct GNUNET_JSON_PackSpec
 TALER_JSON_pack_denom_pub (
   const char *name,
diff --git a/src/lib/exchange_api_purse_deposit.c 
b/src/lib/exchange_api_purse_deposit.c
index 6946419d..836183bb 100644
--- a/src/lib/exchange_api_purse_deposit.c
+++ b/src/lib/exchange_api_purse_deposit.c
@@ -485,29 +485,33 @@ TALER_EXCHANGE_purse_deposit (
   for (unsigned int i = 0; i<num_deposits; i++)
   {
     const struct TALER_EXCHANGE_PurseDeposit *deposit = &deposits[i];
+    const struct TALER_AgeCommitmentProof *acp = deposit->age_commitment_proof;
     struct Coin *coin = &pch->coins[i];
     json_t *jdeposit;
-#if FIXME_OEC
-    struct TALER_AgeCommitmentHash agh;
-    struct TALER_AgeCommitmentHash *aghp = NULL;
+    struct TALER_AgeCommitmentHash ach;
+    struct TALER_AgeCommitmentHash *achp = NULL;
     struct TALER_AgeAttestation attest;
+    struct TALER_AgeAttestation *attestp = NULL;
 
-    TALER_age_commitment_hash (&deposit->age_commitment,
-                               &agh);
-    aghp = &agh;
-    if (GNUNET_OK !=
-        TALER_age_commitment_attest (&deposit->age_proof,
-                                     min_age,
-                                     &attest))
+    if (NULL != acp)
     {
-      GNUNET_break (0);
-      json_decref (deposit_arr);
-      GNUNET_free (pch->base_url);
-      GNUNET_free (pch->coins);
-      GNUNET_free (pch);
-      return NULL;
+      TALER_age_commitment_hash (&acp->commitment,
+                                 &ach);
+      achp = &ach;
+      if (GNUNET_OK !=
+          TALER_age_commitment_attest (acp,
+                                       min_age,
+                                       &attest))
+      {
+        GNUNET_break (0);
+        json_decref (deposit_arr);
+        GNUNET_free (pch->base_url);
+        GNUNET_free (pch->coins);
+        GNUNET_free (pch);
+        return NULL;
+      }
+      attestp = &attest;
     }
-#endif
     GNUNET_CRYPTO_eddsa_key_get_public (&deposit->coin_priv.eddsa_priv,
                                         &coin->coin_pub.eddsa_pub);
     coin->h_denom_pub = deposit->h_denom_pub;
@@ -519,14 +523,12 @@ TALER_EXCHANGE_purse_deposit (
       &deposit->coin_priv,
       &coin->coin_sig);
     jdeposit = GNUNET_JSON_PACK (
-#if FIXME_OEC
       GNUNET_JSON_pack_allow_null (
         GNUNET_JSON_pack_data_auto ("h_age_commitment",
-                                    aghp)),
+                                    achp)),
       GNUNET_JSON_pack_allow_null (
         GNUNET_JSON_pack_data_auto ("age_attestation",
-                                    &attest)),
-#endif
+                                    attestp)),
       TALER_JSON_pack_amount ("amount",
                               &deposit->amount),
       GNUNET_JSON_pack_data_auto ("denom_pub_hash",

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