gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] [taler-exchange] branch master updated: implement /link sig


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: implement /link signatures
Date: Wed, 26 Jun 2019 15:34:47 +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 3a2f72b4 implement /link signatures
3a2f72b4 is described below

commit 3a2f72b4aad3c2719e4326d30a97e49e26b5d797
Author: Christian Grothoff <address@hidden>
AuthorDate: Wed Jun 26 15:34:14 2019 +0200

    implement /link signatures
---
 ChangeLog                                          |   5 +
 src/exchange/taler-exchange-httpd_keystate.c       |   2 +-
 src/exchange/taler-exchange-httpd_refresh_link.c   |   9 +-
 src/exchange/taler-exchange-httpd_refresh_reveal.c | 109 +++++++++++++++++++--
 src/exchangedb/plugin_exchangedb_postgres.c        |  42 +++++---
 src/include/taler_error_codes.h                    |   7 ++
 src/include/taler_exchangedb_plugin.h              |  14 ++-
 src/include/taler_signatures.h                     |  46 ++++++++-
 src/lib/exchange_api_refresh.c                     |  32 +++++-
 9 files changed, 235 insertions(+), 31 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 468fad8a..61ee3b6f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Wed 26 Jun 2019 03:31:52 PM CEST
+    Adding link signatures to prevent exchange from tracking
+    users using coins falsely believed to have been recovered via /link,
+    bumping protocol version to 4. -CG
+
 Sat 08 Jun 2019 07:54:33 PM CEST
     Change payto://sepa/ to payto://iban/ as per current spec. -CG
 
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 6134faf3..c4e55021 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -39,7 +39,7 @@
  * release version, and the format is NOT the same that semantic
  * versioning uses either.
  */
-#define TALER_PROTOCOL_VERSION "3:0:0"
+#define TALER_PROTOCOL_VERSION "4:0:0"
 
 
 /**
diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c 
b/src/exchange/taler-exchange-httpd_refresh_link.c
index 0ec505a8..04145f48 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.c
+++ b/src/exchange/taler-exchange-httpd_refresh_link.c
@@ -92,6 +92,9 @@ handle_link_data (void *cls,
     json_object_set_new (obj,
                          "ev_sig",
                          GNUNET_JSON_from_rsa_signature 
(pos->ev_sig.rsa_signature));
+    json_object_set_new (obj,
+                         "link_sig",
+                         GNUNET_JSON_from_data_auto 
(&pos->orig_coin_link_sig));
     if (0 !=
         json_array_append_new (list,
                                obj))
@@ -204,9 +207,9 @@ TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler 
*rh,
   if (GNUNET_OK !=
       TEH_DB_run_transaction (connection,
                               "run link",
-                             &mhd_ret,
-                             &refresh_link_transaction,
-                             &ctx))
+                              &mhd_ret,
+                              &refresh_link_transaction,
+                              &ctx))
   {
     if (NULL != ctx.mlist)
       json_decref (ctx.mlist);
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c 
b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index 6fc8d1c5..2f6d0b14 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -145,6 +145,12 @@ struct RevealContext
   const struct TALER_RefreshCoinData *rcds;
 
   /**
+   * Signatures over the link data (of type
+   * #TALER_SIGNATURE_WALLET_COIN_LINK)
+   */
+  const struct TALER_CoinSpendSignatureP *link_sigs;
+
+  /**
    * Envelopes with the signatures to be returned.  Initially NULL.
    */
   struct TALER_DenominationSignature *ev_sigs;
@@ -491,6 +497,7 @@ refresh_reveal_persist (void *cls,
       struct TALER_EXCHANGEDB_RefreshRevealedCoin *rrc = &rrcs[i];
 
       rrc->denom_pub = rctx->dkis[i]->denom_pub;
+      rrc->orig_coin_link_sig = rctx->link_sigs[i];
       rrc->coin_ev = rctx->rcds[i].coin_ev;
       rrc->coin_ev_size = rctx->rcds[i].coin_ev_size;
       rrc->coin_sig = rctx->ev_sigs[i];
@@ -524,6 +531,7 @@ refresh_reveal_persist (void *cls,
  * @param rctx context for the operation, partially built at this time
  * @param transfer_pub transfer public key
  * @param tp_json private transfer keys in JSON format
+ * @param link_sigs_json link signatures in JSON format
  * @param new_denoms_h_json requests for fresh coins to be created
  * @param coin_evs envelopes of gamma-selected coins to be signed
  * @return MHD result code
@@ -532,12 +540,14 @@ static int
 handle_refresh_reveal_json (struct MHD_Connection *connection,
                             struct RevealContext *rctx,
                             const json_t *tp_json,
+                            const json_t *link_sigs_json,
                             const json_t *new_denoms_h_json,
                             const json_t *coin_evs)
 {
   unsigned int num_fresh_coins = json_array_size (new_denoms_h_json);
   unsigned int num_tprivs = json_array_size (tp_json);
   struct TEH_KS_StateHandle *key_state;
+  struct TALER_EXCHANGEDB_RefreshMelt refresh_melt;
 
   GNUNET_assert (num_tprivs == TALER_CNC_KAPPA - 1);
   if ( (num_fresh_coins >= MAX_FRESH_COINS) ||
@@ -545,7 +555,7 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
   {
     GNUNET_break_op (0);
     return TEH_RESPONSE_reply_arg_invalid (connection,
-                                          
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
+                                           
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_EXCESSIVE,
                                            "new_denoms");
 
   }
@@ -557,6 +567,14 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
                                           
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH,
                                            "new_denoms/coin_evs");
   }
+  if (json_array_size (new_denoms_h_json) !=
+      json_array_size (link_sigs_json))
+  {
+    GNUNET_break_op (0);
+    return TEH_RESPONSE_reply_arg_invalid (connection,
+                                           
TALER_EC_REFRESH_REVEAL_NEW_DENOMS_ARRAY_SIZE_MISSMATCH,
+                                           "new_denoms/link_sigs");
+  }
 
   /* Parse transfer private keys array */
   for (unsigned int i=0;i<num_tprivs;i++)
@@ -579,7 +597,9 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
   /* Resolve denomination hashes */
   {
     const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation 
*dkis[num_fresh_coins];
+    struct GNUNET_HashCode dki_h[num_fresh_coins];
     struct TALER_RefreshCoinData rcds[num_fresh_coins];
+    struct TALER_CoinSpendSignatureP link_sigs[num_fresh_coins];
     int res;
 
     /* Resolve denomination hashes */
@@ -596,10 +616,9 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
     /* Parse denomination key hashes */
     for (unsigned int i=0;i<num_fresh_coins;i++)
     {
-      struct GNUNET_HashCode dpk_h;
       struct GNUNET_JSON_Specification spec[] = {
         GNUNET_JSON_spec_fixed_auto (NULL,
-                                     &dpk_h),
+                                     &dki_h[i]),
         GNUNET_JSON_spec_end ()
       };
 
@@ -614,7 +633,7 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
         return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
       }
       dkis[i] = TEH_KS_denomination_key_lookup_by_hash (key_state,
-                                                        &dpk_h,
+                                                        &dki_h[i],
                                                         TEH_KS_DKU_WITHDRAW);
       if (NULL == dkis[i])
       {
@@ -652,9 +671,85 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
       rcd->dk = &dkis[i]->denom_pub;
     }
 
+    /* lookup old_coin_pub in database */
+    {
+      enum GNUNET_DB_QueryStatus qs;
+    
+      if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
+          (qs = TEH_plugin->get_melt (TEH_plugin->cls,
+                                      NULL,
+                                      &rctx->rc,
+                                      &refresh_melt)))
+      {
+        switch (qs)
+        {
+        case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
+          res = TEH_RESPONSE_reply_arg_invalid (connection,
+                                                
TALER_EC_REFRESH_REVEAL_SESSION_UNKNOWN,
+                                                "rc");
+          break;
+        case GNUNET_DB_STATUS_HARD_ERROR:
+          res = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                      
TALER_EC_REFRESH_REVEAL_DB_FETCH_SESSION_ERROR);
+          break;
+        case GNUNET_DB_STATUS_SOFT_ERROR:
+        default:
+          GNUNET_break (0); /* should be impossible */
+          res = TEH_RESPONSE_reply_internal_db_error (connection,
+                                                      
TALER_EC_INTERNAL_INVARIANT_FAILURE);
+          break;
+        }
+        goto cleanup;
+      }
+    }
+    /* Parse link signatures array */
+    for (unsigned int i=0;i<num_fresh_coins;i++)
+    {
+      struct GNUNET_JSON_Specification link_spec[] = {
+         GNUNET_JSON_spec_fixed_auto (NULL, &link_sigs[i]),
+         GNUNET_JSON_spec_end ()
+      };
+      int res;
+
+      res = TEH_PARSE_json_array (connection,
+                                  link_sigs_json,
+                                  link_spec,
+                                  i,
+                                  -1);
+      if (GNUNET_OK != res)
+        return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+      /* Check link_sigs[i] signature */
+      {
+        struct TALER_LinkDataPS ldp;
+
+        ldp.purpose.size = htonl (sizeof (ldp));
+        ldp.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK);
+        ldp.h_denom_pub = dki_h[i];
+        ldp.old_coin_pub = refresh_melt.session.coin.coin_pub; 
+        ldp.transfer_pub = rctx->gamma_tp;
+        GNUNET_CRYPTO_hash (rcds[i].coin_ev,
+                            rcds[i].coin_ev_size,
+                            &ldp.coin_envelope_hash);
+
+        if (GNUNET_OK !=
+            GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_LINK,
+                                        &ldp.purpose,
+                                        &link_sigs[i].eddsa_signature,
+                                        
&refresh_melt.session.coin.coin_pub.eddsa_pub))
+        {
+          GNUNET_break_op (0);
+          res = TEH_RESPONSE_reply_signature_invalid (connection,
+                                                      
TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID,
+                                                      "link_sig");
+          goto cleanup;
+        }
+      }
+    }
+    
     rctx->num_fresh_coins = num_fresh_coins;
     rctx->rcds = rcds;
     rctx->dkis = dkis;
+    rctx->link_sigs = link_sigs;
 
     /* sign _early_ (optimistic!) to keep out of transaction scope! */
     rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins,
@@ -749,7 +844,6 @@ handle_refresh_reveal_json (struct MHD_Connection 
*connection,
 }
 
 
-
 /**
  * Handle a "/refresh/reveal" request. This time, the client reveals
  * the private transfer keys except for the cut-and-choose value
@@ -777,12 +871,14 @@ TEH_REFRESH_handler_refresh_reveal (struct 
TEH_RequestHandler *rh,
   json_t *root;
   json_t *coin_evs;
   json_t *transfer_privs;
+  json_t *link_sigs;
   json_t *new_denoms_h;
   struct RevealContext rctx;
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_fixed_auto ("rc", &rctx.rc),
     GNUNET_JSON_spec_fixed_auto ("transfer_pub", &rctx.gamma_tp),
     GNUNET_JSON_spec_json ("transfer_privs", &transfer_privs),
+    GNUNET_JSON_spec_json ("link_sigs", &link_sigs),
     GNUNET_JSON_spec_json ("coin_evs", &coin_evs),
     GNUNET_JSON_spec_json ("new_denoms_h", &new_denoms_h),
     GNUNET_JSON_spec_end ()
@@ -819,12 +915,13 @@ TEH_REFRESH_handler_refresh_reveal (struct 
TEH_RequestHandler *rh,
     GNUNET_JSON_parse_free (spec);
     GNUNET_break_op (0);
     return TEH_RESPONSE_reply_arg_invalid (connection,
-                                          
TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID,
+                                           
TALER_EC_REFRESH_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID,
                                            "transfer_privs");
   }
   res = handle_refresh_reveal_json (connection,
                                     &rctx,
                                     transfer_privs,
+                                    link_sigs,
                                     new_denoms_h,
                                     coin_evs);
   GNUNET_JSON_parse_free (spec);
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 4945d5a5..9f0f044b 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -315,6 +315,7 @@ postgres_create_tables (void *cls)
     GNUNET_PQ_make_execute("CREATE TABLE IF NOT EXISTS refresh_revealed_coins "
                            "(rc BYTEA NOT NULL REFERENCES refresh_commitments 
(rc) ON DELETE CASCADE"
                            ",newcoin_index INT4 NOT NULL"
+                           ",link_sig BYTEA NOT NULL 
CHECK(LENGTH(link_sig)=64)"
                            ",denom_pub_hash BYTEA NOT NULL REFERENCES 
denominations (denom_pub_hash) ON DELETE CASCADE"
                            ",coin_ev BYTEA NOT NULL"
                            ",ev_sig BYTEA NOT NULL"
@@ -951,18 +952,20 @@ postgres_prepare (PGconn *db_conn)
                             "INSERT INTO refresh_revealed_coins "
                             "(rc "
                             ",newcoin_index "
+                            ",link_sig "
                             ",denom_pub_hash "
                             ",coin_ev"
                             ",ev_sig"
                             ") VALUES "
-                            "($1, $2, $3, $4, $5);",
-                            5),
+                            "($1, $2, $3, $4, $5, $6);",
+                            6),
     /* Obtain information about the coins created in a refresh
        operation, used in #postgres_get_refresh_reveal() */
     GNUNET_PQ_make_prepare ("get_refresh_revealed_coins",
                             "SELECT "
                             " newcoin_index"
                             ",denom.denom_pub"
+                            ",link_sig"
                             ",coin_ev"
                             ",ev_sig"
                             " FROM refresh_revealed_coins"
@@ -1239,6 +1242,7 @@ postgres_prepare (PGconn *db_conn)
                             " tp.transfer_pub"
                             ",denoms.denom_pub"
                             ",rrc.ev_sig"
+                            ",rrc.link_sig"
                             " FROM refresh_commitments"
                             "     JOIN refresh_revealed_coins rrc"
                             "       USING (rc)"
@@ -3641,7 +3645,7 @@ postgres_select_refunds_by_coin (void *cls,
  * Lookup refresh melt commitment data under the given @a rc.
  *
  * @param cls the `struct PostgresClosure` with the plugin-specific state
- * @param session database handle to use
+ * @param session database handle to use, NULL if not run in any transaction
  * @param rc commitment hash to use to locate the operation
  * @param[out] refresh_melt where to store the result
  * @return transaction status
@@ -3652,6 +3656,7 @@ postgres_get_melt (void *cls,
                    const struct TALER_RefreshCommitmentP *rc,
                    struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt)
 {
+  struct PostgresClosure *pc = cls;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (rc),
     GNUNET_PQ_query_param_end
@@ -3675,6 +3680,8 @@ postgres_get_melt (void *cls,
   };
   enum GNUNET_DB_QueryStatus qs;
 
+  if (NULL == session)
+    session = postgres_get_session (pc);
   qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
                                                 "get_melt",
                                                 params,
@@ -3790,6 +3797,7 @@ postgres_insert_refresh_reveal (void *cls,
     struct GNUNET_PQ_QueryParam params[] = {
       GNUNET_PQ_query_param_auto_from_type (rc),
       GNUNET_PQ_query_param_uint32 (&i),
+      GNUNET_PQ_query_param_auto_from_type (&rrc->orig_coin_link_sig),
       GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash),
       GNUNET_PQ_query_param_fixed_size (rrc->coin_ev,
                                         rrc->coin_ev_size),
@@ -3876,6 +3884,8 @@ add_revealed_coins (void *cls,
                                     &off),
       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
                                            &rrc->denom_pub.rsa_public_key),
+      GNUNET_PQ_result_spec_auto_from_type ("link_sig",
+                                            &rrc->orig_coin_link_sig),
       GNUNET_PQ_result_spec_variable_size ("coin_ev",
                                           (void **) &rrc->coin_ev,
                                           &rrc->coin_ev_size),
@@ -3932,7 +3942,7 @@ postgres_get_refresh_reveal (void *cls,
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
     GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
-                                         &tp),
+                                          &tp),
     GNUNET_PQ_result_spec_variable_size ("transfer_privs",
                                          &tpriv,
                                          &tpriv_size),
@@ -4087,8 +4097,8 @@ free_link_data_list (void *cls,
  */
 static void
 add_ldl (void *cls,
-        PGresult *result,
-        unsigned int num_results)
+         PGresult *result,
+         unsigned int num_results)
 {
   struct LinkDataContext *ldctx = cls;
 
@@ -4102,11 +4112,13 @@ add_ldl (void *cls,
       struct GNUNET_PQ_ResultSpec rs[] = {
         GNUNET_PQ_result_spec_auto_from_type ("transfer_pub",
                                               &transfer_pub),
-       GNUNET_PQ_result_spec_rsa_signature ("ev_sig",
-                                            &pos->ev_sig.rsa_signature),
-       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                             &pos->denom_pub.rsa_public_key),
-       GNUNET_PQ_result_spec_end
+        GNUNET_PQ_result_spec_auto_from_type ("link_sig",
+                                              &pos->orig_coin_link_sig),
+        GNUNET_PQ_result_spec_rsa_signature ("ev_sig",
+                                             &pos->ev_sig.rsa_signature),
+        GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
+                                              &pos->denom_pub.rsa_public_key),
+        GNUNET_PQ_result_spec_end
       };
 
       if (GNUNET_OK !=
@@ -4173,10 +4185,10 @@ postgres_get_link_data (void *cls,
   ldctx.last = NULL;
   ldctx.status = GNUNET_OK;
   qs = GNUNET_PQ_eval_prepared_multi_select (session->conn,
-                                            "get_link",
-                                            params,
-                                            &add_ldl,
-                                            &ldctx);
+                                             "get_link",
+                                             params,
+                                             &add_ldl,
+                                             &ldctx);
   if (NULL != ldctx.last)
   {
     if (GNUNET_OK == ldctx.status)
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index fbd98352..5767a73b 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -617,7 +617,14 @@ enum TALER_ErrorCode
    */
   TALER_EC_REFRESH_REVEAL_FRESH_DENOMINATION_KEY_NOT_FOUND = 1361,
 
+  /**
+   * The signature made with the coin over the link data is invalid.
+   * This response is provided with HTTP status code
+   * MHD_HTTP_BAD_REQUEST.
+   */
+  TALER_EC_REFRESH_REVEAL_LINK_SIGNATURE_INVALID = 1362,
 
+  
   /**
    * The coin specified in the link request is unknown to the exchange.
    * This response is provided with HTTP status code
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 6f1625dd..67ebc62f 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -541,6 +541,12 @@ struct TALER_EXCHANGEDB_LinkDataList
    * Signature over the blinded envelope.
    */
   struct TALER_DenominationSignature ev_sig;
+
+  /**
+   * Signature of the original coin being refreshed over the
+   * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK
+   */
+  struct TALER_CoinSpendSignatureP orig_coin_link_sig;
 };
 
 
@@ -794,6 +800,12 @@ struct TALER_EXCHANGEDB_RefreshRevealedCoin
   struct TALER_DenominationPublicKey denom_pub;
 
   /**
+   * Signature of the original coin being refreshed over the
+   * link data, of type #TALER_SIGNATURE_WALLET_COIN_LINK
+   */
+  struct TALER_CoinSpendSignatureP orig_coin_link_sig;
+  
+  /**
    * Blinded message to be signed (in envelope), with @e coin_env_size bytes.
    */
   char *coin_ev;
@@ -1634,7 +1646,7 @@ struct TALER_EXCHANGEDB_Plugin
 
 
   /**
-   * Lookup refresh metl commitment data under the given @a rc.
+   * Lookup refresh melt commitment data under the given @a rc.
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session database handle to use
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index bff73f73..b738e315 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -130,9 +130,9 @@
 #define TALER_SIGNATURE_EXCHANGE_RESERVE_CLOSED 1040
 
 
-/*********************/
-/* Wallet signatures */
-/*********************/
+/**********************/
+/* Auditor signatures */
+/**********************/
 
 /**
  * Signature where the auditor confirms that he is
@@ -209,6 +209,11 @@
  */
 #define TALER_SIGNATURE_WALLET_COIN_PAYBACK 1203
 
+/**
+ * Signature using a coin key authenticating link data.
+ */
+#define TALER_SIGNATURE_WALLET_COIN_LINK 1204
+
 
 /*******************/
 /* Test signatures */
@@ -229,6 +234,41 @@
 GNUNET_NETWORK_STRUCT_BEGIN
 
 /**
+ * @brief Format used for to allow the wallet to authenticate
+ * link data provided by the exchange.
+ */
+struct TALER_LinkDataPS
+{
+
+  /**
+   * Purpose must be #TALER_SIGNATURE_WALLET_COIN_LINK.
+   * Used with an EdDSA signature of a `struct TALER_CoinPublicKeyP`.
+   */
+  struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
+
+  /**
+   * Hash of the denomination public key of the new coin.
+   */
+  struct GNUNET_HashCode h_denom_pub;
+
+  /**
+   * Public key of the old coin being refreshed.
+   */
+  struct TALER_CoinSpendPublicKeyP old_coin_pub;
+
+  /**
+   * Transfer public key (for which the private key was not revealed)
+   */
+  struct TALER_TransferPublicKeyP transfer_pub;
+
+  /**
+   * Hash of the blinded new coin.
+   */
+  struct GNUNET_HashCode coin_envelope_hash;
+};
+
+
+/**
  * @brief Format used for to generate the signature on a request to withdraw
  * coins from a reserve.
  */
diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c
index e2a3a245..61bee6d6 100644
--- a/src/lib/exchange_api_refresh.c
+++ b/src/lib/exchange_api_refresh.c
@@ -1065,7 +1065,7 @@ handle_refresh_melt_finished (void *cls,
     {
       rmh->melt_cb (rmh->melt_cb_cls,
                     response_code,
-                   TALER_JSON_get_error_code (j),
+                    TALER_JSON_get_error_code (j),
                     noreveal_index,
                     (0 == response_code) ? NULL : &exchange_pub,
                     j);
@@ -1534,6 +1534,7 @@ TALER_EXCHANGE_refresh_reveal (struct 
TALER_EXCHANGE_Handle *exchange,
   json_t *new_denoms_h;
   json_t *coin_evs;
   json_t *reveal_obj;
+  json_t *link_sigs;
   CURL *eh;
   struct GNUNET_CURL_Context *ctx;
   struct MeltData *md;
@@ -1565,6 +1566,7 @@ TALER_EXCHANGE_refresh_reveal (struct 
TALER_EXCHANGE_Handle *exchange,
   /* now new_denoms */
   GNUNET_assert (NULL != (new_denoms_h = json_array ()));
   GNUNET_assert (NULL != (coin_evs = json_array ()));
+  GNUNET_assert (NULL != (link_sigs = json_array ()));
   for (unsigned int i=0;i<md->num_fresh_coins;i++)
   {
     struct GNUNET_HashCode denom_hash;
@@ -1591,6 +1593,30 @@ TALER_EXCHANGE_refresh_reveal (struct 
TALER_EXCHANGE_Handle *exchange,
                    json_array_append_new (coin_evs,
                                           GNUNET_JSON_from_data (pd.coin_ev,
                                                                  
pd.coin_ev_size)));
+
+    /* compute link signature */
+    {
+      struct TALER_CoinSpendSignatureP link_sig;
+      struct TALER_LinkDataPS ldp;
+
+      ldp.purpose.size = htonl (sizeof (ldp));
+      ldp.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_LINK);
+      ldp.h_denom_pub = denom_hash;
+      GNUNET_CRYPTO_eddsa_key_get_public 
(&md->melted_coin.coin_priv.eddsa_priv,
+                                          &ldp.old_coin_pub.eddsa_pub);
+      ldp.transfer_pub = transfer_pub;
+      GNUNET_CRYPTO_hash (pd.coin_ev,
+                          pd.coin_ev_size,
+                          &ldp.coin_envelope_hash);
+      GNUNET_assert (GNUNET_OK ==
+                     GNUNET_CRYPTO_eddsa_sign 
(&md->melted_coin.coin_priv.eddsa_priv,
+                                               &ldp.purpose,
+                                               &link_sig.eddsa_signature));
+      GNUNET_assert (0 ==
+                     json_array_append_new (link_sigs,
+                                            GNUNET_JSON_from_data_auto 
(&link_sig)));
+    }
+    
     GNUNET_free (pd.coin_ev);
   }
 
@@ -1610,13 +1636,15 @@ TALER_EXCHANGE_refresh_reveal (struct 
TALER_EXCHANGE_Handle *exchange,
   }
 
   /* build main JSON request */
-  reveal_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o}",
+  reveal_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
                           "rc",
                           GNUNET_JSON_from_data_auto (&md->rc),
                           "transfer_pub",
                           GNUNET_JSON_from_data_auto (&transfer_pub),
                           "transfer_privs",
                           transfer_privs,
+                          "link_sigs",
+                          link_sigs,
                           "new_denoms_h",
                           new_denoms_h,
                           "coin_evs",

-- 
To stop receiving notification emails like this one, please contact
address@hidden.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]