gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: fix online denomination signatur


From: gnunet
Subject: [taler-exchange] branch master updated: fix online denomination signatures; thanks to Jonathan Krebs for pointing out the issue
Date: Sat, 23 Sep 2023 19:28:20 +0200

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

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 4c220dce fix online denomination signatures; thanks to Jonathan Krebs 
for pointing out the issue
4c220dce is described below

commit 4c220dce4d5ef33e00e937e236a744324af9dcf0
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Sep 23 19:28:13 2023 +0200

    fix online denomination signatures; thanks to Jonathan Krebs for pointing 
out the issue
---
 configure.ac                             |   2 +-
 debian/changelog                         |   6 +
 src/exchange/taler-exchange-httpd_keys.c | 375 +++++++++++++++++++------------
 src/include/taler_crypto_lib.h           |   6 -
 src/json/json_helper.c                   |   2 -
 src/lib/exchange_api_handle.c            | 218 ++++++++++++++----
 6 files changed, 414 insertions(+), 195 deletions(-)

diff --git a/configure.ac b/configure.ac
index fc08c5f0..e86d2142 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,7 +17,7 @@
 #
 #
 AC_PREREQ([2.69])
-AC_INIT([taler-exchange],[0.9.2],[taler-bug@gnunet.org])
+AC_INIT([taler-exchange],[0.9.3],[taler-bug@gnunet.org])
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_SRCDIR([src/util/util.c])
 AC_CONFIG_HEADERS([taler_config.h])
diff --git a/debian/changelog b/debian/changelog
index f0e914e4..401827f0 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+taler-exchange (0.9.3-1) unstable; urgency=low
+
+  * Actual v0.9.3 release.
+
+ -- Christian Grothoff <grothoff@gnu.org>  Wed, 27 Sep 2023 03:50:12 +0200
+
 taler-exchange (0.9.3) unstable; urgency=low
 
   * First work towards packaging v0.9.3.
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index b9194d89..12d50a81 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -2412,7 +2412,6 @@ wallet_threshold_cb (void *cls,
  * @param[in,out] signkeys list of sign keys to return
  * @param[in,out] recoup list of revoked keys to return
  * @param[in,out] grouped_denominations list of grouped denominations to return
- * @param h_grouped XOR of all hashes in @a grouped_demoninations
  * @return #GNUNET_OK on success
  */
 static enum GNUNET_GenericReturnValue
@@ -2421,14 +2420,11 @@ create_krd (struct TEH_KeyStateHandle *ksh,
             struct GNUNET_TIME_Timestamp last_cherry_pick_date,
             json_t *signkeys,
             json_t *recoup,
-            json_t *grouped_denominations,
-            const struct GNUNET_HashCode *h_grouped)
+            json_t *grouped_denominations)
 {
   struct KeysResponseData krd;
   struct TALER_ExchangePublicKeyP exchange_pub;
   struct TALER_ExchangeSignatureP exchange_sig;
-  struct TALER_ExchangePublicKeyP grouped_exchange_pub;
-  struct TALER_ExchangeSignatureP grouped_exchange_sig;
   struct WireStateHandle *wsh;
   json_t *keys;
 
@@ -2443,14 +2439,14 @@ create_krd (struct TEH_KeyStateHandle *ksh,
   GNUNET_assert (NULL != signkeys);
   GNUNET_assert (NULL != recoup);
   GNUNET_assert (NULL != grouped_denominations);
-  GNUNET_assert (NULL != h_grouped);
   GNUNET_assert (NULL != ksh->auditors);
   GNUNET_assert (NULL != TEH_currency);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               "Creating /keys at cherry pick date %s\n",
               GNUNET_TIME_timestamp2s (last_cherry_pick_date));
 
-  /* Sign hash over denomination keys */
+  /* Sign hash over master signatures of all denomination keys until this time
+     (in reverse order). */
   {
     enum TALER_ErrorCode ec;
 
@@ -2471,33 +2467,6 @@ create_krd (struct TEH_KeyStateHandle *ksh,
     }
   }
 
-  /* Sign grouped hash */
-  {
-    enum TALER_ErrorCode ec;
-
-    if (TALER_EC_NONE !=
-        (ec =
-           TALER_exchange_online_key_set_sign (
-             &TEH_keys_exchange_sign2_,
-             ksh,
-             last_cherry_pick_date,
-             h_grouped,
-             &grouped_exchange_pub,
-             &grouped_exchange_sig)))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Could not create key response data: cannot sign grouped 
hash (%s)\n",
-                  TALER_ErrorCode_get_hint (ec));
-      return GNUNET_SYSERR;
-    }
-  }
-
-  /* both public keys really must be the same */
-  GNUNET_assert (0 ==
-                 memcmp (&grouped_exchange_pub,
-                         &exchange_pub,
-                         sizeof(exchange_pub)));
-
   {
     const struct SigningKey *sk;
 
@@ -2559,12 +2528,10 @@ create_krd (struct TEH_KeyStateHandle *ksh,
                                    ksh->global_fees),
     GNUNET_JSON_pack_timestamp ("list_issue_date",
                                 last_cherry_pick_date),
-    GNUNET_JSON_pack_data_auto ("eddsa_pub",
+    GNUNET_JSON_pack_data_auto ("exchange_pub",
                                 &exchange_pub),
-    GNUNET_JSON_pack_data_auto ("eddsa_sig",
-                                &exchange_sig),
-    GNUNET_JSON_pack_data_auto ("denominations_sig",
-                                &grouped_exchange_sig));
+    GNUNET_JSON_pack_data_auto ("exchange_sig",
+                                &exchange_sig));
   GNUNET_assert (NULL != keys);
 
   /* Set wallet limit if KYC is configured */
@@ -2732,6 +2699,194 @@ create_krd (struct TEH_KeyStateHandle *ksh,
 }
 
 
+/**
+ * Element in the `struct SignatureContext` array.
+ */
+struct SignatureElement
+{
+
+  /**
+   * Offset of the denomination in the group array,
+   * for sorting (2nd rank, ascending).
+   */
+  unsigned int offset;
+
+  /**
+   * Offset of the group in the denominations array,
+   * for sorting (2nd rank, ascending).
+   */
+  unsigned int group_offset;
+
+  /**
+   * Pointer to actual master signature to hash over.
+   */
+  struct TALER_MasterSignatureP master_sig;
+};
+
+/**
+ * Context for collecting the array of master signatures
+ * needed to verify the exchange_sig online signature.
+ */
+struct SignatureContext
+{
+  /**
+   * Array of signatures to hash over.
+   */
+  struct SignatureElement *elements;
+
+  /**
+   * Write offset in the @e elements array.
+   */
+  unsigned int elements_pos;
+
+  /**
+   * Allocated space for @e elements.
+   */
+  unsigned int elements_size;
+};
+
+
+/**
+ * Determine order to sort two elements by before
+ * we hash the master signatures.  Used for
+ * sorting with qsort().
+ *
+ * @param a pointer to a `struct SignatureElement`
+ * @param b pointer to a `struct SignatureElement`
+ * @return 0 if equal, -1 if a < b, 1 if a > b.
+ */
+static int
+signature_context_sort_cb (const void *a,
+                           const void *b)
+{
+  const struct SignatureElement *sa = a;
+  const struct SignatureElement *sb = b;
+
+  if (sa->group_offset < sb->group_offset)
+    return -1;
+  if (sa->group_offset > sb->group_offset)
+    return 1;
+  if (sa->offset < sb->offset)
+    return -1;
+  if (sa->offset > sb->offset)
+    return 1;
+  /* We should never have two disjoint elements
+     with same time and offset */
+  GNUNET_assert (sa == sb);
+  return 0;
+}
+
+
+/**
+ * Append a @a master_sig to the @a sig_ctx using the
+ * given attributes for (later) sorting.
+ *
+ * @param[in,out] sig_ctx signature context to update
+ * @param group_offset offset for the group
+ * @param offset offset for the entry
+ * @param master_sig master signature for the entry
+ */
+static void
+append_signature (struct SignatureContext *sig_ctx,
+                  unsigned int group_offset,
+                  unsigned int offset,
+                  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct SignatureElement *element;
+  unsigned int new_size;
+
+  if (sig_ctx->elements_pos == sig_ctx->elements_size)
+  {
+    if (0 == sig_ctx->elements_size)
+      new_size = 1024;
+    else
+      new_size = sig_ctx->elements_size;
+    GNUNET_array_grow (sig_ctx->elements,
+                       sig_ctx->elements_size,
+                       new_size);
+  }
+  element = &sig_ctx->elements[sig_ctx->elements_pos++];
+  element->offset = offset;
+  element->group_offset = group_offset;
+  element->master_sig = *master_sig;
+}
+
+
+/**
+ *GroupData is the value we store for each group meta-data */
+struct GroupData
+{
+  /**
+   * The json blob with the group meta-data and list of denominations
+   */
+  json_t *json;
+
+  /**
+   * List of denominations for the group,
+   * included in @e json, do not free separately!
+   */
+  json_t *list;
+
+  /**
+   * Offset of the group in the final array.
+   */
+  unsigned int group_off;
+
+};
+
+
+/**
+ * Helper function called to clean up the group data
+ * in the denominations_by_group below.
+ *
+ * @param cls unused
+ * @param key unused
+ * @param value a `struct GroupData` to free
+ * @return #GNUNET_OK
+ */
+static int
+free_group (void *cls,
+            const struct GNUNET_HashCode *key,
+            void *value)
+{
+  struct GroupData *gd = value;
+
+  (void) cls;
+  (void) key;
+  GNUNET_free (gd);
+  return GNUNET_OK;
+}
+
+
+static void
+compute_msig_hash (struct SignatureContext *sig_ctx,
+                   struct GNUNET_HashCode *hc)
+{
+  struct GNUNET_HashContext *hash_context;
+
+  hash_context = GNUNET_CRYPTO_hash_context_start ();
+  qsort (sig_ctx->elements,
+         sig_ctx->elements_pos,
+         sizeof (struct SignatureElement),
+         &signature_context_sort_cb);
+  for (unsigned int i = 0; i<sig_ctx->elements_pos; i++)
+  {
+    struct SignatureElement *element = &sig_ctx->elements[i];
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Adding %u,%u,%s\n",
+                element->group_offset,
+                element->offset,
+                TALER_B2S (&element->master_sig));
+    GNUNET_CRYPTO_hash_context_read (hash_context,
+                                     &element->master_sig,
+                                     sizeof (element->master_sig));
+  }
+  GNUNET_CRYPTO_hash_context_finish (hash_context,
+                                     hc);
+}
+
+
 /**
  * Update the "/keys" responses in @a ksh, computing the detailed replies.
  *
@@ -2750,8 +2905,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   json_t *grouped_denominations = NULL;
   struct GNUNET_TIME_Timestamp last_cherry_pick_date;
   struct GNUNET_CONTAINER_Heap *heap;
-  struct GNUNET_HashContext *hash_context = NULL;
-  struct GNUNET_HashCode grouped_hash_xor = {0};
+  struct SignatureContext sig_ctx = { 0 };
   /* Remember if we have any denomination with age restriction */
   bool has_age_restricted_denomination = false;
 
@@ -2779,39 +2933,19 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
                                   sctx.min_sk_frequency);
   }
 
-  hash_context = GNUNET_CRYPTO_hash_context_start ();
-
   grouped_denominations = json_array ();
   GNUNET_assert (NULL != grouped_denominations);
 
   last_cherry_pick_date = GNUNET_TIME_UNIT_ZERO_TS;
 
-  // FIXME: This block contains the implementation of the DEPRECATED
-  // "denom_pubs" array along with the new grouped "denominations".
-  // "denom_pubs" Will be removed sooner or later.
   {
     struct TEH_DenominationKey *dk;
     struct GNUNET_CONTAINER_MultiHashMap *denominations_by_group;
-    /* GroupData is the value we store for each group meta-data */
-    struct GroupData
-    {
-      /**
-       * The json blob with the group meta-data and list of denominations
-       */
-      json_t *json;
-
-      /**
-       * xor of all hashes of denominations in that group
-       */
-      struct GNUNET_HashCode hash_xor;
-    };
 
     denominations_by_group =
       GNUNET_CONTAINER_multihashmap_create (1024,
                                             GNUNET_NO /* NO, because keys are 
only on the stack */);
-
-
-    /* heap = min heap, sorted by start time */
+    /* heap = max heap, sorted by start time */
     while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
     {
       if (GNUNET_TIME_timestamp_cmp (last_cherry_pick_date,
@@ -2826,23 +2960,19 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
          */
         struct GNUNET_HashCode hc;
 
-        GNUNET_CRYPTO_hash_context_finish (
-          GNUNET_CRYPTO_hash_context_copy (hash_context),
-          &hc);
-
+        compute_msig_hash (&sig_ctx,
+                           &hc);
         if (GNUNET_OK !=
             create_krd (ksh,
                         &hc,
                         last_cherry_pick_date,
                         sctx.signkeys,
                         recoup,
-                        grouped_denominations,
-                        &grouped_hash_xor))
+                        grouped_denominations))
         {
           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                       "Failed to generate key response data for %s\n",
                       GNUNET_TIME_timestamp2s (last_cherry_pick_date));
-          GNUNET_CRYPTO_hash_context_abort (hash_context);
           /* drain heap before destroying it */
           while (NULL != (dk = GNUNET_CONTAINER_heap_remove_root (heap)))
             /* intentionally empty */;
@@ -2860,9 +2990,7 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
        * denominations_by_group.
        */
       {
-        static const char *denoms_key = "denoms";
         struct GroupData *group;
-        json_t *list;
         json_t *entry;
         struct GNUNET_HashCode key;
         struct TALER_DenominationGroup meta = {
@@ -2896,35 +3024,36 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
           default:
             GNUNET_assert (false);
           }
-
+          /* Create a new array for the denominations in this group */
+          group->list = json_array ();
+          GNUNET_assert (NULL != group->list);
           group->json = GNUNET_JSON_PACK (
             GNUNET_JSON_pack_string ("cipher",
                                      cipher),
+            GNUNET_JSON_pack_array_steal ("denoms",
+                                          group->list),
             TALER_JSON_PACK_DENOM_FEES ("fee",
                                         &meta.fees),
             TALER_JSON_pack_amount ("value",
                                     &meta.value));
           GNUNET_assert (NULL != group->json);
-
           if (age_restricted)
           {
-            int r = json_object_set_new (group->json,
-                                         "age_mask",
-                                         json_integer (meta.age_mask.bits));
-
-            GNUNET_assert (0 == r);
-
+            GNUNET_assert (
+              0 ==
+              json_object_set_new (group->json,
+                                   "age_mask",
+                                   json_integer (
+                                     meta.age_mask.bits)));
             /* Remember that we have found at least _one_ age restricted 
denomination */
             has_age_restricted_denomination = true;
           }
-
-          /* Create a new array for the denominations in this group */
-          list = json_array ();
-          GNUNET_assert (NULL != list);
+          group->group_off
+            = json_array_size (grouped_denominations);
           GNUNET_assert (0 ==
-                         json_object_set_new (group->json,
-                                              denoms_key,
-                                              list));
+                         json_array_append_new (
+                           grouped_denominations,
+                           group->json));
           GNUNET_assert (
             GNUNET_OK ==
             GNUNET_CONTAINER_multihashmap_put (denominations_by_group,
@@ -2989,62 +3118,24 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
           GNUNET_assert (NULL != entry);
         }
 
-        /* Build up the running xor of all hashes of the denominations in this
-           group */
-        GNUNET_CRYPTO_hash_xor (&dk->h_denom_pub.hash,
-                                &group->hash_xor,
-                                &group->hash_xor);
-
+        /* Build up the running hash of all master signatures of the
+           denominations */
+        append_signature (&sig_ctx,
+                          group->group_off,
+                          (unsigned int) json_array_size (group->list),
+                          &dk->master_sig);
         /* Finally, add the denomination to the list of denominations in this
            group */
-        list = json_object_get (group->json, denoms_key);
-        GNUNET_assert (NULL != list);
-        GNUNET_assert (true == json_is_array (list));
+        GNUNET_assert (json_is_array (group->list));
         GNUNET_assert (0 ==
-                       json_array_append_new (list, entry));
+                       json_array_append_new (group->list,
+                                              entry));
       }
     } /* loop over heap ends */
 
-    /* Create the JSON-array of grouped denominations */
-    if (0 <
-        GNUNET_CONTAINER_multihashmap_size (denominations_by_group))
-    {
-      struct GNUNET_CONTAINER_MultiHashMapIterator *iter;
-      struct GroupData *group = NULL;
-
-      iter =
-        GNUNET_CONTAINER_multihashmap_iterator_create (denominations_by_group);
-
-      while (GNUNET_OK ==
-             GNUNET_CONTAINER_multihashmap_iterator_next (iter,
-                                                          NULL,
-                                                          (const
-                                                           void **) &group))
-      {
-        /* Add the XOR over all hashes of denominations in this group to the 
group */
-        GNUNET_assert (0 ==
-                       json_object_set_new (
-                         group->json,
-                         "hash",
-                         GNUNET_JSON_PACK (
-                           GNUNET_JSON_pack_data_auto (NULL,
-                                                       &group->hash_xor))));
-
-        /* Add this group to the array */
-        GNUNET_assert (0 ==
-                       json_array_append_new (
-                         grouped_denominations,
-                         group->json));
-        /* Build the running XOR over all hash(_xor) */
-        GNUNET_CRYPTO_hash_xor (&group->hash_xor,
-                                &grouped_hash_xor,
-                                &grouped_hash_xor);
-        GNUNET_free (group);
-      }
-      GNUNET_CONTAINER_multihashmap_iterator_destroy (iter);
-
-    }
-
+    GNUNET_CONTAINER_multihashmap_iterate (denominations_by_group,
+                                           &free_group,
+                                           NULL);
     GNUNET_CONTAINER_multihashmap_destroy (denominations_by_group);
   }
 
@@ -3053,16 +3144,15 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   {
     struct GNUNET_HashCode hc;
 
-    GNUNET_CRYPTO_hash_context_finish (hash_context,
-                                       &hc);
+    compute_msig_hash (&sig_ctx,
+                       &hc);
     if (GNUNET_OK !=
         create_krd (ksh,
                     &hc,
                     last_cherry_pick_date,
                     sctx.signkeys,
                     recoup,
-                    grouped_denominations,
-                    &grouped_hash_xor))
+                    grouped_denominations))
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Failed to generate key response data for %s\n",
@@ -3090,12 +3180,13 @@ finish_keys_response (struct TEH_KeyStateHandle *ksh)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "No denomination keys available. Refusing to generate /keys 
response.\n");
-    GNUNET_CRYPTO_hash_context_abort (hash_context);
   }
-
   ret = GNUNET_OK;
 
 CLEANUP:
+  GNUNET_array_grow (sig_ctx.elements,
+                     sig_ctx.elements_size,
+                     0);
   json_decref (grouped_denominations);
   json_decref (sctx.signkeys);
   json_decref (recoup);
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index dfce91cd..ffb48285 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -6043,12 +6043,6 @@ TALER_age_restriction_from_secret (
 struct TALER_DenominationGroup
 {
 
-  /**
-   * XOR of all SHA-512 hashes of the public keys in this
-   * group.
-   */
-  struct GNUNET_HashCode hash;
-
   /**
    * Value of coins in this denomination group.
    */
diff --git a/src/json/json_helper.c b/src/json/json_helper.c
index 9d7df090..ab1ce787 100644
--- a/src/json/json_helper.c
+++ b/src/json/json_helper.c
@@ -266,8 +266,6 @@ parse_denomination_group (void *cls,
       GNUNET_JSON_spec_uint32 ("age_mask",
                                &group->age_mask.bits),
       &age_mask_missing),
-    GNUNET_JSON_spec_fixed_auto ("hash",
-                                 &group->hash),
     GNUNET_JSON_spec_end ()
   };
   const char *emsg;
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index 5562936f..6009b7c1 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -84,7 +84,7 @@ struct TALER_EXCHANGE_GetKeysHandle
 {
 
   /**
-   * The exchange base URL (i.e. "http://exchange.taler.net/";)
+   * The exchange base URL (i.e. "https://exchange.demo.taler.net/";)
    */
   char *exchange_url;
 
@@ -123,6 +123,119 @@ struct TALER_EXCHANGE_GetKeysHandle
 };
 
 
+/**
+ * Element in the `struct SignatureContext` array.
+ */
+struct SignatureElement
+{
+
+  /**
+   * Offset of the denomination in the group array,
+   * for sorting (2nd rank, ascending).
+   */
+  unsigned int offset;
+
+  /**
+   * Offset of the group in the denominations array,
+   * for sorting (2nd rank, ascending).
+   */
+  unsigned int group_offset;
+
+  /**
+   * Pointer to actual master signature to hash over.
+   */
+  struct TALER_MasterSignatureP master_sig;
+};
+
+/**
+ * Context for collecting the array of master signatures
+ * needed to verify the exchange_sig online signature.
+ */
+struct SignatureContext
+{
+  /**
+   * Array of signatures to hash over.
+   */
+  struct SignatureElement *elements;
+
+  /**
+   * Write offset in the @e elements array.
+   */
+  unsigned int elements_pos;
+
+  /**
+   * Allocated space for @e elements.
+   */
+  unsigned int elements_size;
+};
+
+
+/**
+ * Determine order to sort two elements by before
+ * we hash the master signatures.  Used for
+ * sorting with qsort().
+ *
+ * @param a pointer to a `struct SignatureElement`
+ * @param b pointer to a `struct SignatureElement`
+ * @return 0 if equal, -1 if a < b, 1 if a > b.
+ */
+static int
+signature_context_sort_cb (const void *a,
+                           const void *b)
+{
+  const struct SignatureElement *sa = a;
+  const struct SignatureElement *sb = b;
+
+  if (sa->group_offset < sb->group_offset)
+    return -1;
+  if (sa->group_offset > sb->group_offset)
+    return 1;
+  if (sa->offset < sb->offset)
+    return -1;
+  if (sa->offset > sb->offset)
+    return 1;
+  /* We should never have two disjoint elements
+     with same time and offset */
+  GNUNET_assert (sa == sb);
+  return 0;
+}
+
+
+/**
+ * Append a @a master_sig to the @a sig_ctx using the
+ * given attributes for (later) sorting.
+ *
+ * @param[in,out] sig_ctx signature context to update
+ * @param group_offset offset for the group
+ * @param offset offset for the entry
+ * @param master_sig master signature for the entry
+ */
+static void
+append_signature (struct SignatureContext *sig_ctx,
+                  unsigned int group_offset,
+                  unsigned int offset,
+                  const struct TALER_MasterSignatureP *master_sig)
+{
+  struct SignatureElement *element;
+  unsigned int new_size;
+
+  if (sig_ctx->elements_pos == sig_ctx->elements_size)
+  {
+    if (0 == sig_ctx->elements_size)
+      new_size = 1024;
+    else
+      new_size = sig_ctx->elements_size;
+    GNUNET_array_grow (sig_ctx->elements,
+                       sig_ctx->elements_size,
+                       new_size);
+  }
+  element = &sig_ctx->elements[sig_ctx->elements_pos++];
+  element->offset = offset;
+  element->group_offset = group_offset;
+  element->master_sig = *master_sig;
+}
+
+
 /**
  * Frees @a wfm array.
  *
@@ -335,7 +448,10 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey 
*sign_key,
  * @param check_sigs should we check signatures?
  * @param denom_key_obj json to parse
  * @param master_key master key to use to verify signature
- * @param[in,out] hash_xor where to accumulate data for signature verification 
via XOR
+ * @param group_offset offset for the group
+ * @param index index of this denomination key in the group
+ * @param sig_ctx where to write details about encountered
+ *        master signatures, NULL if not used
  * @return #GNUNET_OK if all is fine, #GNUNET_SYSERR if the signature is
  *        invalid or the json malformed.
  */
@@ -346,7 +462,9 @@ parse_json_denomkey_partially (
   bool check_sigs,
   const json_t *denom_key_obj,
   struct TALER_MasterPublicKeyP *master_key,
-  struct GNUNET_HashCode *hash_xor)
+  unsigned int group_offset,
+  unsigned int index,
+  struct SignatureContext *sig_ctx)
 {
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("master_sig",
@@ -379,10 +497,11 @@ parse_json_denomkey_partially (
   }
   TALER_denom_pub_hash (&denom_key->key,
                         &denom_key->h_key);
-  if (NULL != hash_xor)
-    GNUNET_CRYPTO_hash_xor (&denom_key->h_key.hash,
-                            hash_xor,
-                            hash_xor);
+  if (NULL != sig_ctx)
+    append_signature (sig_ctx,
+                      group_offset,
+                      index,
+                      &denom_key->master_sig);
   if (! check_sigs)
     return GNUNET_OK;
   EXITIF (GNUNET_SYSERR ==
@@ -644,9 +763,8 @@ decode_keys_json (const json_t *resp_obj,
                   struct TALER_EXCHANGE_Keys *key_data,
                   enum TALER_EXCHANGE_VersionCompatibility *vc)
 {
-  struct TALER_ExchangeSignatureP denominations_sig;
-  struct GNUNET_HashCode hash_xor = {0};
-  struct TALER_ExchangePublicKeyP pub;
+  struct TALER_ExchangeSignatureP exchange_sig;
+  struct TALER_ExchangePublicKeyP exchange_pub;
   const json_t *wblwk = NULL;
   const json_t *global_fees;
   const json_t *sign_keys_array;
@@ -659,6 +777,7 @@ decode_keys_json (const json_t *resp_obj,
   const json_t *accounts;
   const json_t *fees;
   const json_t *wads;
+  struct SignatureContext sig_ctx = { 0 };
 
   if (JSON_OBJECT != json_typeof (resp_obj))
   {
@@ -722,11 +841,11 @@ decode_keys_json (const json_t *resp_obj,
     const char *asset_type;
     struct GNUNET_JSON_Specification mspec[] = {
       GNUNET_JSON_spec_fixed_auto (
-        "denominations_sig",
-        &denominations_sig),
+        "exchange_sig",
+        &exchange_sig),
       GNUNET_JSON_spec_fixed_auto (
-        "eddsa_pub",
-        &pub),
+        "exchange_pub",
+        &exchange_pub),
       GNUNET_JSON_spec_fixed_auto (
         "master_public_key",
         &key_data->master_pub),
@@ -959,13 +1078,10 @@ decode_keys_json (const json_t *resp_obj,
     json_t *group_obj;
     unsigned int group_idx;
 
-    json_array_foreach (denominations_by_group, group_idx, group_obj)
+    json_array_foreach (denominations_by_group,
+                        group_idx,
+                        group_obj)
     {
-      /* Running XOR of each SHA512 hash of the denominations' public key in
-         this group.  Used to compare against group.hash after all keys have
-         been parsed. */
-      struct GNUNET_HashCode group_hash_xor = {0};
-
       /* First, parse { cipher, fees, value, age_mask, hash } of the current
          group. */
       struct TALER_DenominationGroup group = {0};
@@ -988,7 +1104,9 @@ decode_keys_json (const json_t *resp_obj,
                                  NULL));
 
       /* Now, parse the individual denominations */
-      json_array_foreach (denom_keys_array, index, denom_key_obj)
+      json_array_foreach (denom_keys_array,
+                          index,
+                          denom_key_obj)
       {
         /* Set the common fields from the group for this particular
            denomination.  Required to make the validity check inside
@@ -1007,12 +1125,11 @@ decode_keys_json (const json_t *resp_obj,
                                                check_sig,
                                                denom_key_obj,
                                                &key_data->master_pub,
-                                               check_sig ? &hash_xor : NULL));
-
-        /* Build the running xor of the SHA512-hash of the public keys for the 
group */
-        GNUNET_CRYPTO_hash_xor (&dk.h_key.hash,
-                                &group_hash_xor,
-                                &group_hash_xor);
+                                               group_idx,
+                                               index,
+                                               check_sig
+                                               ? &sig_ctx
+                                               : NULL));
         for (unsigned int j = 0;
              j<key_data->num_denom_keys;
              j++)
@@ -1046,13 +1163,6 @@ decode_keys_json (const json_t *resp_obj,
           = GNUNET_TIME_timestamp_max (key_data->last_denom_issue_date,
                                        dk.valid_from);
       };   /* end of json_array_foreach over denominations */
-
-      /* The calculated group_hash_xor must be the same as group.hash from
-         the JSON. */
-      EXITIF (0 !=
-              GNUNET_CRYPTO_hash_cmp (&group_hash_xor,
-                                      &group.hash));
-
     } /* end of json_array_foreach over groups of denominations */
   } /* end of scope for group_ojb/group_idx */
 
@@ -1162,15 +1272,41 @@ decode_keys_json (const json_t *resp_obj,
 
   if (check_sig)
   {
+    struct GNUNET_HashContext *hash_context;
+    struct GNUNET_HashCode hc;
+
+    hash_context = GNUNET_CRYPTO_hash_context_start ();
+    qsort (sig_ctx.elements,
+           sig_ctx.elements_pos,
+           sizeof (struct SignatureElement),
+           &signature_context_sort_cb);
+    for (unsigned int i = 0; i<sig_ctx.elements_pos; i++)
+    {
+      struct SignatureElement *element = &sig_ctx.elements[i];
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Adding %u,%u,%s\n",
+                  element->group_offset,
+                  element->offset,
+                  TALER_B2S (&element->master_sig));
+      GNUNET_CRYPTO_hash_context_read (hash_context,
+                                       &element->master_sig,
+                                       sizeof (element->master_sig));
+    }
+    GNUNET_array_grow (sig_ctx.elements,
+                       sig_ctx.elements_size,
+                       0);
+    GNUNET_CRYPTO_hash_context_finish (hash_context,
+                                       &hc);
     EXITIF (GNUNET_OK !=
             TALER_EXCHANGE_test_signing_key (key_data,
-                                             &pub));
+                                             &exchange_pub));
     EXITIF (GNUNET_OK !=
             TALER_exchange_online_key_set_verify (
               key_data->list_issue_date,
-              &hash_xor,
-              &pub,
-              &denominations_sig));
+              &hc,
+              &exchange_pub,
+              &exchange_sig));
   }
   return GNUNET_OK;
 
@@ -1853,8 +1989,6 @@ add_grp (void *cls,
   }
 
   ge = GNUNET_JSON_PACK (
-    GNUNET_JSON_pack_data_auto ("hash",
-                                &gd->meta.hash),
     GNUNET_JSON_pack_string ("cipher",
                              cipher),
     GNUNET_JSON_pack_array_steal ("denoms",
@@ -2023,10 +2157,6 @@ TALER_EXCHANGE_keys_to_json (const struct 
TALER_EXCHANGE_Keys *kd)
                                              
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
 
       }
-      /* Build the running xor of the SHA512-hash of the public keys */
-      GNUNET_CRYPTO_hash_xor (&dk->h_key.hash,
-                              &gd->meta.hash,
-                              &gd->meta.hash);
       switch (meta.cipher)
       {
       case TALER_DENOMINATION_RSA:

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