gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: -add logic for econtract_sig sig


From: gnunet
Subject: [taler-exchange] branch master updated: -add logic for econtract_sig signatures
Date: Mon, 04 Apr 2022 07:29:56 +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 831e32b7 -add logic for econtract_sig signatures
831e32b7 is described below

commit 831e32b7ada11ad852e1171c4bee6646fb0ab865
Author: Christian Grothoff <grothoff@gnunet.org>
AuthorDate: Mon Apr 4 07:29:50 2022 +0200

    -add logic for econtract_sig signatures
---
 src/exchange/taler-exchange-httpd_purses_create.c |  78 ++++++++++--
 src/exchangedb/plugin_exchangedb_postgres.c       |   6 +
 src/include/taler_exchangedb_plugin.h             |   4 +
 src/lib/exchange_api_purse_create_with_deposit.c  | 147 +++++++++++++++-------
 4 files changed, 181 insertions(+), 54 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd_purses_create.c 
b/src/exchange/taler-exchange-httpd_purses_create.c
index 75cb448a..326dad5c 100644
--- a/src/exchange/taler-exchange-httpd_purses_create.c
+++ b/src/exchange/taler-exchange-httpd_purses_create.c
@@ -111,6 +111,11 @@ struct PurseCreateContext
    */
   struct TALER_PurseContractSignatureP purse_sig;
 
+  /**
+   * Signature of the client affiming this encrypted contract.
+   */
+  struct TALER_PurseContractSignatureP econtract_sig;
+
   /**
    * Hash of the contract terms of the purse.
    */
@@ -260,7 +265,7 @@ create_transaction (void *cls,
       return GNUNET_DB_STATUS_HARD_ERROR;
     }
     *mhd_ret
-      =   return TALER_MHD_REPLY_JSON_PACK (
+      = TALER_MHD_REPLY_JSON_PACK (
           connection,
           MHD_HTTP_CONFLICT,
           TALER_JSON_pack_ec (
@@ -319,6 +324,7 @@ create_transaction (void *cls,
                                     &pcc->contract_pub,
                                     pcc->econtract_size,
                                     pcc->econtract,
+                                    &pcc->econtract_sig,
                                     &in_conflict);
   if (qs < 0)
   {
@@ -333,16 +339,45 @@ create_transaction (void *cls,
   }
   if (in_conflict)
   {
-    /* FIXME-DESIGN: we have no proof that the
-       client is at fault here!
-       => need 2nd client signature over the encrypted
-       contract (and ECDHE public key)!!! */
+    struct TALER_ContractDiffiePublicP pub_ckey;
+    struct TALER_PurseContractSignatureP econtract_sig;
+    size_t econtract_size;
+    void *econtract;
+    struct GNUNET_HashCode h_econtract;
+
+    qs = select_contract (cls,
+                          &pcc->purse_pub,
+                          &pub_ckey,
+                          &econtract_sig,
+                          &econtract_size,
+                          &econtract);
+    if (qs <= 0)
+    {
+      if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
+        return qs;
+      TALER_LOG_WARNING (
+        "Failed to store fetch contract information from database\n");
+      *mhd_ret = TALER_MHD_reply_with_error (connection,
+                                             MHD_HTTP_INTERNAL_SERVER_ERROR,
+                                             TALER_EC_GENERIC_DB_FETCH_FAILED,
+                                             "select contract");
+      return qs;
+    }
+    GNUNET_CRYPTO_hash (econtract,
+                        econtract_size,
+                        &h_econtract);
     *mhd_ret
-      = TEH_RESPONSE_reply_with_error (
+      = TALER_MHD_REPLY_JSON_PACK (
           connection,
-          MHD_HTTP_INTERNAL_SERVER_ERROR,
-          TALER_EC_EXCHANGE_PURSE_CREATE_CONFLICTING_CONTRACT_STORED,
-          NULL);
+          MHD_HTTP_CONFLICT,
+          TALER_JSON_pack_ec (
+            TALER_EC_EXCHANGE_PURSE_ECONTRACT_CONFLICTING_META_DATA),
+          GNUNET_JSON_pack_data_auto ("h_econtract",
+                                      &h_econtract),
+          GNUNET_JSON_pack_data_auto ("econtract_sig",
+                                      &econtract_sig),
+          GNUNET_JSON_pack_data_auto ("pub_ckey",
+                                      &pub_ckey));
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
   return qs;
@@ -591,8 +626,12 @@ TEH_handler_purses_create (
       GNUNET_JSON_spec_var_size ("econtract",
                                  &pcc.econtract,
                                  &pcc.ecotract_size)),
-    GNUNET_JSON_spec_fixed_auto ("contract_pub",
-                                 &pcc.contract_pub),
+    GNUNET_JSON_spec_mark_optional (
+      GNUNET_JSON_spec_fixed_auto ("econtract_sig",
+                                   &pcc.econtract_sig)),
+    GNUNET_JSON_spec_mark_optional (
+      GNUNET_JSON_spec_fixed_auto ("contract_pub",
+                                   &pcc.contract_pub)),
     GNUNET_JSON_spec_fixed_auto ("merge_pub",
                                  &pcc.merge_pub),
     GNUNET_JSON_spec_fixed_auto ("purse_sig",
@@ -719,6 +758,23 @@ TEH_handler_purses_create (
                                        
TALER_EC_EXCHANGE_PURSE_CREATE_SIGNATURE_INVALID,
                                        NULL);
   }
+  if ( (NULL != pcc.econtract) &&
+       (GNUNET_OK !=
+        TALER_wallet_econtract_upload_verify (pcc.econtract,
+                                              pcc.econtract_size,
+                                              &pcc.contract_pub,
+                                              purse_pub,
+                                              &pcc.econtract_sig)) )
+  {
+    TALER_LOG_WARNING ("Invalid signature on /purses/$PID/create request\n");
+    GNUNET_JSON_parse_free (spec);
+    GNUNET_free (pcc.coins);
+    return TALER_MHD_reply_with_error (connection,
+                                       MHD_HTTP_UNAUTHORIZED,
+                                       
TALER_EC_EXCHANGE_PURSE_ECONTRACT_SIGNATURE_INVALID,
+                                       NULL);
+  }
+
 
   if (GNUNET_SYSERR ==
       TEH_plugin->preflight (TEH_plugin->cls))
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 9ba37370..bc6da918 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -3289,6 +3289,7 @@ prepare_statements (struct PostgresClosure *pg)
       "SELECT "
       " pub_ckey"
       ",e_contract"
+      // ",econtract_sig"
       " FROM contracts"
       "   WHERE purse_pub=$1;",
       1),
@@ -12811,6 +12812,7 @@ postgres_insert_partner (void *cls,
  * @param pub_ckey ephemeral key for DH used to encrypt the contract
  * @param econtract_size number of bytes in @a econtract
  * @param econtract the encrypted contract
+ * @param[out] econtract_sig set to the signature over the encrypted contract
  * @param[out] in_conflict set to true if @a econtract
  *             conflicts with an existing contract;
  *             in this case, the return value will be
@@ -12823,6 +12825,8 @@ postgres_insert_contract (void *cls,
                           const struct TALER_ContractDiffiePublicP *pub_ckey,
                           size_t econtract_size,
                           const void *econtract,
+                          const struct
+                          TALER_PurseContractSignatureP *econtract_sig,
                           bool *in_conflict)
 {
   GNUNET_break (0);
@@ -12836,6 +12840,7 @@ postgres_insert_contract (void *cls,
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param purse_pub key to lookup the contract by
  * @param[out] pub_ckey set to the ephemeral DH used to encrypt the contract
+ * @param[out] econtract_sig set to the signature over the encrypted contract
  * @param[out] econtract_size set to the number of bytes in @a econtract
  * @param[out] econtract set to the encrypted contract on success, to be freed 
by the caller
  * @return transaction status code
@@ -12844,6 +12849,7 @@ static enum GNUNET_DB_QueryStatus
 postgres_select_contract (void *cls,
                           const struct TALER_PurseContractPublicKeyP 
*purse_pub,
                           struct TALER_ContractDiffiePublicP *pub_ckey,
+                          struct TALER_PurseContractSignatureP *econtract_sig,
                           size_t *econtract_size,
                           void **econtract)
 {
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 5512d333..1e56c5e0 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -4426,6 +4426,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param pub_ckey ephemeral key for DH used to encrypt the contract
    * @param econtract_size number of bytes in @a econtract
    * @param econtract the encrypted contract
+   * @param[out] econtract_sig set to the signature over the encrypted contract
    * @param[out] in_conflict set to true if @a econtract
    *             conflicts with an existing contract;
    *             in this case, the return value will be
@@ -4438,6 +4439,7 @@ struct TALER_EXCHANGEDB_Plugin
                      const struct TALER_ContractDiffiePublicP *pub_ckey,
                      size_t econtract_size,
                      const void *econtract,
+                     const struct TALER_PurseContractSignatureP *econtract_sig,
                      bool *in_conflict);
 
 
@@ -4447,6 +4449,7 @@ struct TALER_EXCHANGEDB_Plugin
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param purse_pub key to lookup the contract by
    * @param[out] pub_ckey set to the ephemeral DH used to encrypt the contract
+   * @param[out] econtract_sig set to the signature over the encrypted contract
    * @param[out] econtract_size set to the number of bytes in @a econtract
    * @param[out] econtract set to the encrypted contract on success, to be 
freed by the caller
    * @return transaction status code
@@ -4455,6 +4458,7 @@ struct TALER_EXCHANGEDB_Plugin
   (*select_contract)(void *cls,
                      const struct TALER_PurseContractPublicKeyP *purse_pub,
                      struct TALER_ContractDiffiePublicP *pub_ckey,
+                     struct TALER_PurseContractSignatureP *econtract_sig,
                      size_t *econtract_size,
                      void **econtract);
 
diff --git a/src/lib/exchange_api_purse_create_with_deposit.c 
b/src/lib/exchange_api_purse_create_with_deposit.c
index 5ce91e0e..065e2722 100644
--- a/src/lib/exchange_api_purse_create_with_deposit.c
+++ b/src/lib/exchange_api_purse_create_with_deposit.c
@@ -70,6 +70,30 @@ struct TALER_EXCHANGE_PurseCreateDepositHandle
    */
   void *cb_cls;
 
+  /**
+   * Expected value in the purse after fees.
+   */
+  struct TALER_Amount purse_value_after_fees;
+
+  /**
+   * Public key of the merge capability.
+   */
+  struct TALER_PurseMergePublicKeyP merge_pub;
+
+  /**
+   * Public key of the purse.
+   */
+  struct TALER_PurseContractPublicKeyP purse_pub;
+
+  /**
+   * Hash over the purse's contrac terms.
+   */
+  struct TALER_PrivateContractHashP h_contract_terms;
+
+  /**
+   * When does the purse expire.
+   */
+  struct GNUNET_TIME_Timestamp purse_expiration;
 };
 
 
@@ -102,13 +126,18 @@ handle_purse_create_deposit_finished (void *cls,
   case MHD_HTTP_OK:
     {
       const struct TALER_EXCHANGE_Keys *key_state;
+      struct GNUNET_TIME_Timestamp etime;
+      struct TALER_Amount total_deposited;
       struct GNUNET_JSON_Specification spec[] = {
-#if 0
         GNUNET_JSON_spec_fixed_auto ("exchange_sig",
                                      &pch->exchange_sig),
         GNUNET_JSON_spec_fixed_auto ("exchange_pub",
                                      &pch->exchange_pub),
-#endif
+        GNUNET_JSON_spec_timestamp ("exchange_timestamp",
+                                    &etime),
+        TALER_JSON_spec_amount ("total_deposited",
+                                pch->purse_value_after_fees.currency,
+                                &total_deposited),
         GNUNET_JSON_spec_end ()
       };
 
@@ -123,7 +152,6 @@ handle_purse_create_deposit_finished (void *cls,
         break;
       }
       key_state = TALER_EXCHANGE_get_keys (pch->exchange);
-#if 0
       if (GNUNET_OK !=
           TALER_EXCHANGE_test_signing_key (key_state,
                                            &exchange_pub))
@@ -134,9 +162,24 @@ handle_purse_create_deposit_finished (void *cls,
           
TALER_EC_EXCHANGE_PURSE_CREATE_WITH_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
         break;
       }
-#endif
-      // FIXME: validate reply...
-      (void) key_state;
+      if (GNUNET_OK !=
+          TALER_exchange_online_purse_created_verify (
+            etime,
+            pcc->purse_expiration,
+            &pcc->purse_value_after_fees,
+            &total_deposited,
+            &pcc->purse_pub,
+            &pcc->merge_pub,
+            &pcc->h_contract_terms,
+            &exchange_pub,
+            &exchange_sig))
+      {
+        GNUNET_break_op (0);
+        dr.hr.http_status = 0;
+        dr.hr.ec =
+          
TALER_EC_EXCHANGE_PURSE_CREATE_WITH_DEPOSIT_INVALID_SIGNATURE_BY_EXCHANGE;
+        break;
+      }
     }
     break;
   case MHD_HTTP_BAD_REQUEST:
@@ -159,7 +202,7 @@ handle_purse_create_deposit_finished (void *cls,
        happen, we should pass the JSON reply to the application */
     break;
   case MHD_HTTP_CONFLICT:
-    // FIXME: check reply?
+    // FIXME: check reply!
     break;
   case MHD_HTTP_GONE:
     /* could happen if denomination was revoked */
@@ -211,50 +254,55 @@ TALER_EXCHANGE_purse_create_with_deposit (
   json_t *create_obj;
   json_t *deposit_arr;
   CURL *eh;
-  struct TALER_PurseMergePublicKeyP merge_pub;
   struct TALER_PurseContractSignatureP purse_sig;
-  struct TALER_PurseContractPublicKeyP purse_pub;
+  struct TALER_PurseContractSignatureP econtract_sig;
   struct TALER_ContractDiffiePublicP contract_pub;
-  struct TALER_PrivateContractHashP h_contract_terms;
   char arg_str[sizeof (purse_pub) * 2 + 32];
   char *url;
   uint32_t min_age;
-  struct TALER_Amount purse_value_after_fees;
-  struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_amount_any ("amount",
-                                &purse_value_after_fees),
-    GNUNET_JSON_spec_mark_optional (
-      GNUNET_JSON_spec_uint32 ("minimum_age",
-                               &min_age)),
-    GNUNET_JSON_spec_end ()
-  };
 
-  if (GNUNET_OK !=
-      GNUNET_JSON_parse (contract_terms,
-                         spec,
-                         NULL, NULL))
+  pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
+  pch->exchange = exchange;
+  pch->cb = cb;
+  pch->cb_cls = cb_cls;
+  pcc->purse_expiration = purse_expiration;
   {
-    GNUNET_break (0);
-    return NULL;
+    struct GNUNET_JSON_Specification spec[] = {
+      TALER_JSON_spec_amount_any ("amount",
+                                  &pch->purse_value_after_fees),
+      GNUNET_JSON_spec_mark_optional (
+        GNUNET_JSON_spec_uint32 ("minimum_age",
+                                 &min_age)),
+      GNUNET_JSON_spec_end ()
+    };
+
+    if (GNUNET_OK !=
+        GNUNET_JSON_parse (contract_terms,
+                           spec,
+                           NULL, NULL))
+    {
+      GNUNET_break (0);
+      return NULL;
+    }
   }
   GNUNET_assert (GNUNET_YES ==
                  TEAH_handle_is_ready (exchange));
   if (GNUNET_OK !=
       TALER_JSON_contract_hash (contract_terms,
-                                &h_contract_terms))
+                                &pcc->h_contract_terms))
   {
     GNUNET_break (0);
     return NULL;
   }
   GNUNET_CRYPTO_eddsa_key_get_public (&purse_priv->eddsa_priv,
-                                      &purse_pub.eddsa_pub);
+                                      &pcc->purse_pub.eddsa_pub);
   {
     char pub_str[sizeof (purse_pub) * 2];
     char *end;
 
     end = GNUNET_STRINGS_data_to_string (
-      &purse_pub,
-      sizeof (purse_pub),
+      &pcc->purse_pub,
+      sizeof (pcc->purse_pub),
       pub_str,
       sizeof (pub_str));
     *end = '\0';
@@ -263,14 +311,10 @@ TALER_EXCHANGE_purse_create_with_deposit (
                      "/purses/%s/create",
                      pub_str);
   }
-  pch = GNUNET_new (struct TALER_EXCHANGE_PurseCreateDepositHandle);
-  pch->exchange = exchange;
-  pch->cb = cb;
-  pch->cb_cls = cb_cls;
   GNUNET_CRYPTO_ecdhe_key_get_public (&contract_priv->ecdhe_priv,
                                       &contract_pub.ecdhe_pub);
   GNUNET_CRYPTO_eddsa_key_get_public (&merge_priv->eddsa_priv,
-                                      &merge_pub.eddsa_pub);
+                                      &pcc->merge_pub.eddsa_pub);
   pch->url = TEAH_path_to_url (exchange,
                                arg_str);
   if (NULL == pch->url)
@@ -310,7 +354,7 @@ TALER_EXCHANGE_purse_create_with_deposit (
 #endif
     TALER_wallet_purse_deposit_sign (
       url,
-      &purse_pub,
+      &pcc->purse_pub,
       &deposit->amount,
       &deposit->coin_priv,
       &coin_sig);
@@ -337,10 +381,10 @@ TALER_EXCHANGE_purse_create_with_deposit (
   }
   GNUNET_free (url);
   TALER_wallet_purse_create_sign (purse_expiration,
-                                  &h_contract_terms,
-                                  &merge_pub,
+                                  &pcc->h_contract_terms,
+                                  &pcc->merge_pub,
                                   min_age,
-                                  &purse_value_after_fees,
+                                  &pcc->purse_value_after_fees,
                                   purse_priv,
                                   &purse_sig);
   {
@@ -348,29 +392,46 @@ TALER_EXCHANGE_purse_create_with_deposit (
     size_t econtract_size = 0;
 
     if (upload_contract)
+    {
       TALER_CRYPTO_contract_encrypt_for_merge (&purse_pub,
                                                contract_priv,
                                                merge_priv,
                                                contract_terms,
                                                &econtract,
                                                &econtract_size);
+      TALER_wallet_econtract_upload_sign (econtract,
+                                          econtract_size,
+                                          &contract_pub,
+                                          purse_priv,
+                                          &econtract_sig);
+    }
     create_obj = GNUNET_JSON_PACK (
       TALER_JSON_pack_amount ("amount",
-                              &purse_value_after_fees),
+                              &pcc->purse_value_after_fees),
       GNUNET_JSON_pack_uint64 ("min_age",
                                min_age),
       GNUNET_JSON_pack_allow_null (
         GNUNET_JSON_pack_data_varsize ("econtract",
                                        econtract,
                                        econtract_size)),
-      GNUNET_JSON_pack_data_auto ("contract_pub",
-                                  &contract_pub),
+      GNUNET_JSON_pack_allow_null (
+        (upload_contract)
+        ? GNUNET_JSON_pack_data_auto ("contract_pub",
+                                      &contract_pub)
+        : GNUNET_JSON_pack_string ("dummy",
+                                   NULL)),
+      GNUNET_JSON_pack_allow_null (
+        (upload_contract)
+        ? GNUNET_JSON_pack_data_auto ("econtract_sig",
+                                      &econtract_sig)
+        : GNUNET_JSON_pack_string ("dummy2",
+                                   NULL)),
       GNUNET_JSON_pack_data_auto ("purse_sig",
                                   &purse_sig),
       GNUNET_JSON_pack_data_auto ("merge_pub",
-                                  &merge_pub),
+                                  &pcc->merge_pub),
       GNUNET_JSON_pack_data_auto ("h_contract_terms",
-                                  &h_contract_terms),
+                                  &pcc->h_contract_terms),
       GNUNET_JSON_pack_timestamp ("purse_expiration",
                                   purse_expiration),
       GNUNET_JSON_pack_array_steal ("deposits",

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