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: replace denom_pub w


From: gnunet
Subject: [GNUnet-SVN] [taler-exchange] branch master updated: replace denom_pub with denom_pub_hash in exchange API to reduce bandwidth
Date: Thu, 02 May 2019 21:17:01 +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 de9fdf86 replace denom_pub with denom_pub_hash in exchange API to 
reduce bandwidth
de9fdf86 is described below

commit de9fdf860af9bdeadee4ed21a2c03dc34d58dd86
Author: Christian Grothoff <address@hidden>
AuthorDate: Thu May 2 21:16:51 2019 +0200

    replace denom_pub with denom_pub_hash in exchange API to reduce bandwidth
---
 ChangeLog                                          |  5 ++
 src/auditor/taler-auditor.c                        | 57 ++++++++++-----
 src/exchange/taler-exchange-httpd_deposit.c        | 19 ++---
 src/exchange/taler-exchange-httpd_keystate.c       |  8 +--
 src/exchange/taler-exchange-httpd_keystate.h       |  2 +-
 src/exchange/taler-exchange-httpd_payback.c        | 21 +++---
 src/exchange/taler-exchange-httpd_refresh_melt.c   | 40 +++++------
 src/exchange/taler-exchange-httpd_refresh_reveal.c |  1 -
 src/exchange/taler-exchange-httpd_refund.c         |  6 +-
 .../taler-exchange-httpd_reserve_withdraw.c        | 22 +++---
 src/exchange/taler-exchange-httpd_responses.c      |  5 +-
 src/exchange/test_taler_exchange_aggregator.c      |  3 +-
 src/exchangedb/perf_taler_exchangedb_init.c        | 28 ++------
 src/exchangedb/perf_taler_exchangedb_interpreter.c |  5 +-
 src/exchangedb/plugin_exchangedb_common.c          | 10 ---
 src/exchangedb/plugin_exchangedb_postgres.c        | 82 +++++++++-------------
 src/exchangedb/test_exchangedb.c                   | 28 ++++----
 src/include/taler_crypto_lib.h                     | 10 +--
 src/include/taler_exchangedb_plugin.h              |  9 +--
 src/lib/exchange_api_deposit.c                     | 13 +++-
 src/lib/exchange_api_handle.c                      |  2 +-
 src/lib/exchange_api_payback.c                     |  5 +-
 src/lib/exchange_api_refresh.c                     |  7 +-
 src/lib/exchange_api_reserve.c                     | 11 +--
 src/util/crypto.c                                  | 17 ++++-
 25 files changed, 220 insertions(+), 196 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5fce75ec..c7bf8b7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Thu 02 May 2019 09:15:37 PM CEST
+    Pass hash of denomination public key in operations from
+    clients to exchange instead of the (larger) full public key.
+    Breaks protocol compatibility, bumping protocol to v3. -CG
+
 Mon Mar 11 03:24:07 CET 2019
        Completed implementation of #5536 (delete private keys once we
        no longer need them). -CG
diff --git a/src/auditor/taler-auditor.c b/src/auditor/taler-auditor.c
index 9d629d1e..0cd84523 100644
--- a/src/auditor/taler-auditor.c
+++ b/src/auditor/taler-auditor.c
@@ -562,25 +562,18 @@ static struct GNUNET_CONTAINER_MultiHashMap 
*denominations;
 /**
  * Obtain information about a @a denom_pub.
  *
- * @param denom_pub key to look up
+ * @param dh hash of the denomination public key to look up
  * @param[out] dki set to detailed information about @a denom_pub, NULL if not 
found, must
  *                 NOT be freed by caller
- * @param[out] dh set to the hash of @a denom_pub, may be NULL
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
-get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub,
-                       const struct 
TALER_EXCHANGEDB_DenominationKeyInformationP **dki,
-                       struct GNUNET_HashCode *dh)
+get_denomination_info_by_hash (const struct GNUNET_HashCode *dh,
+                       const struct 
TALER_EXCHANGEDB_DenominationKeyInformationP **dki)
 {
-  struct GNUNET_HashCode hc;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP *dkip;
   enum GNUNET_DB_QueryStatus qs;
 
-  if (NULL == dh)
-    dh = &hc;
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                     dh);
   if (NULL == denominations)
     denominations = GNUNET_CONTAINER_multihashmap_create (256,
                                                           GNUNET_NO);
@@ -594,9 +587,9 @@ get_denomination_info (const struct 
TALER_DenominationPublicKey *denom_pub,
   }
   dkip = GNUNET_new (struct TALER_EXCHANGEDB_DenominationKeyInformationP);
   qs = edb->get_denomination_info (edb->cls,
-                                  esession,
-                                  denom_pub,
-                                  dkip);
+                                   esession,
+                                   dh,
+                                   dkip);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
     GNUNET_free (dkip);
@@ -624,6 +617,31 @@ get_denomination_info (const struct 
TALER_DenominationPublicKey *denom_pub,
 
 
 /**
+ * Obtain information about a @a denom_pub.
+ *
+ * @param denom_pub key to look up
+ * @param[out] dki set to detailed information about @a denom_pub, NULL if not 
found, must
+ *                 NOT be freed by caller
+ * @param[out] dh set to the hash of @a denom_pub, may be NULL
+ * @return transaction status code
+ */
+static enum GNUNET_DB_QueryStatus
+get_denomination_info (const struct TALER_DenominationPublicKey *denom_pub,
+                       const struct 
TALER_EXCHANGEDB_DenominationKeyInformationP **dki,
+                       struct GNUNET_HashCode *dh)
+{
+  struct GNUNET_HashCode hc;
+
+  if (NULL == dh)
+    dh = &hc;
+  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
+                                     dh);
+  return get_denomination_info_by_hash (dh,
+                                        dki);
+}
+
+
+/**
  * Free denomination key information.
  *
  * @param cls NULL
@@ -1065,6 +1083,7 @@ handle_payback_by_reserve (void *cls,
                            const struct TALER_Amount *amount,
                            const struct TALER_ReservePublicKeyP *reserve_pub,
                            const struct TALER_CoinPublicInfo *coin,
+                           const struct TALER_DenominationPublicKey *denom_pub,
                            const struct TALER_CoinSpendSignatureP *coin_sig,
                            const struct TALER_DenominationBlindingKeyP 
*coin_blind)
 {
@@ -1081,11 +1100,12 @@ handle_payback_by_reserve (void *cls,
   /* should be monotonically increasing */
   GNUNET_assert (rowid >= ppr.last_reserve_payback_serial_id);
   ppr.last_reserve_payback_serial_id = rowid + 1;
-  GNUNET_CRYPTO_rsa_public_key_hash (coin->denom_pub.rsa_public_key,
-                                     &pr.h_denom_pub);
+  // FIXME: should probably check that denom_pub hashes to this hash code!
+  pr.h_denom_pub = coin->denom_pub_hash;
 
   if (GNUNET_OK !=
-      TALER_test_coin_valid (coin))
+      TALER_test_coin_valid (coin,
+                             denom_pub))
   {
     report (report_bad_sig_losses,
             json_pack ("{s:s, s:I, s:o, s:o}",
@@ -2263,9 +2283,8 @@ wire_transfer_information_cb (void *cls,
     break;
   }
   GNUNET_assert (NULL != coin); /* hard check that switch worked */
-  qs = get_denomination_info (&coin->denom_pub,
-                             &dki,
-                             NULL);
+  qs = get_denomination_info_by_hash (&coin->denom_pub_hash,
+                                      &dki);
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != qs)
   {
     GNUNET_break (GNUNET_DB_STATUS_SOFT_ERROR == qs);
diff --git a/src/exchange/taler-exchange-httpd_deposit.c 
b/src/exchange/taler-exchange-httpd_deposit.c
index 530cff77..5a1bf496 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -246,7 +246,7 @@ verify_and_execute_deposit (struct MHD_Connection 
*connection,
   struct TALER_Amount amount_without_fee;
   struct DepositContext dc;
   struct TEH_KS_StateHandle *mks;
-  struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
+  const struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
 
   /* check signature */
   dr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_DEPOSIT);
@@ -282,9 +282,9 @@ verify_and_execute_deposit (struct MHD_Connection 
*connection,
                                               
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
                                               "no keys");
   }
-  dki = TEH_KS_denomination_key_lookup (mks,
-                                        &deposit->coin.denom_pub,
-                                        TEH_KS_DKU_DEPOSIT);
+  dki = TEH_KS_denomination_key_lookup_by_hash (mks,
+                                                &deposit->coin.denom_pub_hash,
+                                                TEH_KS_DKU_DEPOSIT);
   if (NULL == dki)
   {
     TEH_KS_release (mks);
@@ -392,7 +392,7 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
   struct GNUNET_JSON_Specification spec[] = {
     GNUNET_JSON_spec_json ("wire", &wire),
     TALER_JSON_spec_amount ("contribution", &deposit.amount_with_fee),
-    TALER_JSON_spec_denomination_public_key ("denom_pub", 
&deposit.coin.denom_pub),
+    GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", 
&deposit.coin.denom_pub_hash),
     TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub),
     GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub),
@@ -487,9 +487,9 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
                                               
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
                                               "no keys");
   }
-  dki = TEH_KS_denomination_key_lookup (key_state,
-                                        &deposit.coin.denom_pub,
-                                       TEH_KS_DKU_DEPOSIT);
+  dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                &deposit.coin.denom_pub_hash,
+                                                TEH_KS_DKU_DEPOSIT);
   if (NULL == dki)
   {
     /* FIXME: #3887: if DK was revoked, we might want to give a 403 and not a 
404! */
@@ -504,7 +504,8 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
                      &dki->issue.properties.fee_deposit);
   /* check coin signature */
   if (GNUNET_YES !=
-      TALER_test_coin_valid (&deposit.coin))
+      TALER_test_coin_valid (&deposit.coin,
+                             &dki->denom_pub))
   {
     TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
     TEH_KS_release (key_state);
diff --git a/src/exchange/taler-exchange-httpd_keystate.c 
b/src/exchange/taler-exchange-httpd_keystate.c
index 901ab6fa..a452a124 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 "2:0:0"
+#define TALER_PROTOCOL_VERSION "3:0:0"
 
 
 /**
@@ -674,7 +674,7 @@ add_denomination_transaction (void *cls,
 
   qs = TEH_plugin->get_denomination_info (TEH_plugin->cls,
                                          session,
-                                         &dki->denom_pub,
+                                         &dki->issue.properties.denom_hash,
                                          &issue_exists);
   if (0 > qs)
     return qs;
@@ -789,7 +789,7 @@ revocations_iter (void *cls,
   struct TEH_KS_StateHandle *key_state = rfc->key_state;
   struct AddRevocationContext arc;
   struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *dki;
-  
+
   dki = GNUNET_CONTAINER_multihashmap_get (key_state->denomkey_map,
                                           denom_hash);
   if (NULL == dki)
@@ -1613,7 +1613,7 @@ make_fresh_key_state (struct GNUNET_TIME_Absolute now)
     json_decref (rfc.sign_keys_array);
     return NULL;
   }
-  
+
   /* Initialize `current_sign_key_issue` and `rfc.sign_keys_array` */
   TALER_EXCHANGEDB_signing_keys_iterate (TEH_exchange_directory,
                                          &reload_keys_sign_iter,
diff --git a/src/exchange/taler-exchange-httpd_keystate.h 
b/src/exchange/taler-exchange-httpd_keystate.h
index 62d69373..c9b98230 100644
--- a/src/exchange/taler-exchange-httpd_keystate.h
+++ b/src/exchange/taler-exchange-httpd_keystate.h
@@ -127,7 +127,7 @@ enum TEH_KS_DenominationKeyUse {
 struct TALER_EXCHANGEDB_DenominationKeyIssueInformation *
 TEH_KS_denomination_key_lookup (const struct TEH_KS_StateHandle *key_state,
                                 const struct TALER_DenominationPublicKey 
*denom_pub,
-                               enum TEH_KS_DenominationKeyUse use);
+                                enum TEH_KS_DenominationKeyUse use);
 
 
 /**
diff --git a/src/exchange/taler-exchange-httpd_payback.c 
b/src/exchange/taler-exchange-httpd_payback.c
index 2164863e..06181519 100644
--- a/src/exchange/taler-exchange-httpd_payback.c
+++ b/src/exchange/taler-exchange-httpd_payback.c
@@ -326,9 +326,9 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
                                               
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
                                               "no keys");
   }
-  dki = TEH_KS_denomination_key_lookup (key_state,
-                                        &coin->denom_pub,
-                                       TEH_KS_DKU_PAYBACK);
+  dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                &coin->denom_pub_hash,
+                                                TEH_KS_DKU_PAYBACK);
   if (NULL == dki)
   {
     TEH_KS_release (key_state);
@@ -342,7 +342,8 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
 
   /* check denomination signature */
   if (GNUNET_YES !=
-      TALER_test_coin_valid (coin))
+      TALER_test_coin_valid (coin,
+                             &dki->denom_pub))
   {
     TALER_LOG_WARNING ("Invalid coin passed for /payback\n");
     TEH_KS_release (key_state);
@@ -358,8 +359,6 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
   pr.h_denom_pub = dki->issue.properties.denom_hash;
   pr.coin_blind = *coin_bks;
 
-  TEH_KS_release (key_state);
-
   if (GNUNET_OK !=
       GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_WALLET_COIN_PAYBACK,
                                   &pr.purpose,
@@ -367,6 +366,7 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
                                   &coin->coin_pub.eddsa_pub))
   {
     TALER_LOG_WARNING ("Invalid signature on /payback request\n");
+    TEH_KS_release (key_state);
     return TEH_RESPONSE_reply_signature_invalid (connection,
                                                 
TALER_EC_PAYBACK_SIGNATURE_INVALID,
                                                  "coin_sig");
@@ -378,15 +378,18 @@ verify_and_execute_payback (struct MHD_Connection 
*connection,
   if (GNUNET_YES !=
       GNUNET_CRYPTO_rsa_blind (&c_hash,
                                &coin_bks->bks,
-                               coin->denom_pub.rsa_public_key,
+                               dki->denom_pub.rsa_public_key,
                                &coin_ev,
                                &coin_ev_size))
   {
     GNUNET_break (0);
+    TEH_KS_release (key_state);
+
     return TEH_RESPONSE_reply_internal_error (connection,
                                               TALER_EC_PAYBACK_BLINDING_FAILED,
                                               "coin_bks");
   }
+  TEH_KS_release (key_state);
   GNUNET_CRYPTO_hash (coin_ev,
                       coin_ev_size,
                       &pc.h_blind);
@@ -454,8 +457,8 @@ TEH_PAYBACK_handler_payback (struct TEH_RequestHandler *rh,
   struct TALER_DenominationBlindingKeyP coin_bks;
   struct TALER_CoinSpendSignatureP coin_sig;
   struct GNUNET_JSON_Specification spec[] = {
-    TALER_JSON_spec_denomination_public_key ("denom_pub",
-                                             &coin.denom_pub),
+    GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
+                                 &coin.denom_pub_hash),
     TALER_JSON_spec_denomination_signature ("denom_sig",
                                             &coin.denom_sig),
     GNUNET_JSON_spec_fixed_auto ("coin_pub",
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c 
b/src/exchange/taler-exchange-httpd_refresh_melt.c
index 8e776c77..1b8e04a0 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -412,8 +412,8 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler 
*rh,
                                  &rmc.refresh_session.coin.coin_pub),
     TALER_JSON_spec_denomination_signature ("denom_sig",
                                             
&rmc.refresh_session.coin.denom_sig),
-    TALER_JSON_spec_denomination_public_key ("denom_pub",
-                                             
&rmc.refresh_session.coin.denom_pub),
+    GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
+                                 &rmc.refresh_session.coin.denom_pub_hash),
     GNUNET_JSON_spec_fixed_auto ("confirm_sig",
                                  &rmc.refresh_session.coin_sig),
     TALER_JSON_spec_amount ("value_with_fee",
@@ -444,17 +444,6 @@ TEH_REFRESH_handler_refresh_melt (struct 
TEH_RequestHandler *rh,
   if (GNUNET_OK != res)
     return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
 
-  if (GNUNET_OK !=
-      TALER_test_coin_valid (&rmc.refresh_session.coin))
-  {
-    GNUNET_break_op (0);
-    GNUNET_JSON_parse_free (spec);
-    return TEH_RESPONSE_reply_signature_invalid (connection,
-                                                 
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
-                                                 "denom_sig");
-  }
-
-  /* run actual logic, now that the request was parsed */
   key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
   if (NULL == key_state)
   {
@@ -464,9 +453,9 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler 
*rh,
                                              "no keys");
     goto cleanup;
   }
-  rmc.dki = TEH_KS_denomination_key_lookup (key_state,
-                                            
&rmc.refresh_session.coin.denom_pub,
-                                            TEH_KS_DKU_DEPOSIT);
+  rmc.dki = TEH_KS_denomination_key_lookup_by_hash (key_state,
+                                                    
&rmc.refresh_session.coin.denom_pub_hash,
+                                                    TEH_KS_DKU_DEPOSIT);
   if (NULL == rmc.dki)
   {
     TALER_LOG_WARNING ("Unknown denomination key in /refresh/melt request\n");
@@ -476,6 +465,20 @@ TEH_REFRESH_handler_refresh_melt (struct 
TEH_RequestHandler *rh,
     goto cleanup;
   }
 
+  if (GNUNET_OK !=
+      TALER_test_coin_valid (&rmc.refresh_session.coin,
+                             &rmc.dki->denom_pub))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    TEH_KS_release (key_state);
+    return TEH_RESPONSE_reply_signature_invalid (connection,
+                                                 
TALER_EC_REFRESH_MELT_DENOMINATION_SIGNATURE_INVALID,
+                                                 "denom_sig");
+  }
+
+  /* run actual logic, now that the request was parsed */
+
   /* make sure coin is 'known' in database */
   {
     struct TEH_DB_KnowCoinContext kcc;
@@ -502,11 +505,6 @@ TEH_REFRESH_handler_refresh_melt (struct 
TEH_RequestHandler *rh,
     TEH_KS_release (key_state);
     key_state = NULL;
   }
-  if (NULL != rmc.refresh_session.coin.denom_pub.rsa_public_key)
-  {
-    GNUNET_CRYPTO_rsa_public_key_free 
(rmc.refresh_session.coin.denom_pub.rsa_public_key);
-    rmc.refresh_session.coin.denom_pub.rsa_public_key = NULL;
-  }
   if (NULL != rmc.refresh_session.coin.denom_sig.rsa_signature)
   {
     GNUNET_CRYPTO_rsa_signature_free 
(rmc.refresh_session.coin.denom_sig.rsa_signature);
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c 
b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index bdf59c37..25de5f1f 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -265,7 +265,6 @@ static void
 free_refresh_melt (struct TALER_EXCHANGEDB_RefreshMelt *refresh_melt)
 {
   GNUNET_CRYPTO_rsa_signature_free 
(refresh_melt->session.coin.denom_sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_public_key_free 
(refresh_melt->session.coin.denom_pub.rsa_public_key);
 }
 
 
diff --git a/src/exchange/taler-exchange-httpd_refund.c 
b/src/exchange/taler-exchange-httpd_refund.c
index 92dd54e9..ee6aac1b 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -342,9 +342,9 @@ refund_transaction (void *cls,
                                                   "no keys");
     return GNUNET_DB_STATUS_HARD_ERROR;
   }
-  dki = TEH_KS_denomination_key_lookup (mks,
-                                        &dep->coin.denom_pub,
-                                       TEH_KS_DKU_DEPOSIT);
+  dki = TEH_KS_denomination_key_lookup_by_hash (mks,
+                                                &dep->coin.denom_pub_hash,
+                                                TEH_KS_DKU_DEPOSIT);
   if (NULL == dki)
   {
     /* DKI not found, but we do have a coin with this DK in our database;
diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c 
b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
index 370916b0..c988cde6 100644
--- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
@@ -116,9 +116,9 @@ struct WithdrawContext
   struct TALER_Amount amount_required;
 
   /**
-   * Denomination public key.
+   * Hash of the denomination public key.
    */
-  struct TALER_DenominationPublicKey denomination_pub;
+  struct GNUNET_HashCode denom_pub_hash;
 
   /**
    * Signature over the request.
@@ -229,7 +229,7 @@ withdraw_transaction (void *cls,
    */
   {
 #define PUBSIZE 80
-    char pub_s[PUBSIZE]; 
+    char pub_s[PUBSIZE];
 
     GNUNET_break
       (NULL != GNUNET_STRINGS_data_to_string (&r.pub,
@@ -312,7 +312,7 @@ withdraw_transaction (void *cls,
 #endif
   TALER_amount_ntoh (&fee_withdraw,
                      &wc->dki->issue.properties.fee_withdraw);
-  wc->collectable.denom_pub = wc->denomination_pub;
+  wc->collectable.denom_pub_hash = wc->denom_pub_hash;
   wc->collectable.amount_with_fee = wc->amount_required;
   wc->collectable.withdraw_fee = fee_withdraw;
   wc->collectable.reserve_pub = wc->wsrd.reserve_pub;
@@ -370,8 +370,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct 
TEH_RequestHandler *rh,
                                  &wc.wsrd.reserve_pub),
     GNUNET_JSON_spec_fixed_auto ("reserve_sig",
                                  &wc.signature),
-    TALER_JSON_spec_denomination_public_key ("denom_pub",
-                                             &wc.denomination_pub),
+    GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
+                                 &wc.denom_pub_hash),
     GNUNET_JSON_spec_end ()
   };
 
@@ -399,9 +399,9 @@ TEH_RESERVE_handler_reserve_withdraw (struct 
TEH_RequestHandler *rh,
                                               
TALER_EC_EXCHANGE_BAD_CONFIGURATION,
                                               "no keys");
   }
-  wc.dki = TEH_KS_denomination_key_lookup (wc.key_state,
-                                          &wc.denomination_pub,
-                                          TEH_KS_DKU_WITHDRAW);
+  wc.dki = TEH_KS_denomination_key_lookup_by_hash (wc.key_state,
+                                                   &wc.denom_pub_hash,
+                                                   TEH_KS_DKU_WITHDRAW);
   if (NULL == wc.dki)
   {
     GNUNET_JSON_parse_free (spec);
@@ -435,8 +435,8 @@ TEH_RESERVE_handler_reserve_withdraw (struct 
TEH_RequestHandler *rh,
     = htonl (sizeof (struct TALER_WithdrawRequestPS));
   wc.wsrd.purpose.purpose
     = htonl (TALER_SIGNATURE_WALLET_RESERVE_WITHDRAW);
-  GNUNET_CRYPTO_rsa_public_key_hash (wc.denomination_pub.rsa_public_key,
-                                     &wc.wsrd.h_denomination_pub);
+  wc.wsrd.h_denomination_pub
+    = wc.denom_pub_hash;
   GNUNET_CRYPTO_hash (wc.blinded_msg,
                       wc.blinded_msg_len,
                       &wc.wsrd.h_coin_envelope);
diff --git a/src/exchange/taler-exchange-httpd_responses.c 
b/src/exchange/taler-exchange-httpd_responses.c
index 21046ef9..21394337 100644
--- a/src/exchange/taler-exchange-httpd_responses.c
+++ b/src/exchange/taler-exchange-httpd_responses.c
@@ -750,7 +750,6 @@ TEH_RESPONSE_compile_reserve_history (const struct 
TALER_EXCHANGEDB_ReserveHisto
       break;
     case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
       {
-       struct GNUNET_HashCode h_denom_pub;
        struct TALER_Amount value;
 
        value = pos->details.withdraw->amount_with_fee;
@@ -771,15 +770,13 @@ TEH_RESPONSE_compile_reserve_history (const struct 
TALER_EXCHANGEDB_ReserveHisto
          }
        }
        ret |= 2;
-       GNUNET_CRYPTO_rsa_public_key_hash 
(pos->details.withdraw->denom_pub.rsa_public_key,
-                                          &h_denom_pub);
        GNUNET_assert (0 ==
                       json_array_append_new (json_history,
                                              json_pack ("{s:s, s:o, s:o, s:o, 
s:o, s:o}",
                                                         "type", "WITHDRAW",
                                                         "reserve_sig", 
GNUNET_JSON_from_data_auto (&pos->details.withdraw->reserve_sig),
                                                         "h_coin_envelope", 
GNUNET_JSON_from_data_auto (&pos->details.withdraw->h_coin_envelope),
-                                                        "h_denom_pub", 
GNUNET_JSON_from_data_auto (&h_denom_pub),
+                                                        "h_denom_pub", 
GNUNET_JSON_from_data_auto (&pos->details.withdraw->denom_pub_hash),
                                                         "withdraw_fee", 
TALER_JSON_from_amount (&pos->details.withdraw->withdraw_fee),
                                                         "amount", 
TALER_JSON_from_amount (&value))));
       }
diff --git a/src/exchange/test_taler_exchange_aggregator.c 
b/src/exchange/test_taler_exchange_aggregator.c
index 0ba8152d..c0d3d912 100644
--- a/src/exchange/test_taler_exchange_aggregator.c
+++ b/src/exchange/test_taler_exchange_aggregator.c
@@ -383,7 +383,8 @@ fake_coin (struct TALER_CoinPublicInfo *coin)
 {
   struct GNUNET_HashCode hc;
 
-  coin->denom_pub.rsa_public_key = coin_pub;
+  GNUNET_CRYPTO_rsa_public_key_hash (coin_pub,
+                                     &coin->denom_pub_hash);
   GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_WEAK,
                                     &hc);
   coin->denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_sign_fdh (coin_pk,
diff --git a/src/exchangedb/perf_taler_exchangedb_init.c 
b/src/exchangedb/perf_taler_exchangedb_init.c
index 789aaea0..089536a4 100644
--- a/src/exchangedb/perf_taler_exchangedb_init.c
+++ b/src/exchangedb/perf_taler_exchangedb_init.c
@@ -263,9 +263,7 @@ PERF_TALER_EXCHANGEDB_deposit_init (const struct 
PERF_TALER_EXCHANGEDB_Coin *coi
                                          &deposit_fee));
   {
     deposit->coin.coin_pub = coin->public_info.coin_pub;
-    deposit->coin.denom_pub.rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (
-      coin->public_info.denom_pub.rsa_public_key);
-    GNUNET_assert (NULL != coin->public_info.denom_pub.rsa_public_key);
+    deposit->coin.denom_pub_hash = coin->public_info.denom_pub_hash;
     deposit->coin.denom_sig.rsa_signature = GNUNET_CRYPTO_rsa_signature_dup (
       coin->public_info.denom_sig.rsa_signature);
     GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature);
@@ -298,8 +296,6 @@ PERF_TALER_EXCHANGEDB_deposit_copy (const struct 
TALER_EXCHANGEDB_Deposit *depos
   copy = GNUNET_new (struct TALER_EXCHANGEDB_Deposit);
   *copy = *deposit;
   copy->receiver_wire_account = json_incref (deposit->receiver_wire_account);
-  copy->coin.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup (deposit->coin.denom_pub.rsa_public_key);
   copy->coin.denom_sig.rsa_signature =
     GNUNET_CRYPTO_rsa_signature_dup (deposit->coin.denom_sig.rsa_signature);
   return copy;
@@ -315,7 +311,6 @@ PERF_TALER_EXCHANGEDB_deposit_free (struct 
TALER_EXCHANGEDB_Deposit *deposit)
 {
   if (NULL == deposit)
     return GNUNET_OK;
-  GNUNET_CRYPTO_rsa_public_key_free (deposit->coin.denom_pub.rsa_public_key);
   GNUNET_CRYPTO_rsa_signature_free (deposit->coin.denom_sig.rsa_signature);
   json_decref (deposit->receiver_wire_account);
   GNUNET_free (deposit);
@@ -350,24 +345,21 @@ PERF_TALER_EXCHANGEDB_coin_init (
   /* public_info */
   GNUNET_CRYPTO_eddsa_key_get_public (&coin->priv,
                                       &coin->public_info.coin_pub.eddsa_pub);
-  coin->public_info.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key);
+  GNUNET_CRYPTO_rsa_public_key_hash (dki->denom_pub.rsa_public_key,
+                                     &coin->public_info.denom_pub_hash);
   GNUNET_CRYPTO_hash (&coin->public_info.coin_pub,
                       sizeof (struct TALER_CoinSpendPublicKeyP),
                       &hc);
   coin->public_info.denom_sig.rsa_signature =
     GNUNET_CRYPTO_rsa_sign_fdh (dki->denom_priv.rsa_private_key,
                                 &hc);
-  GNUNET_assert (NULL != coin->public_info.denom_pub.rsa_public_key);
   GNUNET_assert (NULL != coin->public_info.denom_sig.rsa_signature);
 
   /* blind */
   coin->blind.sig.rsa_signature =
     GNUNET_CRYPTO_rsa_signature_dup 
(coin->public_info.denom_sig.rsa_signature);
-  coin->blind.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup (dki->denom_pub.rsa_public_key);
+  coin->blind.denom_pub_hash = coin->public_info.denom_pub_hash;
   GNUNET_assert (NULL != coin->blind.sig.rsa_signature);
-  GNUNET_assert (NULL != coin->blind.denom_pub.rsa_public_key);
   TALER_amount_ntoh (&coin->blind.amount_with_fee,
                      &dki->issue.properties.value);
   TALER_amount_ntoh (&coin->blind.withdraw_fee,
@@ -396,16 +388,14 @@ PERF_TALER_EXCHANGEDB_coin_copy (const struct 
PERF_TALER_EXCHANGEDB_Coin *coin)
   copy->priv = coin->priv;
   /* public_info */
   copy->public_info.coin_pub = coin->public_info.coin_pub;
-  copy->public_info.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup 
(coin->public_info.denom_pub.rsa_public_key);
+  copy->public_info.denom_pub_hash = coin->public_info.denom_pub_hash;
   copy->public_info.denom_sig.rsa_signature =
     GNUNET_CRYPTO_rsa_signature_dup 
(coin->public_info.denom_sig.rsa_signature);
 
   /* blind */
   copy->blind.sig.rsa_signature =
     GNUNET_CRYPTO_rsa_signature_dup (coin->blind.sig.rsa_signature);
-  copy->blind.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup (coin->blind.denom_pub.rsa_public_key);
+  copy->blind.denom_pub_hash = coin->blind.denom_pub_hash;
   copy->blind.amount_with_fee = coin->blind.amount_with_fee;
   copy->blind.withdraw_fee = coin->blind.withdraw_fee;
   copy->blind.reserve_pub = coin->blind.reserve_pub;
@@ -426,10 +416,8 @@ PERF_TALER_EXCHANGEDB_coin_free (struct 
PERF_TALER_EXCHANGEDB_Coin *coin)
 {
   if (NULL == coin)
     return GNUNET_OK;
-  GNUNET_CRYPTO_rsa_public_key_free 
(coin->public_info.denom_pub.rsa_public_key);
   GNUNET_CRYPTO_rsa_signature_free (coin->public_info.denom_sig.rsa_signature);
   GNUNET_CRYPTO_rsa_signature_free (coin->blind.sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_public_key_free (coin->blind.denom_pub.rsa_public_key);
   GNUNET_free (coin);
   return GNUNET_OK;
 }
@@ -475,9 +463,7 @@ PERF_TALER_EXCHANGEDB_refresh_melt_init (struct 
TALER_RefreshCommitmentP *rc,
   melt->session.coin.coin_pub = coin->public_info.coin_pub;
   melt->session.coin.denom_sig.rsa_signature =
     GNUNET_CRYPTO_rsa_signature_dup 
(coin->public_info.denom_sig.rsa_signature);
-  melt->session.coin.denom_pub.rsa_public_key =
-    GNUNET_CRYPTO_rsa_public_key_dup 
(coin->public_info.denom_pub.rsa_public_key);
-  GNUNET_assert (NULL != melt->session.coin.denom_pub.rsa_public_key);
+  melt->session.coin.denom_pub_hash = coin->public_info.denom_pub_hash;
   GNUNET_assert (NULL != melt->session.coin.denom_sig.rsa_signature);
   melt->session.coin_sig = coin_sig;
   melt->session.rc = *rc;
diff --git a/src/exchangedb/perf_taler_exchangedb_interpreter.c 
b/src/exchangedb/perf_taler_exchangedb_interpreter.c
index cdd5a5fc..6c968410 100644
--- a/src/exchangedb/perf_taler_exchangedb_interpreter.c
+++ b/src/exchangedb/perf_taler_exchangedb_interpreter.c
@@ -1342,12 +1342,15 @@ interpret (struct 
PERF_TALER_EXCHANGEDB_interpreter_state *state)
           unsigned int denom_index;
           enum GNUNET_DB_QueryStatus qs;
           struct PERF_TALER_EXCHANGEDB_Data *data;
+          struct GNUNET_HashCode hc;
 
           denom_index = 
state->cmd[state->i].details.get_denomination.index_denom;
           data = &state->cmd[denom_index].exposed;
+          GNUNET_CRYPTO_rsa_public_key_hash 
(data->data.dki->denom_pub.rsa_public_key,
+                                             &hc);
           qs = state->plugin->get_denomination_info (state->plugin->cls,
                                                     state->session,
-                                                    &data->data.dki->denom_pub,
+                                                     &hc,
                                                     &data->data.dki->issue);
           GNUNET_assert (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs);
         }
diff --git a/src/exchangedb/plugin_exchangedb_common.c 
b/src/exchangedb/plugin_exchangedb_common.c
index 26515670..fd2620c7 100644
--- a/src/exchangedb/plugin_exchangedb_common.c
+++ b/src/exchangedb/plugin_exchangedb_common.c
@@ -49,13 +49,11 @@ common_free_reserve_history (void *cls,
     case TALER_EXCHANGEDB_RO_WITHDRAW_COIN:
       cbc = rh->details.withdraw;
       GNUNET_CRYPTO_rsa_signature_free (cbc->sig.rsa_signature);
-      GNUNET_CRYPTO_rsa_public_key_free (cbc->denom_pub.rsa_public_key);
       GNUNET_free (cbc);
       break;
     case TALER_EXCHANGEDB_RO_PAYBACK_COIN:
       payback = rh->details.payback;
       GNUNET_CRYPTO_rsa_signature_free (payback->coin.denom_sig.rsa_signature);
-      GNUNET_CRYPTO_rsa_public_key_free 
(payback->coin.denom_pub.rsa_public_key);
       GNUNET_free (payback);
       break;
     case TALER_EXCHANGEDB_RO_EXCHANGE_TO_BANK:
@@ -92,29 +90,21 @@ common_free_coin_transaction_list (void *cls,
     case TALER_EXCHANGEDB_TT_DEPOSIT:
       if (NULL != list->details.deposit->receiver_wire_account)
         json_decref (list->details.deposit->receiver_wire_account);
-      if (NULL != list->details.deposit->coin.denom_pub.rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free 
(list->details.deposit->coin.denom_pub.rsa_public_key);
       if (NULL != list->details.deposit->coin.denom_sig.rsa_signature)
         GNUNET_CRYPTO_rsa_signature_free 
(list->details.deposit->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.deposit);
       break;
     case TALER_EXCHANGEDB_TT_REFRESH_MELT:
-      if (NULL != list->details.melt->session.coin.denom_pub.rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free 
(list->details.melt->session.coin.denom_pub.rsa_public_key);
       if (NULL != list->details.melt->session.coin.denom_sig.rsa_signature)
         GNUNET_CRYPTO_rsa_signature_free 
(list->details.melt->session.coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.melt);
       break;
     case TALER_EXCHANGEDB_TT_REFUND:
-      if (NULL != list->details.refund->coin.denom_pub.rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free 
(list->details.refund->coin.denom_pub.rsa_public_key);
       if (NULL != list->details.refund->coin.denom_sig.rsa_signature)
         GNUNET_CRYPTO_rsa_signature_free 
(list->details.refund->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.refund);
       break;
     case TALER_EXCHANGEDB_TT_PAYBACK:
-      if (NULL != list->details.payback->coin.denom_pub.rsa_public_key)
-        GNUNET_CRYPTO_rsa_public_key_free 
(list->details.payback->coin.denom_pub.rsa_public_key);
       if (NULL != list->details.payback->coin.denom_sig.rsa_signature)
         GNUNET_CRYPTO_rsa_signature_free 
(list->details.payback->coin.denom_sig.rsa_signature);
       GNUNET_free (list->details.payback);
diff --git a/src/exchangedb/plugin_exchangedb_postgres.c 
b/src/exchangedb/plugin_exchangedb_postgres.c
index 82308ea8..9dc8eb2f 100644
--- a/src/exchangedb/plugin_exchangedb_postgres.c
+++ b/src/exchangedb/plugin_exchangedb_postgres.c
@@ -766,7 +766,7 @@ postgres_prepare (PGconn *db_conn)
        make sure /reserve/withdraw requests are idempotent. */
     GNUNET_PQ_make_prepare ("get_withdraw_info",
                             "SELECT"
-                            " denom.denom_pub"
+                            " denom_pub_hash"
                             ",denom_sig"
                             ",reserve_sig"
                             ",reserve_pub"
@@ -790,7 +790,7 @@ postgres_prepare (PGconn *db_conn)
     GNUNET_PQ_make_prepare ("get_reserves_out",
                             "SELECT"
                             " h_blind_ev"
-                            ",denom.denom_pub"
+                            ",denom_pub_hash"
                             ",denom_sig"
                             ",reserve_sig"
                             ",execution_date"
@@ -838,11 +838,9 @@ postgres_prepare (PGconn *db_conn)
        a coin known to the exchange. */
     GNUNET_PQ_make_prepare ("get_known_coin",
                             "SELECT"
-                            " denom.denom_pub"
+                            " denom_pub_hash"
                             ",denom_sig"
                             " FROM known_coins"
-                            "    JOIN denominations denom"
-                            "      USING (denom_pub_hash)"
                             " WHERE coin_pub=$1"
                             " FOR UPDATE;",
                             1),
@@ -876,7 +874,7 @@ postgres_prepare (PGconn *db_conn)
        high-level information about a melt operation */
     GNUNET_PQ_make_prepare ("get_melt",
                             "SELECT"
-                            " denom.denom_pub"
+                            " kc.denom_pub_hash"
                             ",denom.fee_refresh_val"
                             ",denom.fee_refresh_frac"
                             ",denom.fee_refresh_curr"
@@ -1518,6 +1516,7 @@ postgres_prepare (PGconn *db_conn)
                             ",coin_sig"
                             ",coin_blind"
                             ",h_blind_ev"
+                            ",coins.denom_pub_hash"
                             ",denoms.denom_pub"
                             ",coins.denom_sig"
                             ",amount_val"
@@ -1526,10 +1525,10 @@ postgres_prepare (PGconn *db_conn)
                             " FROM payback"
                             "    JOIN known_coins coins"
                             "      USING (coin_pub)"
-                            "    JOIN denominations denoms"
-                            "      USING (denom_pub_hash)"
                             "    JOIN reserves_out ro"
                             "      USING (h_blind_ev)"
+                            "    JOIN denominations denoms"
+                            "      ON (coins.denom_pub_hash = 
denoms.denom_pub_hash)"
                             " WHERE payback_uuid>=$1"
                             " ORDER BY payback_uuid ASC;",
                             1),
@@ -1563,13 +1562,11 @@ postgres_prepare (PGconn *db_conn)
                             ",amount_frac"
                             ",amount_curr"
                             ",timestamp"
-                            ",denoms.denom_pub"
+                            ",coins.denom_pub_hash"
                             ",coins.denom_sig"
                             " FROM payback"
                             "    JOIN known_coins coins"
                             "      USING (coin_pub)"
-                            "    JOIN denominations denoms"
-                            "      USING (denom_pub_hash)"
                             "    JOIN reserves_out ro"
                             "      USING (h_blind_ev)"
                             " WHERE ro.reserve_pub=$1"
@@ -1618,13 +1615,11 @@ postgres_prepare (PGconn *db_conn)
                             ",amount_frac"
                             ",amount_curr"
                             ",timestamp"
-                            ",denoms.denom_pub"
+                            ",coins.denom_pub_hash"
                             ",coins.denom_sig"
                             " FROM payback"
                             "    JOIN known_coins coins"
                             "      USING (coin_pub)"
-                            "    JOIN denominations denoms"
-                            "      USING (denom_pub_hash)"
                             "    JOIN reserves_out ro"
                             "      USING (h_blind_ev)"
                             " WHERE payback.coin_pub=$1;",
@@ -1947,20 +1942,19 @@ postgres_insert_denomination_info (void *cls,
  *
  * @param cls the @e cls of this struct with the plugin-specific state
  * @param session connection to use
- * @param denom_pub the public key used for signing coins of this denomination
+ * @param denom_pub_hash hash of the public key used for signing coins of this 
denomination
  * @param[out] issue set to issue information with value, fees and other info 
about the coin
  * @return transaction status code
  */
 static enum GNUNET_DB_QueryStatus
 postgres_get_denomination_info (void *cls,
                                 struct TALER_EXCHANGEDB_Session *session,
-                                const struct TALER_DenominationPublicKey 
*denom_pub,
+                                const struct GNUNET_HashCode *denom_pub_hash,
                                 struct 
TALER_EXCHANGEDB_DenominationKeyInformationP *issue)
 {
   enum GNUNET_DB_QueryStatus qs;
-  struct GNUNET_HashCode dph;
   struct GNUNET_PQ_QueryParam params[] = {
-    GNUNET_PQ_query_param_auto_from_type (&dph),
+    GNUNET_PQ_query_param_auto_from_type (denom_pub_hash),
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
@@ -1989,8 +1983,6 @@ postgres_get_denomination_info (void *cls,
     GNUNET_PQ_result_spec_end
   };
 
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                    &dph);
   qs = GNUNET_PQ_eval_prepared_singleton_select (session->conn,
                                                 "denomination_get",
                                                 params,
@@ -1999,8 +1991,7 @@ postgres_get_denomination_info (void *cls,
     return qs;
   issue->properties.purpose.size = htonl (sizeof (struct 
TALER_DenominationKeyValidityPS));
   issue->properties.purpose.purpose = htonl 
(TALER_SIGNATURE_MASTER_DENOMINATION_KEY_VALIDITY);
-  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
-                                     &issue->properties.denom_hash);
+  issue->properties.denom_hash = *denom_pub_hash;
   return qs;
 }
 
@@ -2394,10 +2385,10 @@ postgres_get_withdraw_info (void *cls,
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                         
&collectable->denom_pub.rsa_public_key),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &collectable->denom_pub_hash),
     GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                        &collectable->sig.rsa_signature),
+                                         &collectable->sig.rsa_signature),
     GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
                                          &collectable->reserve_sig),
     GNUNET_PQ_result_spec_auto_from_type ("reserve_pub",
@@ -2434,12 +2425,11 @@ postgres_insert_withdraw_info (void *cls,
 {
   struct PostgresClosure *pg = cls;
   struct TALER_EXCHANGEDB_Reserve reserve;
-  struct GNUNET_HashCode denom_pub_hash;
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Absolute expiry;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&collectable->h_coin_envelope),
-    GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash),
+    GNUNET_PQ_query_param_auto_from_type (&collectable->denom_pub_hash),
     GNUNET_PQ_query_param_rsa_signature (collectable->sig.rsa_signature),
     GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_pub),
     GNUNET_PQ_query_param_auto_from_type (&collectable->reserve_sig),
@@ -2451,8 +2441,6 @@ postgres_insert_withdraw_info (void *cls,
 
   now = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&now);
-  GNUNET_CRYPTO_rsa_public_key_hash (collectable->denom_pub.rsa_public_key,
-                                    &denom_pub_hash);
   qs = GNUNET_PQ_eval_prepared_non_select (session->conn,
                                           "insert_withdraw_info",
                                           params);
@@ -2638,8 +2626,8 @@ add_withdraw_coin (void *cls,
       struct GNUNET_PQ_ResultSpec rs[] = {
        GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
                                              &cbc->h_coin_envelope),
-       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                             &cbc->denom_pub.rsa_public_key),
+       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                             &cbc->denom_pub_hash),
        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
                                             &cbc->sig.rsa_signature),
        GNUNET_PQ_result_spec_auto_from_type ("reserve_sig",
@@ -2692,7 +2680,7 @@ add_payback (void *cls,
     payback = GNUNET_new (struct TALER_EXCHANGEDB_Payback);
     {
       struct GNUNET_PQ_ResultSpec rs[] = {
-       TALER_PQ_result_spec_amount ("amount",
+    TALER_PQ_result_spec_amount ("amount",
                                     &payback->value),
        GNUNET_PQ_result_spec_auto_from_type ("coin_pub",
                                              &payback->coin.coin_pub),
@@ -2702,10 +2690,10 @@ add_payback (void *cls,
                                              &payback->coin_sig),
        TALER_PQ_result_spec_absolute_time ("timestamp",
                                             &payback->timestamp),
-       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                             
&payback->coin.denom_pub.rsa_public_key),
+       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &payback->coin.denom_pub_hash),
        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
-                                            
&payback->coin.denom_sig.rsa_signature),
+                                         
&payback->coin.denom_sig.rsa_signature),
        GNUNET_PQ_result_spec_end
       };
 
@@ -3291,8 +3279,8 @@ get_known_coin (void *cls,
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                         &coin_info->denom_pub.rsa_public_key),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          &coin_info->denom_pub_hash),
     GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
                                         &coin_info->denom_sig.rsa_signature),
     GNUNET_PQ_result_spec_end
@@ -3324,10 +3312,9 @@ insert_known_coin (void *cls,
                    struct TALER_EXCHANGEDB_Session *session,
                    const struct TALER_CoinPublicInfo *coin_info)
 {
-  struct GNUNET_HashCode denom_pub_hash;
   struct GNUNET_PQ_QueryParam params[] = {
     GNUNET_PQ_query_param_auto_from_type (&coin_info->coin_pub),
-    GNUNET_PQ_query_param_auto_from_type (&denom_pub_hash),
+    GNUNET_PQ_query_param_auto_from_type (&coin_info->denom_pub_hash),
     GNUNET_PQ_query_param_rsa_signature (coin_info->denom_sig.rsa_signature),
     GNUNET_PQ_query_param_end
   };
@@ -3335,8 +3322,6 @@ insert_known_coin (void *cls,
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Creating known coin %s\n",
               TALER_B2S (&coin_info->coin_pub));
-  GNUNET_CRYPTO_rsa_public_key_hash (coin_info->denom_pub.rsa_public_key,
-                                    &denom_pub_hash);
   return GNUNET_PQ_eval_prepared_non_select (session->conn,
                                             "insert_known_coin",
                                             params);
@@ -3407,7 +3392,6 @@ postgres_ensure_coin_known (void *cls,
   }
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
   {
-    GNUNET_CRYPTO_rsa_public_key_free (known_coin.denom_pub.rsa_public_key);
     GNUNET_CRYPTO_rsa_signature_free (known_coin.denom_sig.rsa_signature);
     return GNUNET_DB_STATUS_SUCCESS_NO_RESULTS; /* no change! */
   }
@@ -3647,8 +3631,8 @@ postgres_get_melt (void *cls,
     GNUNET_PQ_query_param_end
   };
   struct GNUNET_PQ_ResultSpec rs[] = {
-    GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                          
&refresh_melt->session.coin.denom_pub.rsa_public_key),
+    GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                          
&refresh_melt->session.coin.denom_pub_hash),
     TALER_PQ_result_spec_amount ("fee_refresh",
                                  &refresh_melt->melt_fee),
     GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
@@ -4470,8 +4454,8 @@ add_coin_payback (void *cls,
                                              &payback->coin_sig),
        TALER_PQ_result_spec_absolute_time ("timestamp",
                                             &payback->timestamp),
-       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                             
&payback->coin.denom_pub.rsa_public_key),
+       GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                             &payback->coin.denom_pub_hash),
        GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
                                             
&payback->coin.denom_sig.rsa_signature),
        GNUNET_PQ_result_spec_end
@@ -6356,6 +6340,7 @@ payback_serial_helper_cb (void *cls,
     struct TALER_CoinPublicInfo coin;
     struct TALER_CoinSpendSignatureP coin_sig;
     struct TALER_DenominationBlindingKeyP coin_blind;
+    struct TALER_DenominationPublicKey denom_pub;
     struct TALER_Amount amount;
     struct GNUNET_HashCode h_blind_ev;
     struct GNUNET_TIME_Absolute timestamp;
@@ -6374,8 +6359,10 @@ payback_serial_helper_cb (void *cls,
                                             &coin_blind),
       GNUNET_PQ_result_spec_auto_from_type ("h_blind_ev",
                                             &h_blind_ev),
+      GNUNET_PQ_result_spec_auto_from_type ("denom_pub_hash",
+                                            &coin.denom_pub_hash),
       GNUNET_PQ_result_spec_rsa_public_key ("denom_pub",
-                                            &coin.denom_pub.rsa_public_key),
+                                           &denom_pub.rsa_public_key),
       GNUNET_PQ_result_spec_rsa_signature ("denom_sig",
                                            &coin.denom_sig.rsa_signature),
       TALER_PQ_result_spec_amount ("amount",
@@ -6399,6 +6386,7 @@ payback_serial_helper_cb (void *cls,
                   &amount,
                   &reserve_pub,
                   &coin,
+                   &denom_pub,
                   &coin_sig,
                   &coin_blind);
     GNUNET_PQ_cleanup_result (rs);
diff --git a/src/exchangedb/test_exchangedb.c b/src/exchangedb/test_exchangedb.c
index c8d4fa04..66ccb4c7 100644
--- a/src/exchangedb/test_exchangedb.c
+++ b/src/exchangedb/test_exchangedb.c
@@ -271,7 +271,7 @@ create_denom_key_pair (unsigned int size,
   if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
       plugin->get_denomination_info (plugin->cls,
                                      session,
-                                     &dki.denom_pub,
+                                     &dki.issue.properties.denom_hash,
                                      &issue2))
   {
     GNUNET_break(0);
@@ -574,7 +574,8 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
         GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
                                     &hc);
     GNUNET_assert (NULL != refresh_session.coin.denom_sig.rsa_signature);
-    refresh_session.coin.denom_pub = dkp->pub;
+    GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
+                                       &refresh_session.coin.denom_pub_hash);
     refresh_session.amount_with_fee = amount_with_fee;
   }
 
@@ -616,10 +617,9 @@ test_melting (struct TALER_EXCHANGEDB_Session *session)
                        &ret_refresh_session.session.coin.coin_pub,
                        sizeof (refresh_session.coin.coin_pub)));
   FAILIF (0 !=
-          GNUNET_CRYPTO_rsa_public_key_cmp 
(refresh_session.coin.denom_pub.rsa_public_key,
-                                            
ret_refresh_session.session.coin.denom_pub.rsa_public_key));
+          GNUNET_memcmp (&refresh_session.coin.denom_pub_hash,
+                         &ret_refresh_session.session.coin.denom_pub_hash));
   GNUNET_CRYPTO_rsa_signature_free 
(ret_refresh_session.session.coin.denom_sig.rsa_signature);
-  GNUNET_CRYPTO_rsa_public_key_free 
(ret_refresh_session.session.coin.denom_pub.rsa_public_key);
 
   /* test 'select_refreshs_above_serial_id' */
   auditor_row_cnt = 0;
@@ -1057,6 +1057,7 @@ test_gc (struct TALER_EXCHANGEDB_Session *session)
   struct GNUNET_TIME_Absolute now;
   struct GNUNET_TIME_Absolute past;
   struct TALER_EXCHANGEDB_DenominationKeyInformationP issue2;
+  struct GNUNET_HashCode denom_hash;
 
   now = GNUNET_TIME_absolute_get ();
   GNUNET_TIME_round_abs (&now);
@@ -1079,10 +1080,13 @@ test_gc (struct TALER_EXCHANGEDB_Session *session)
     destroy_denom_key_pair (dkp);
     return GNUNET_SYSERR;
   }
+    GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
+                                       &denom_hash);
+
   if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS !=
       plugin->get_denomination_info (plugin->cls,
                                      session,
-                                     &dkp->pub,
+                                     &denom_hash,
                                      &issue2))
   {
     GNUNET_break(0);
@@ -1376,6 +1380,7 @@ payback_cb (void *cls,
             const struct TALER_Amount *amount,
             const struct TALER_ReservePublicKeyP *reserve_pub,
             const struct TALER_CoinPublicInfo *coin,
+            const struct TALER_DenominationPublicKey *denom_pub,
             const struct TALER_CoinSpendSignatureP *coin_sig,
             const struct TALER_DenominationBlindingKeyP *coin_blind)
 {
@@ -1700,7 +1705,7 @@ run (void *cls)
                                      &dkp_pub_hash);
   RND_BLK(&cbc.h_coin_envelope);
   RND_BLK(&cbc.reserve_sig);
-  cbc.denom_pub = dkp->pub;
+  cbc.denom_pub_hash = dkp_pub_hash;
   cbc.sig.rsa_signature
     = GNUNET_CRYPTO_rsa_sign_fdh (dkp->priv.rsa_private_key,
                                   &cbc.h_coin_envelope);
@@ -1732,7 +1737,6 @@ run (void *cls)
                                      session,
                                      &cbc.h_coin_envelope,
                                      &cbc2));
-  FAILIF (NULL == cbc2.denom_pub.rsa_public_key);
   FAILIF(0 != GNUNET_memcmp(&cbc2.reserve_sig, &cbc.reserve_sig));
   FAILIF(0 != GNUNET_memcmp(&cbc2.reserve_pub, &cbc.reserve_pub));
   result = 6;
@@ -1745,7 +1749,8 @@ run (void *cls)
   RND_BLK (&coin_sig);
   RND_BLK (&coin_blind);
   RND_BLK (&deposit.coin.coin_pub);
-  deposit.coin.denom_pub = dkp->pub;
+  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
+                                     &deposit.coin.denom_pub_hash);
   deposit.coin.denom_sig = cbc.sig;
   deadline = GNUNET_TIME_absolute_get ();
   (void) GNUNET_TIME_round_abs (&deadline);
@@ -1885,7 +1890,8 @@ run (void *cls)
           0,
           sizeof (deposit));
   RND_BLK (&deposit.coin.coin_pub);
-  deposit.coin.denom_pub = dkp->pub;
+  GNUNET_CRYPTO_rsa_public_key_hash (dkp->pub.rsa_public_key,
+                                     &deposit.coin.denom_pub_hash);
   deposit.coin.denom_sig = cbc.sig;
   RND_BLK (&deposit.csig);
   RND_BLK (&deposit.merchant_pub);
@@ -2259,8 +2265,6 @@ run (void *cls)
     destroy_denom_key_pair (dkp);
   if (NULL != cbc.sig.rsa_signature)
     GNUNET_CRYPTO_rsa_signature_free (cbc.sig.rsa_signature);
-  if (NULL != cbc2.denom_pub.rsa_public_key)
-    GNUNET_CRYPTO_rsa_public_key_free (cbc2.denom_pub.rsa_public_key);
   if (NULL != cbc2.sig.rsa_signature)
     GNUNET_CRYPTO_rsa_signature_free (cbc2.sig.rsa_signature);
   dkp = NULL;
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index f1251617..18c214e1 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -354,10 +354,10 @@ struct TALER_CoinPublicInfo
   struct TALER_CoinSpendPublicKeyP coin_pub;
 
   /**
-   * Public key representing the denomination of the coin
-   * that is being deposited.
+   * Hash of the public key representing the denomination of the coin that is
+   * being deposited.
    */
-  struct TALER_DenominationPublicKey denom_pub;
+  struct GNUNET_HashCode denom_pub_hash;
 
   /**
    * (Unblinded) signature over @e coin_pub with @e denom_pub,
@@ -401,12 +401,14 @@ struct TALER_TrackTransferDetails
  * is not expired, and the signature is correct.
  *
  * @param coin_public_info the coin public info to check for validity
+ * @param denom_pub denomination key, must match @a coin_public_info's 
`denom_pub_hash`
  * @return #GNUNET_YES if the coin is valid,
  *         #GNUNET_NO if it is invalid
  *         #GNUNET_SYSERR if an internal error occured
  */
 int
-TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info);
+TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info,
+                       const struct TALER_DenominationPublicKey *denom_pub);
 
 
 GNUNET_NETWORK_STRUCT_BEGIN
diff --git a/src/include/taler_exchangedb_plugin.h 
b/src/include/taler_exchangedb_plugin.h
index 2d9f1420..0a46c726 100644
--- a/src/include/taler_exchangedb_plugin.h
+++ b/src/include/taler_exchangedb_plugin.h
@@ -147,9 +147,9 @@ struct TALER_EXCHANGEDB_CollectableBlindcoin
   struct TALER_DenominationSignature sig;
 
   /**
-   * Denomination key (which coin was generated).
+   * Hash of the denomination key (which coin was generated).
    */
-  struct TALER_DenominationPublicKey denom_pub;
+  struct GNUNET_HashCode denom_pub_hash;
 
   /**
    * Value of the coin being exchangeed (matching the denomination key)
@@ -1045,6 +1045,7 @@ typedef int
                                     const struct TALER_Amount *amount,
                                     const struct TALER_ReservePublicKeyP 
*reserve_pub,
                                     const struct TALER_CoinPublicInfo *coin,
+                                    const struct TALER_DenominationPublicKey 
*denom_pub,
                                     const struct TALER_CoinSpendSignatureP 
*coin_sig,
                                     const struct 
TALER_DenominationBlindingKeyP *coin_blind);
 
@@ -1274,14 +1275,14 @@ struct TALER_EXCHANGEDB_Plugin
    *
    * @param cls the @e cls of this struct with the plugin-specific state
    * @param session connection to use
-   * @param denom_pub the public key used for signing coins of this 
denomination
+   * @param denom_pub_hash hash of the public key used for signing coins of 
this denomination
    * @param[out] issue set to issue information with value, fees and other 
info about the coin
    * @return transaction status code
    */
   enum GNUNET_DB_QueryStatus
   (*get_denomination_info) (void *cls,
                             struct TALER_EXCHANGEDB_Session *session,
-                            const struct TALER_DenominationPublicKey 
*denom_pub,
+                            const struct GNUNET_HashCode *denom_pub_hash,
                             struct 
TALER_EXCHANGEDB_DenominationKeyInformationP *issue);
 
 
diff --git a/src/lib/exchange_api_deposit.c b/src/lib/exchange_api_deposit.c
index 3f72ad95..4033cc2e 100644
--- a/src/lib/exchange_api_deposit.c
+++ b/src/lib/exchange_api_deposit.c
@@ -359,6 +359,7 @@ handle_deposit_finished (void *cls,
  * @param h_contract_terms hash of the contact of the merchant with the 
customer (further details are never disclosed to the exchange)
  * @param coin_pub coin’s public key
  * @param denom_pub denomination key with which the coin is signed
+ * @param denom_pub_hash hash of @a denom_pub
  * @param denom_sig exchange’s unblinded signature of the coin
  * @param timestamp timestamp when the deposit was finalized
  * @param merchant_pub the public key of the merchant (used to identify the 
merchant for refund requests)
@@ -374,6 +375,7 @@ verify_signatures (const struct 
TALER_EXCHANGE_DenomPublicKey *dki,
                    const struct TALER_CoinSpendPublicKeyP *coin_pub,
                    const struct TALER_DenominationSignature *denom_sig,
                    const struct TALER_DenominationPublicKey *denom_pub,
+                   const struct GNUNET_HashCode *denom_pub_hash,
                    struct GNUNET_TIME_Absolute timestamp,
                    const struct TALER_MerchantPublicKeyP *merchant_pub,
                    struct GNUNET_TIME_Absolute refund_deadline,
@@ -414,10 +416,11 @@ verify_signatures (const struct 
TALER_EXCHANGE_DenomPublicKey *dki,
 
   /* check coin signature */
   coin_info.coin_pub = *coin_pub;
-  coin_info.denom_pub = *denom_pub;
+  coin_info.denom_pub_hash = *denom_pub_hash;
   coin_info.denom_sig = *denom_sig;
   if (GNUNET_YES !=
-      TALER_test_coin_valid (&coin_info))
+      TALER_test_coin_valid (&coin_info,
+                             denom_pub))
   {
     GNUNET_break_op (0);
     TALER_LOG_WARNING ("Invalid coin passed for /deposit\n");
@@ -489,6 +492,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
   json_t *deposit_obj;
   CURL *eh;
   struct GNUNET_HashCode h_wire;
+  struct GNUNET_HashCode denom_pub_hash;
   struct TALER_Amount amount_without_fee;
 
   (void) GNUNET_TIME_round_abs (&wire_deadline);
@@ -512,6 +516,8 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
                 TALER_amount_subtract (&amount_without_fee,
                                        amount,
                                        &dki->fee_deposit));
+  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
+                                     &denom_pub_hash);
   if (GNUNET_OK !=
       verify_signatures (dki,
                          amount,
@@ -520,6 +526,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
                          coin_pub,
                          denom_sig,
                          denom_pub,
+                         &denom_pub_hash,
                          timestamp,
                          merchant_pub,
                          refund_deadline,
@@ -541,7 +548,7 @@ TALER_EXCHANGE_deposit (struct TALER_EXCHANGE_Handle 
*exchange,
                            "H_wire", GNUNET_JSON_from_data_auto (&h_wire),
                            "h_contract_terms", GNUNET_JSON_from_data_auto 
(h_contract_terms),
                            "coin_pub", GNUNET_JSON_from_data_auto (coin_pub),
-                           "denom_pub", GNUNET_JSON_from_rsa_public_key 
(denom_pub->rsa_public_key),
+                           "denom_pub_hash", GNUNET_JSON_from_data_auto 
(&denom_pub_hash),
                            "ub_sig", GNUNET_JSON_from_rsa_signature 
(denom_sig->rsa_signature),
                            "timestamp", GNUNET_JSON_from_time_abs (timestamp),
                            "merchant_pub", GNUNET_JSON_from_data_auto 
(merchant_pub),
diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index cbcde724..93fe798c 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -432,7 +432,7 @@ parse_json_signkey (struct TALER_EXCHANGE_SigningPublicKey 
*sign_key,
  */
 static int
 parse_json_denomkey (struct TALER_EXCHANGE_DenomPublicKey *denom_key,
-                    int check_sigs,
+                     int check_sigs,
                      json_t *denom_key_obj,
                      struct TALER_MasterPublicKeyP *master_key,
                      struct GNUNET_HashContext *hash_context)
diff --git a/src/lib/exchange_api_payback.c b/src/lib/exchange_api_payback.c
index 6c1772af..b3624f73 100644
--- a/src/lib/exchange_api_payback.c
+++ b/src/lib/exchange_api_payback.c
@@ -280,6 +280,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle 
*exchange,
   struct GNUNET_CURL_Context *ctx;
   struct TALER_PaybackRequestPS pr;
   struct TALER_CoinSpendSignatureP coin_sig;
+  struct GNUNET_HashCode h_denom_pub;
   json_t *payback_obj;
   CURL *eh;
 
@@ -289,6 +290,8 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle 
*exchange,
   pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS));
   GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
                                       &pr.coin_pub.eddsa_pub);
+  GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
+                                     &h_denom_pub);
   pr.h_denom_pub = pk->h_key;
   pr.coin_blind = ps->blinding_key;
   GNUNET_assert (GNUNET_OK ==
@@ -299,7 +302,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle 
*exchange,
   payback_obj = json_pack ("{s:o, s:o," /* denom pub/sig */
                            " s:o, s:o," /* coin pub/sig */
                            " s:o}", /* coin_bks */
-                           "denom_pub", GNUNET_JSON_from_rsa_public_key 
(pk->key.rsa_public_key),
+                           "denom_pub_hash", GNUNET_JSON_from_data_auto 
(&h_denom_pub),
                            "denom_sig", GNUNET_JSON_from_rsa_signature 
(denom_sig->rsa_signature),
                            "coin_pub", GNUNET_JSON_from_data_auto 
(&pr.coin_pub),
                            "coin_sig", GNUNET_JSON_from_data_auto (&coin_sig),
diff --git a/src/lib/exchange_api_refresh.c b/src/lib/exchange_api_refresh.c
index 230f445e..4b2de2f4 100644
--- a/src/lib/exchange_api_refresh.c
+++ b/src/lib/exchange_api_refresh.c
@@ -1151,6 +1151,7 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle 
*exchange,
   struct MeltData *md;
   struct TALER_CoinSpendSignatureP confirm_sig;
   struct TALER_RefreshMeltCoinAffirmationPS melt;
+  struct GNUNET_HashCode h_denom_pub;
 
   GNUNET_assert (GNUNET_YES ==
                 TEAH_handle_is_ready (exchange));
@@ -1174,11 +1175,13 @@ TALER_EXCHANGE_refresh_melt (struct 
TALER_EXCHANGE_Handle *exchange,
   GNUNET_CRYPTO_eddsa_sign (&md->melted_coin.coin_priv.eddsa_priv,
                             &melt.purpose,
                             &confirm_sig.eddsa_signature);
+  GNUNET_CRYPTO_rsa_public_key_hash (md->melted_coin.pub_key.rsa_public_key,
+                                     &h_denom_pub);
   melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}",
                         "coin_pub",
                         GNUNET_JSON_from_data_auto (&melt.coin_pub),
-                        "denom_pub",
-                        GNUNET_JSON_from_rsa_public_key 
(md->melted_coin.pub_key.rsa_public_key),
+                        "denom_pub_hash",
+                        GNUNET_JSON_from_data_auto (&h_denom_pub),
                         "denom_sig",
                         GNUNET_JSON_from_rsa_signature 
(md->melted_coin.sig.rsa_signature),
                         "confirm_sig",
diff --git a/src/lib/exchange_api_reserve.c b/src/lib/exchange_api_reserve.c
index 4aa5794f..66509bc5 100644
--- a/src/lib/exchange_api_reserve.c
+++ b/src/lib/exchange_api_reserve.c
@@ -187,8 +187,8 @@ parse_reserve_history (struct TALER_EXCHANGE_Handle 
*exchange,
       struct GNUNET_JSON_Specification withdraw_spec[] = {
         GNUNET_JSON_spec_fixed_auto ("reserve_sig",
                                      &sig),
-       TALER_JSON_spec_amount_nbo ("withdraw_fee",
-                                   &withdraw_purpose.withdraw_fee),
+        TALER_JSON_spec_amount_nbo ("withdraw_fee",
+                                    &withdraw_purpose.withdraw_fee),
         GNUNET_JSON_spec_fixed_auto ("h_denom_pub",
                                      &withdraw_purpose.h_denomination_pub),
         GNUNET_JSON_spec_fixed_auto ("h_coin_envelope",
@@ -1001,6 +1001,7 @@ reserve_withdraw_internal (struct TALER_EXCHANGE_Handle 
*exchange,
   struct GNUNET_CURL_Context *ctx;
   json_t *withdraw_obj;
   CURL *eh;
+  struct GNUNET_HashCode h_denom_pub;
 
   wsh = GNUNET_new (struct TALER_EXCHANGE_ReserveWithdrawHandle);
   wsh->exchange = exchange;
@@ -1009,9 +1010,11 @@ reserve_withdraw_internal (struct TALER_EXCHANGE_Handle 
*exchange,
   wsh->pk = pk;
   wsh->reserve_pub = *reserve_pub;
   wsh->c_hash = pd->c_hash;
-  withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
+  GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
+                                     &h_denom_pub);
+  withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub_hash and coin_ev */
                             " s:o, s:o}",/* reserve_pub and reserve_sig */
-                            "denom_pub", GNUNET_JSON_from_rsa_public_key 
(pk->key.rsa_public_key),
+                            "denom_pub_hash", GNUNET_JSON_from_data_auto 
(&h_denom_pub),
                             "coin_ev", GNUNET_JSON_from_data (pd->coin_ev,
                                                               
pd->coin_ev_size),
                             "reserve_pub", GNUNET_JSON_from_data_auto 
(reserve_pub),
diff --git a/src/util/crypto.c b/src/util/crypto.c
index b44c31ff..95eb11eb 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -77,22 +77,33 @@ TALER_gcrypt_init ()
  * is not expired, and the signature is correct.
  *
  * @param coin_public_info the coin public info to check for validity
+ * @param denom_pub denomination key, must match @a coin_public_info's 
`denom_pub_hash`
  * @return #GNUNET_YES if the coin is valid,
  *         #GNUNET_NO if it is invalid
  *         #GNUNET_SYSERR if an internal error occured
  */
 int
-TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info)
+TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info,
+                       const struct TALER_DenominationPublicKey *denom_pub)
 {
   struct GNUNET_HashCode c_hash;
-
+#if 1 /* sanity check of invariant, could probably be disabled in production
+         for slightly more performance */
+  struct GNUNET_HashCode d_hash;
+
+  GNUNET_CRYPTO_rsa_public_key_hash (denom_pub->rsa_public_key,
+                                     &d_hash);
+  GNUNET_assert (0 ==
+                 GNUNET_memcmp (&d_hash,
+                                &coin_public_info->denom_pub_hash));
+#endif
   GNUNET_CRYPTO_hash (&coin_public_info->coin_pub,
                       sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
                       &c_hash);
   if (GNUNET_OK !=
       GNUNET_CRYPTO_rsa_verify (&c_hash,
                                 coin_public_info->denom_sig.rsa_signature,
-                                coin_public_info->denom_pub.rsa_public_key))
+                                denom_pub->rsa_public_key))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                 "coin signature is invalid\n");

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



reply via email to

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