diff options
author | Christian Grothoff <christian@grothoff.org> | 2016-08-05 16:08:19 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2016-08-05 16:08:19 +0200 |
commit | 745719dbc1482734ab3ca7a20541ee8a12ecb69c (patch) | |
tree | 68ca6a1f328f59351a69064c72dc87b92756b689 | |
parent | e800772c85e1e1399c756162921c3f557794ffea (diff) |
first half of changing refresh protocol to derive all key data from DH
-rw-r--r-- | src/exchange-lib/exchange_api_refresh.c | 215 | ||||
-rw-r--r-- | src/exchange-lib/exchange_api_refresh_link.c | 39 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_db.c | 61 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_db.h | 4 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_refresh.c | 106 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_responses.c | 22 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_responses.h | 5 | ||||
-rw-r--r-- | src/exchange/taler-exchange-httpd_test.c | 17 | ||||
-rw-r--r-- | src/exchangedb/plugin_exchangedb_postgres.c | 104 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 177 | ||||
-rw-r--r-- | src/include/taler_exchangedb_plugin.h | 43 | ||||
-rw-r--r-- | src/include/taler_signatures.h | 25 | ||||
-rw-r--r-- | src/util/crypto.c | 357 | ||||
-rw-r--r-- | src/util/test_crypto.c | 115 |
14 files changed, 323 insertions, 967 deletions
diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c index f259daa54..09e1a09bb 100644 --- a/src/exchange-lib/exchange_api_refresh.c +++ b/src/exchange-lib/exchange_api_refresh.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2015 GNUnet e.V. + Copyright (C) 2015, 2016 GNUnet e.V. TALER is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -93,26 +93,6 @@ struct MeltedCoinP /** - * Header for serializations of coin-specific information about the - * fresh coins we generate during a melt. - */ -struct FreshCoinP -{ - - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * The blinding key. - */ - struct TALER_DenominationBlindingKeyP blinding_key; - -}; - - -/** * Header of serialized data about a melt operation, suitable for * persisting it on disk. */ @@ -125,12 +105,6 @@ struct MeltDataP struct GNUNET_HashCode melt_session_hash; /** - * Link secret used to encrypt the @a coin_priv and the blinding - * key in the linkage data for the respective cut-and-choose dimension. - */ - struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA]; - - /** * Number of coins we are melting, in NBO */ uint16_t num_melted_coins GNUNET_PACKED; @@ -144,7 +118,7 @@ struct MeltDataP 1) struct MeltedCoinP melted_coins[num_melted_coins]; 2) struct TALER_EXCHANGE_DenomPublicKey fresh_pks[num_fresh_coins]; 3) TALER_CNC_KAPPA times: - 3a) struct FreshCoinP fresh_coins[num_fresh_coins]; + 3a) struct TALER_FreshCoinP fresh_coins[num_fresh_coins]; */ }; @@ -212,11 +186,6 @@ struct MeltData struct GNUNET_HashCode melt_session_hash; /** - * Link secrets for each cut-and-choose dimension. - */ - struct TALER_LinkSecretP link_secrets[TALER_CNC_KAPPA]; - - /** * Number of coins we are creating */ uint16_t num_fresh_coins; @@ -236,7 +205,7 @@ struct MeltData * Arrays of @e num_fresh_coins with information about the fresh * coins to be created, for each cut-and-choose dimension. */ - struct FreshCoinP *fresh_coins[TALER_CNC_KAPPA]; + struct TALER_FreshCoinP *fresh_coins[TALER_CNC_KAPPA]; }; @@ -522,15 +491,15 @@ deserialize_denomination_key (struct TALER_DenominationPublicKey *dk, * @a buf is NULL, number of bytes required */ static size_t -serialize_fresh_coin (const struct FreshCoinP *fc, +serialize_fresh_coin (const struct TALER_FreshCoinP *fc, char *buf, size_t off) { if (NULL != buf) memcpy (&buf[off], fc, - sizeof (struct FreshCoinP)); - return sizeof (struct FreshCoinP); + sizeof (struct TALER_FreshCoinP)); + return sizeof (struct TALER_FreshCoinP); } @@ -544,12 +513,12 @@ serialize_fresh_coin (const struct FreshCoinP *fc, * @return number of bytes read from @a buf, 0 on error */ static size_t -deserialize_fresh_coin (struct FreshCoinP *fc, +deserialize_fresh_coin (struct TALER_FreshCoinP *fc, const char *buf, size_t size, int *ok) { - if (size < sizeof (struct FreshCoinP)) + if (size < sizeof (struct TALER_FreshCoinP)) { GNUNET_break (0); *ok = GNUNET_NO; @@ -557,8 +526,8 @@ deserialize_fresh_coin (struct FreshCoinP *fc, } memcpy (fc, buf, - sizeof (struct FreshCoinP)); - return sizeof (struct FreshCoinP); + sizeof (struct TALER_FreshCoinP)); + return sizeof (struct TALER_FreshCoinP); } @@ -598,8 +567,6 @@ serialize_melt_data (const struct MeltData *md, size = sizeof (struct MeltDataP); mdp = (struct MeltDataP *) buf; mdp->melt_session_hash = md->melt_session_hash; - for (i=0;i<TALER_CNC_KAPPA;i++) - mdp->link_secrets[i] = md->link_secrets[i]; mdp->num_fresh_coins = htons (md->num_fresh_coins); } size += serialize_melted_coin (&md->melted_coin, @@ -646,14 +613,12 @@ deserialize_melt_data (const char *buf, sizeof (struct MeltDataP)); md = GNUNET_new (struct MeltData); md->melt_session_hash = mdp.melt_session_hash; - for (i=0;i<TALER_CNC_KAPPA;i++) - md->link_secrets[i] = mdp.link_secrets[i]; md->num_fresh_coins = ntohs (mdp.num_fresh_coins); md->fresh_pks = GNUNET_new_array (md->num_fresh_coins, struct TALER_DenominationPublicKey); for (i=0;i<TALER_CNC_KAPPA;i++) md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins, - struct FreshCoinP); + struct TALER_FreshCoinP); off = sizeof (struct MeltDataP); ok = GNUNET_YES; off += deserialize_melted_coin (&md->melted_coin, @@ -688,27 +653,6 @@ deserialize_melt_data (const char *buf, /** - * Setup information for a fresh coin. - * - * @param[out] fc value to initialize - * @param pk denomination information for the fresh coin - */ -static void -setup_fresh_coin (struct FreshCoinP *fc, - const struct TALER_EXCHANGE_DenomPublicKey *pk) -{ - struct GNUNET_CRYPTO_EddsaPrivateKey *epk; - - epk = GNUNET_CRYPTO_eddsa_key_create (); - fc->coin_priv.eddsa_priv = *epk; - GNUNET_free (epk); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, - &fc->blinding_key, - sizeof (fc->blinding_key)); -} - - -/** * Melt (partially spent) coins to obtain fresh coins that are * unlinkable to the original coin(s). Note that melting more * than one coin in a single request will make those coins linkable, @@ -765,25 +709,37 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr unsigned int j; struct GNUNET_HashContext *hash_context; struct TALER_Amount total; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct TALER_TransferSecretP trans_sec[TALER_CNC_KAPPA]; + GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv, + &coin_pub.eddsa_pub); + hash_context = GNUNET_CRYPTO_hash_context_start (); /* build up melt data structure */ for (i=0;i<TALER_CNC_KAPPA;i++) - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, - &md.link_secrets[i], - sizeof (struct TALER_LinkSecretP)); - md.num_fresh_coins = fresh_pks_len; - md.melted_coin.coin_priv = *melt_priv; - md.melted_coin.melt_amount_with_fee = *melt_amount; - md.melted_coin.fee_melt = melt_pk->fee_refresh; - md.melted_coin.original_value = melt_pk->value; - for (j=0;j<TALER_CNC_KAPPA;j++) { struct GNUNET_CRYPTO_EcdhePrivateKey *tpk; + struct TALER_TransferPublicKeyP tp; tpk = GNUNET_CRYPTO_ecdhe_key_create (); - md.melted_coin.transfer_priv[j].ecdhe_priv = *tpk; + md.melted_coin.transfer_priv[i].ecdhe_priv = *tpk; GNUNET_free (tpk); + + GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv, + &tp.ecdhe_pub); + GNUNET_CRYPTO_hash_context_read (hash_context, + &tp, + sizeof (struct TALER_TransferPublicKeyP)); + /* DH */ + TALER_link_derive_transfer_secret (melt_priv, + &md.melted_coin.transfer_priv[i], + &trans_sec[i]); } + md.num_fresh_coins = fresh_pks_len; + md.melted_coin.coin_priv = *melt_priv; + md.melted_coin.melt_amount_with_fee = *melt_amount; + md.melted_coin.fee_melt = melt_pk->fee_refresh; + md.melted_coin.original_value = melt_pk->value; md.melted_coin.expire_deposit = melt_pk->expire_deposit; md.melted_coin.pub_key.rsa_public_key @@ -798,11 +754,12 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr for (i=0;i<TALER_CNC_KAPPA;i++) { md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len, - struct FreshCoinP); + struct TALER_FreshCoinP); for (j=0;j<fresh_pks_len;j++) { - setup_fresh_coin (&md.fresh_coins[i][j], - &fresh_pks[j]); + TALER_setup_fresh_coin (&trans_sec[i], + j, + &md.fresh_coins[i][j]); } } @@ -830,7 +787,7 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr TALER_amount_cmp (&total, melt_amount) ) { - /* Eh, this operation is more expensive than the + /* Eh, this operation is more expensive than the @a melt_amount. This is not OK. */ GNUNET_break (0); free_melt_data (&md); @@ -839,7 +796,6 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr /* now compute melt session hash */ - hash_context = GNUNET_CRYPTO_hash_context_start (); for (i=0;i<fresh_pks_len;i++) { char *buf; @@ -853,11 +809,8 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr GNUNET_free (buf); } { - struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_AmountNBO melt_amountn; - GNUNET_CRYPTO_eddsa_key_get_public (&melt_priv->eddsa_priv, - &coin_pub.eddsa_pub); GNUNET_CRYPTO_hash_context_read (hash_context, &coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP)); @@ -872,13 +825,11 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr { for (j = 0; j < fresh_pks_len; j++) { - const struct FreshCoinP *fc; /* coin this is about */ + const struct TALER_FreshCoinP *fc; /* coin this is about */ struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_HashCode coin_hash; char *coin_ev; /* blinded message to be signed (in envelope) for each coin */ size_t coin_ev_size; - struct TALER_RefreshLinkDecryptedP rld; - struct TALER_RefreshLinkEncryptedP rle; fc = &md.fresh_coins[i][j]; GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv, @@ -902,35 +853,8 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr coin_ev, coin_ev_size); GNUNET_free (coin_ev); - - rld.coin_priv = fc->coin_priv; - rld.blinding_key = fc->blinding_key; - TALER_refresh_encrypt (&rld, - &md.link_secrets[i], - &rle); - GNUNET_CRYPTO_hash_context_read (hash_context, - &rle, - sizeof (rle)); } } - for (i = 0; i < TALER_CNC_KAPPA; i++) - { - struct TALER_RefreshCommitLinkP rcl; - struct TALER_TransferSecretP trans_sec; - - GNUNET_CRYPTO_ecdhe_key_get_public (&md.melted_coin.transfer_priv[i].ecdhe_priv, - &rcl.transfer_pub.ecdhe_pub); - TALER_link_derive_transfer_secret (melt_priv, - &md.melted_coin.transfer_priv[i], - &trans_sec); - TALER_transfer_encrypt (&md.link_secrets[i], - &trans_sec, - &rcl.shared_secret_enc); - GNUNET_CRYPTO_hash_context_read (hash_context, - &rcl, - sizeof (struct TALER_RefreshCommitLinkP)); - } - GNUNET_CRYPTO_hash_context_finish (hash_context, &md.melt_session_hash); @@ -1315,8 +1239,6 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, json_t *melt_coin; json_t *coin_evs; json_t *transfer_pubs; - json_t *secret_encs; - json_t *link_encs; json_t *tmp; struct TALER_EXCHANGE_RefreshMeltHandle *rmh; CURL *eh; @@ -1335,14 +1257,12 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, return NULL; } - /* build JSON request, each of the 6 arrays first */ + /* build JSON request, each of the 4 arrays first */ new_denoms = json_array (); melt_coin = melted_coin_to_json (&md->melt_session_hash, &md->melted_coin); coin_evs = json_array (); transfer_pubs = json_array (); - secret_encs = json_array (); - link_encs = json_array (); /* now transfer_pubs */ for (j=0;j<TALER_CNC_KAPPA;j++) @@ -1357,25 +1277,6 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, GNUNET_JSON_from_data_auto (&transfer_pub))); } - /* now secret_encs */ - for (j=0;j<TALER_CNC_KAPPA;j++) - { - const struct MeltedCoin *mc = &md->melted_coin; - struct TALER_EncryptedLinkSecretP els; - struct TALER_TransferSecretP trans_sec; - - TALER_link_derive_transfer_secret (&mc->coin_priv, - &mc->transfer_priv[j], - &trans_sec); - GNUNET_assert (GNUNET_OK == - TALER_transfer_encrypt (&md->link_secrets[j], - &trans_sec, - &els)); - GNUNET_assert (0 == - json_array_append_new (secret_encs, - GNUNET_JSON_from_data_auto (&els))); - } - /* now new_denoms */ for (i=0;i<md->num_fresh_coins;i++) { @@ -1385,37 +1286,13 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, (md->fresh_pks[i].rsa_public_key))); } - /* now link_encs */ - for (j=0;j<TALER_CNC_KAPPA;j++) - { - tmp = json_array (); - for (i=0;i<md->num_fresh_coins;i++) - { - const struct FreshCoinP *fc = &md->fresh_coins[j][i]; - struct TALER_RefreshLinkDecryptedP rld; - struct TALER_RefreshLinkEncryptedP rle; - - rld.coin_priv = fc->coin_priv; - rld.blinding_key = fc->blinding_key; - TALER_refresh_encrypt (&rld, - &md->link_secrets[j], - &rle); - GNUNET_assert (0 == - json_array_append_new (tmp, - GNUNET_JSON_from_data_auto (&rle))); - } - GNUNET_assert (0 == - json_array_append_new (link_encs, - tmp)); - } - /* now coin_evs */ for (j=0;j<TALER_CNC_KAPPA;j++) { tmp = json_array (); for (i=0;i<md->num_fresh_coins;i++) { - const struct FreshCoinP *fc = &md->fresh_coins[j][i]; + const struct TALER_FreshCoinP *fc = &md->fresh_coins[j][i]; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_HashCode coin_hash; char *coin_ev; /* blinded message to be signed (in envelope) for each coin */ @@ -1440,8 +1317,6 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, json_decref (coin_evs); json_decref (melt_coin); json_decref (transfer_pubs); - json_decref (secret_encs); - json_decref (link_encs); return NULL; } GNUNET_assert (0 == @@ -1456,13 +1331,11 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange, } /* finally, assemble main JSON request from constitutent arrays */ - melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", + melt_obj = json_pack ("{s:o, s:o, s:o, s:o}", "new_denoms", new_denoms, "melt_coin", melt_coin, "coin_evs", coin_evs, - "transfer_pubs", transfer_pubs, - "secret_encs", secret_encs, - "link_encs", link_encs); + "transfer_pubs", transfer_pubs); /* and now we can at last begin the actual request handling */ rmh = GNUNET_new (struct TALER_EXCHANGE_RefreshMeltHandle); @@ -1627,7 +1500,7 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh, } for (i=0;i<rrh->md->num_fresh_coins;i++) { - const struct FreshCoinP *fc; + const struct TALER_FreshCoinP *fc; struct TALER_DenominationPublicKey *pk; json_t *jsonai; struct GNUNET_CRYPTO_RsaSignature *blind_sig; diff --git a/src/exchange-lib/exchange_api_refresh_link.c b/src/exchange-lib/exchange_api_refresh_link.c index 2a1e3048b..31c27fe98 100644 --- a/src/exchange-lib/exchange_api_refresh_link.c +++ b/src/exchange-lib/exchange_api_refresh_link.c @@ -75,8 +75,8 @@ struct TALER_EXCHANGE_RefreshLinkHandle * * @param rlh refresh link handle * @param json json reply with the data for one coin + * @param coin_num number of the coin to decode * @param trans_pub our transfer public key - * @param secret_enc encrypted key to decrypt link data * @param[out] coin_priv where to return private coin key * @param[out] sig where to return private coin signature * @param[out] pub where to return the public key for the coin @@ -85,24 +85,22 @@ struct TALER_EXCHANGE_RefreshLinkHandle static int parse_refresh_link_coin (const struct TALER_EXCHANGE_RefreshLinkHandle *rlh, const json_t *json, + unsigned int coin_num, const struct TALER_TransferPublicKeyP *trans_pub, - const struct TALER_EncryptedLinkSecretP *secret_enc, struct TALER_CoinSpendPrivateKeyP *coin_priv, struct TALER_DenominationSignature *sig, struct TALER_DenominationPublicKey *pub) { struct GNUNET_CRYPTO_RsaSignature *bsig; struct GNUNET_CRYPTO_RsaPublicKey *rpub; - struct TALER_RefreshLinkEncryptedP rle; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("link_enc", &rle), GNUNET_JSON_spec_rsa_public_key ("denom_pub", &rpub), GNUNET_JSON_spec_rsa_signature ("ev_sig", &bsig), GNUNET_JSON_spec_end() }; - struct TALER_RefreshLinkDecryptedP rld; - struct TALER_LinkSecretP secret; - + struct TALER_TransferSecretP secret; + struct TALER_FreshCoinP fc; + /* parse reply */ if (GNUNET_OK != GNUNET_JSON_parse (json, @@ -113,25 +111,18 @@ parse_refresh_link_coin (const struct TALER_EXCHANGE_RefreshLinkHandle *rlh, return GNUNET_SYSERR; } - if (GNUNET_OK != - TALER_link_decrypt_secret2 (secret_enc, - trans_pub, - &rlh->coin_priv, - &secret)) - { - GNUNET_break_op (0); - GNUNET_JSON_parse_free (spec); - return GNUNET_SYSERR; - } - TALER_refresh_decrypt (&rle, - &secret, - &rld); + TALER_link_recover_transfer_secret (trans_pub, + &rlh->coin_priv, + &secret); + TALER_setup_fresh_coin (&secret, + coin_num, + &fc); /* extract coin and signature */ - *coin_priv = rld.coin_priv; + *coin_priv = fc.coin_priv; sig->rsa_signature = GNUNET_CRYPTO_rsa_unblind (bsig, - &rld.blinding_key.bks, + &fc.blinding_key.bks, rpub); /* clean up */ pub->rsa_public_key = GNUNET_CRYPTO_rsa_public_key_dup (rpub); @@ -217,11 +208,9 @@ parse_refresh_link_ok (struct TALER_EXCHANGE_RefreshLinkHandle *rlh, { json_t *jsona; struct TALER_TransferPublicKeyP trans_pub; - struct TALER_EncryptedLinkSecretP secret_enc; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_json ("new_coins", &jsona), GNUNET_JSON_spec_fixed_auto ("transfer_pub", &trans_pub), - GNUNET_JSON_spec_fixed_auto ("secret_enc", &secret_enc), GNUNET_JSON_spec_end() }; @@ -248,8 +237,8 @@ parse_refresh_link_ok (struct TALER_EXCHANGE_RefreshLinkHandle *rlh, parse_refresh_link_coin (rlh, json_array_get (jsona, i), + i, &trans_pub, - &secret_enc, &coin_privs[i+off_coin], &sigs[i+off_coin], &pubs[i+off_coin])) diff --git a/src/exchange/taler-exchange-httpd_db.c b/src/exchange/taler-exchange-httpd_db.c index 99805653e..9847a7ba3 100644 --- a/src/exchange/taler-exchange-httpd_db.c +++ b/src/exchange/taler-exchange-httpd_db.c @@ -973,7 +973,7 @@ refresh_check_melt (struct MHD_Connection *connection, * @param commit_coin 2d array of coin commitments (what the exchange is to sign * once the "/refres/reveal" of cut and choose is done), * x-dimension must be #TALER_CNC_KAPPA - * @param commit_link array of coin link commitments (what the exchange is + * @param transfer_pubs array of transfer public keys (what the exchange is * to return via "/refresh/link" to enable linkage in the * future) of length #TALER_CNC_KAPPA * @return MHD result code @@ -985,7 +985,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, const struct TALER_DenominationPublicKey *denom_pubs, const struct TMH_DB_MeltDetails *coin_melt_detail, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, - const struct TALER_RefreshCommitLinkP *commit_link) + const struct TALER_TransferPublicKeyP *transfer_pubs) { struct TMH_KS_StateHandle *key_state; struct TALER_EXCHANGEDB_RefreshSession refresh_session; @@ -1082,11 +1082,11 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, for (i = 0; i < TALER_CNC_KAPPA; i++) { if (GNUNET_OK != - TMH_plugin->insert_refresh_commit_link (TMH_plugin->cls, - session, - session_hash, - i, - &commit_link[i])) + TMH_plugin->insert_refresh_transfer_public_key (TMH_plugin->cls, + session, + session_hash, + i, + &transfer_pubs[i])) { TMH_plugin->rollback (TMH_plugin->cls, session); @@ -1180,19 +1180,19 @@ check_commitment (struct MHD_Connection *connection, unsigned int num_newcoins, const struct TALER_DenominationPublicKey *denom_pubs) { - struct TALER_RefreshCommitLinkP commit_link; - struct TALER_LinkSecretP shared_secret; + struct TALER_TransferPublicKeyP transfer_pub; + struct TALER_TransferSecretP transfer_secret; struct TALER_TransferPublicKeyP transfer_pub_check; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins; unsigned int j; int ret; if (GNUNET_OK != - TMH_plugin->get_refresh_commit_link (TMH_plugin->cls, - session, - session_hash, - off, - &commit_link)) + TMH_plugin->get_refresh_transfer_public_key (TMH_plugin->cls, + session, + session_hash, + off, + &transfer_pub)) { GNUNET_break (0); return (MHD_YES == TMH_RESPONSE_reply_internal_db_error (connection)) @@ -1203,7 +1203,7 @@ check_commitment (struct MHD_Connection *connection, &transfer_pub_check.ecdhe_pub); if (0 != memcmp (&transfer_pub_check, - &commit_link.transfer_pub, + &transfer_pub, sizeof (struct TALER_TransferPublicKeyP))) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -1217,17 +1217,9 @@ check_commitment (struct MHD_Connection *connection, "transfer key"); } - if (GNUNET_OK != - TALER_link_decrypt_secret (&commit_link.shared_secret_enc, - transfer_priv, - &melt->coin.coin_pub, - &shared_secret)) - { - return (MHD_YES == - TMH_RESPONSE_reply_internal_error (connection, - "Transfer secret decryption error")) - ? GNUNET_NO : GNUNET_SYSERR; - } + TALER_link_reveal_transfer_secret (transfer_priv, + &melt->coin.coin_pub, + &transfer_secret); /* Check that the commitments for all new coins were correct */ commit_coins = GNUNET_new_array (num_newcoins, @@ -1249,23 +1241,23 @@ check_commitment (struct MHD_Connection *connection, for (j = 0; j < num_newcoins; j++) { - struct TALER_RefreshLinkDecryptedP link_data; + struct TALER_FreshCoinP fc; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_HashCode h_msg; char *buf; size_t buf_len; - TALER_refresh_decrypt (&commit_coins[j].refresh_link, - &shared_secret, - &link_data); - GNUNET_CRYPTO_eddsa_key_get_public (&link_data.coin_priv.eddsa_priv, + TALER_setup_fresh_coin (&transfer_secret, + j, + &fc); + GNUNET_CRYPTO_eddsa_key_get_public (&fc.coin_priv.eddsa_priv, &coin_pub.eddsa_pub); GNUNET_CRYPTO_hash (&coin_pub, sizeof (struct TALER_CoinSpendPublicKeyP), &h_msg); if (GNUNET_YES != GNUNET_CRYPTO_rsa_blind (&h_msg, - &link_data.blinding_key.bks, + &fc.blinding_key.bks, denom_pubs[j].rsa_public_key, &buf, &buf_len)) @@ -1598,13 +1590,11 @@ struct HTD_Context * @param cls closure, a `struct HTD_Context` * @param session_hash a session the coin was melted in * @param transfer_pub public transfer key for the session - * @param shared_secret_enc set to shared secret for the session */ static void handle_transfer_data (void *cls, const struct GNUNET_HashCode *session_hash, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct TALER_EncryptedLinkSecretP *shared_secret_enc) + const struct TALER_TransferPublicKeyP *transfer_pub) { struct HTD_Context *ctx = cls; struct TALER_EXCHANGEDB_LinkDataList *ldl; @@ -1632,7 +1622,6 @@ handle_transfer_data (void *cls, ctx->num_sessions + 1); lsi = &ctx->sessions[ctx->num_sessions - 1]; lsi->transfer_pub = *transfer_pub; - lsi->shared_secret_enc = *shared_secret_enc; lsi->ldl = ldl; } diff --git a/src/exchange/taler-exchange-httpd_db.h b/src/exchange/taler-exchange-httpd_db.h index 8685cd5ae..67fe8d5b4 100644 --- a/src/exchange/taler-exchange-httpd_db.h +++ b/src/exchange/taler-exchange-httpd_db.h @@ -136,7 +136,7 @@ struct TMH_DB_MeltDetails * @param coin_melt_details signatures and (residual) value of and information about the respective coin to be melted * @param commit_coin 2d array of coin commitments (what the exchange is to sign * once the "/refres/reveal" of cut and choose is done) - * @param commit_link array of coin link commitments (what the exchange is + * @param transfer_pubs array of transfer public keys (what the exchange is * to return via "/refresh/link" to enable linkage in the * future) of length #TALER_CNC_KAPPA * @return MHD result code @@ -148,7 +148,7 @@ TMH_DB_execute_refresh_melt (struct MHD_Connection *connection, const struct TALER_DenominationPublicKey *denom_pubs, const struct TMH_DB_MeltDetails *coin_melt_details, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, - const struct TALER_RefreshCommitLinkP *commit_link); + const struct TALER_TransferPublicKeyP *transfer_pubs); /** diff --git a/src/exchange/taler-exchange-httpd_refresh.c b/src/exchange/taler-exchange-httpd_refresh.c index 40a00e163..3dbffe511 100644 --- a/src/exchange/taler-exchange-httpd_refresh.c +++ b/src/exchange/taler-exchange-httpd_refresh.c @@ -43,7 +43,7 @@ * @param session_hash hash over the data that the client commits to * @param commit_coin 2d array of coin commitments (what the exchange is to sign * once the "/refres/reveal" of cut and choose is done) - * @param commit_link array of coin link commitments (what the exchange is + * @param transfer_pubs array of transfer public keys (which the exchange is * to return via "/refresh/link" to enable linkage in the * future) of length #TALER_CNC_KAPPA * @return MHD result code @@ -55,7 +55,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, const struct TMH_DB_MeltDetails *coin_melt_details, const struct GNUNET_HashCode *session_hash, struct TALER_EXCHANGEDB_RefreshCommitCoin *const* commit_coin, - const struct TALER_RefreshCommitLinkP * commit_link) + const struct TALER_TransferPublicKeyP *transfer_pubs) { unsigned int i; struct TMH_KS_StateHandle *key_state; @@ -146,7 +146,7 @@ handle_refresh_melt_binary (struct MHD_Connection *connection, denom_pubs, coin_melt_details, commit_coin, - commit_link); + transfer_pubs); } @@ -321,9 +321,7 @@ free_commit_coins (struct TALER_EXCHANGEDB_RefreshCommitCoin **commit_coin, * @param new_denoms array of denomination keys * @param melt_coin coin to melt * @param transfer_pubs #TALER_CNC_KAPPA-dimensional array of transfer keys - * @param secret_encs #TALER_CNC_KAPPA-dimensional array of old coin secrets * @param coin_evs #TALER_CNC_KAPPA-dimensional array of envelopes to sign - * @param link_encs #TALER_CNC_KAPPA-dimensional array of `length(@a new_denoms)` encrypted links (2D array) * @return MHD result code */ static int @@ -331,9 +329,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, const json_t *new_denoms, const json_t *melt_coin, const json_t *transfer_pubs, - const json_t *secret_encs, - const json_t *coin_evs, - const json_t *link_encs) + const json_t *coin_evs) { int res; unsigned int i; @@ -344,11 +340,36 @@ handle_refresh_melt_json (struct MHD_Connection *connection, struct GNUNET_HashCode session_hash; struct GNUNET_HashContext *hash_context; struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coin[TALER_CNC_KAPPA]; - struct TALER_RefreshCommitLinkP commit_link[TALER_CNC_KAPPA]; + struct TALER_TransferPublicKeyP transfer_pub[TALER_CNC_KAPPA]; + /* For the signature check, we hash most of the inputs together (except for the signatures on the coins). */ hash_context = GNUNET_CRYPTO_hash_context_start (); + + for (i = 0; i < TALER_CNC_KAPPA; i++) + { + struct GNUNET_JSON_Specification trans_spec[] = { + GNUNET_JSON_spec_fixed_auto (NULL, &transfer_pub[i]), + GNUNET_JSON_spec_end () + }; + + res = TMH_PARSE_json_array (connection, + transfer_pubs, + trans_spec, + i, -1); + if (GNUNET_OK != res) + { + GNUNET_break_op (0); + res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; + goto cleanup; + } + GNUNET_CRYPTO_hash_context_read (hash_context, + &transfer_pub[i], + sizeof (struct TALER_TransferPublicKeyP)); + } + + num_newcoins = json_array_size (new_denoms); denom_pubs = GNUNET_new_array (num_newcoins, struct TALER_DenominationPublicKey); @@ -405,7 +426,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection, /* parse JSON arrays into binary arrays and hash everything together for the signature check */ memset (commit_coin, 0, sizeof (commit_coin)); - memset (commit_link, 0, sizeof (commit_link)); for (i = 0; i < TALER_CNC_KAPPA; i++) { commit_coin[i] = GNUNET_new_array (num_newcoins, @@ -419,11 +439,6 @@ handle_refresh_melt_json (struct MHD_Connection *connection, &rcc->coin_ev_size), GNUNET_JSON_spec_end () }; - struct GNUNET_JSON_Specification link_spec[] = { - GNUNET_JSON_spec_fixed_auto (NULL, - &rcc->refresh_link), - GNUNET_JSON_spec_end () - }; res = TMH_PARSE_json_array (connection, coin_evs, @@ -439,59 +454,10 @@ handle_refresh_melt_json (struct MHD_Connection *connection, GNUNET_CRYPTO_hash_context_read (hash_context, rcc->coin_ev, rcc->coin_ev_size); - res = TMH_PARSE_json_array (connection, - link_encs, - link_spec, - i, j, -1); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - goto cleanup; - } - GNUNET_CRYPTO_hash_context_read (hash_context, - &rcc->refresh_link, - sizeof (rcc->refresh_link)); - GNUNET_JSON_parse_free (link_spec); + GNUNET_JSON_parse_free (coin_spec); } } - for (i = 0; i < TALER_CNC_KAPPA; i++) - { - struct TALER_RefreshCommitLinkP *rcl = &commit_link[i]; - struct GNUNET_JSON_Specification trans_spec[] = { - GNUNET_JSON_spec_fixed_auto (NULL, &rcl->transfer_pub), - GNUNET_JSON_spec_end () - }; - struct GNUNET_JSON_Specification sec_spec[] = { - GNUNET_JSON_spec_fixed_auto (NULL, &rcl->shared_secret_enc), - GNUNET_JSON_spec_end () - }; - - res = TMH_PARSE_json_array (connection, - transfer_pubs, - trans_spec, - i, -1); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - goto cleanup; - } - res = TMH_PARSE_json_array (connection, - secret_encs, - sec_spec, - i, -1); - if (GNUNET_OK != res) - { - GNUNET_break_op (0); - res = (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; - goto cleanup; - } - GNUNET_CRYPTO_hash_context_read (hash_context, - rcl, - sizeof (struct TALER_RefreshCommitLinkP)); - } GNUNET_CRYPTO_hash_context_finish (hash_context, &session_hash); hash_context = NULL; @@ -513,7 +479,7 @@ handle_refresh_melt_json (struct MHD_Connection *connection, &coin_melt_details, &session_hash, commit_coin, - commit_link); + transfer_pub); cleanup: free_commit_coins (commit_coin, TALER_CNC_KAPPA, @@ -558,17 +524,13 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh, json_t *new_denoms; json_t *melt_coin; json_t *coin_evs; - json_t *link_encs; json_t *transfer_pubs; - json_t *secret_encs; int res; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_json ("new_denoms", &new_denoms), GNUNET_JSON_spec_json ("melt_coin", &melt_coin), GNUNET_JSON_spec_json ("coin_evs", &coin_evs), - GNUNET_JSON_spec_json ("link_encs", &link_encs), GNUNET_JSON_spec_json ("transfer_pubs", &transfer_pubs), - GNUNET_JSON_spec_json ("secret_encs", &secret_encs), GNUNET_JSON_spec_end () }; @@ -608,9 +570,7 @@ TMH_REFRESH_handler_refresh_melt (struct TMH_RequestHandler *rh, new_denoms, melt_coin, transfer_pubs, - secret_encs, - coin_evs, - link_encs); + coin_evs); GNUNET_JSON_parse_free (spec); return res; } diff --git a/src/exchange/taler-exchange-httpd_responses.c b/src/exchange/taler-exchange-httpd_responses.c index bbcdbe35f..b39b68a44 100644 --- a/src/exchange/taler-exchange-httpd_responses.c +++ b/src/exchange/taler-exchange-httpd_responses.c @@ -1028,7 +1028,7 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, { json_t *info_commit_k; json_t *info_link_k; - const struct TALER_RefreshCommitLinkP *cl; + const struct TALER_TransferPublicKeyP *transfer_pub; info_commit_k = json_array (); for (i=0;i<mc->num_newcoins;i++) @@ -1042,13 +1042,6 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, "coin_ev", GNUNET_JSON_from_data (cc->coin_ev, cc->coin_ev_size)); - json_object_set_new (cc_json, - "coin_priv_enc", - GNUNET_JSON_from_data_auto (cc->refresh_link.coin_priv_enc)); - json_object_set_new (cc_json, - "blinding_key_enc", - GNUNET_JSON_from_data_auto (&cc->refresh_link.blinding_key_enc)); - GNUNET_assert (0 == json_array_append_new (info_commit_k, cc_json)); @@ -1058,13 +1051,10 @@ TMH_RESPONSE_reply_refresh_reveal_missmatch (struct MHD_Connection *connection, info_commit_k)); info_link_k = json_object (); - cl = &mc->commit_links[k]; + transfer_pub = &mc->transfer_pubs[k]; json_object_set_new (info_link_k, "transfer_pub", - GNUNET_JSON_from_data_auto (&cl->transfer_pub)); - json_object_set_new (info_link_k, - "shared_secret_enc", - GNUNET_JSON_from_data_auto (&cl->shared_secret_enc)); + GNUNET_JSON_from_data_auto (transfer_pub)); GNUNET_assert (0 == json_array_append_new (info_links, info_link_k)); @@ -1114,9 +1104,6 @@ TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, obj = json_object (); json_object_set_new (obj, - "link_enc", - GNUNET_JSON_from_data_auto (&pos->link_data_enc)); - json_object_set_new (obj, "denom_pub", GNUNET_JSON_from_rsa_public_key (pos->denom_pub.rsa_public_key)); json_object_set_new (obj, @@ -1133,9 +1120,6 @@ TMH_RESPONSE_reply_refresh_link_success (struct MHD_Connection *connection, json_object_set_new (root, "transfer_pub", GNUNET_JSON_from_data_auto (&sessions[i].transfer_pub)); - json_object_set_new (root, - "secret_enc", - GNUNET_JSON_from_data_auto (&sessions[i].shared_secret_enc)); GNUNET_assert (0 == json_array_append_new (mlist, root)); diff --git a/src/exchange/taler-exchange-httpd_responses.h b/src/exchange/taler-exchange-httpd_responses.h index ce6710080..4079bd12b 100644 --- a/src/exchange/taler-exchange-httpd_responses.h +++ b/src/exchange/taler-exchange-httpd_responses.h @@ -522,11 +522,6 @@ struct TMH_RESPONSE_LinkSessionInfo struct TALER_TransferPublicKeyP transfer_pub; /** - * Encrypted shared secret for decrypting the transfer secrets. - */ - struct TALER_EncryptedLinkSecretP shared_secret_enc; - - /** * Linked data of coins being created in the session. */ struct TALER_EXCHANGEDB_LinkDataList *ldl; diff --git a/src/exchange/taler-exchange-httpd_test.c b/src/exchange/taler-exchange-httpd_test.c index d8849d310..b371bd215 100644 --- a/src/exchange/taler-exchange-httpd_test.c +++ b/src/exchange/taler-exchange-httpd_test.c @@ -535,16 +535,14 @@ TMH_TEST_handler_test_transfer (struct TMH_RequestHandler *rh, { json_t *json; int res; - struct TALER_EncryptedLinkSecretP secret_enc; struct TALER_TransferPrivateKeyP trans_priv; struct TALER_CoinSpendPublicKeyP coin_pub; struct GNUNET_JSON_Specification spec[] = { - GNUNET_JSON_spec_fixed_auto ("secret_enc", &secret_enc), GNUNET_JSON_spec_fixed_auto ("trans_priv", &trans_priv), GNUNET_JSON_spec_fixed_auto ("coin_pub", &coin_pub), GNUNET_JSON_spec_end () }; - struct TALER_LinkSecretP secret; + struct TALER_TransferSecretP secret; res = TMH_PARSE_post_json (connection, connection_cls, @@ -561,16 +559,9 @@ TMH_TEST_handler_test_transfer (struct TMH_RequestHandler *rh, json_decref (json); if (GNUNET_YES != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; - if (GNUNET_OK != - TALER_link_decrypt_secret (&secret_enc, - &trans_priv, - &coin_pub, - &secret)) - { - GNUNET_JSON_parse_free (spec); - return TMH_RESPONSE_reply_internal_error (connection, - "Failed to decrypt secret"); - } + TALER_link_reveal_transfer_secret (&trans_priv, + &coin_pub, + &secret); return TMH_RESPONSE_reply_json_pack (connection, MHD_HTTP_OK, "{s:o}", diff --git a/src/exchangedb/plugin_exchangedb_postgres.c b/src/exchangedb/plugin_exchangedb_postgres.c index 508a242b4..47d59c862 100644 --- a/src/exchangedb/plugin_exchangedb_postgres.c +++ b/src/exchangedb/plugin_exchangedb_postgres.c @@ -221,7 +221,7 @@ postgres_drop_tables (void *cls) SQLEXEC_ (conn, "DROP TABLE IF EXISTS refresh_commit_coin;"); SQLEXEC_ (conn, - "DROP TABLE IF EXISTS refresh_commit_link;"); + "DROP TABLE IF EXISTS refresh_transfer_public_key;"); SQLEXEC_ (conn, "DROP TABLE IF EXISTS refunds;"); SQLEXEC_ (conn, @@ -385,15 +385,14 @@ postgres_create_tables (void *cls) oldcoin index and the cut-and-choose index (from 0 to #TALER_CNC_KAPPA-1), as well as the actual link data (the transfer public key and the encrypted link secret) */ - SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_commit_link " + SQLEXEC("CREATE TABLE IF NOT EXISTS refresh_transfer_public_key " "(session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) ON DELETE CASCADE" ",transfer_pub BYTEA NOT NULL CHECK(LENGTH(transfer_pub)=32)" - ",link_secret_enc BYTEA NOT NULL CHECK(LENGTH(link_secret_enc)=64)" ",cnc_index INT2 NOT NULL" ",UNIQUE (session_hash, cnc_index)" ")"); - SQLEXEC_INDEX("CREATE INDEX refresh_commit_link_session_hash_index " - "ON refresh_commit_link(session_hash, cnc_index)"); + SQLEXEC_INDEX("CREATE INDEX refresh_transfer_public_key_index " + "ON refresh_transfer_public_key(session_hash, cnc_index)"); /* Table with the commitments for the new coins that are to be created during a melting session. Includes the session, the cut-and-choose @@ -405,7 +404,6 @@ postgres_create_tables (void *cls) "(session_hash BYTEA NOT NULL REFERENCES refresh_sessions (session_hash) ON DELETE CASCADE" ",cnc_index INT2 NOT NULL" ",newcoin_index INT2 NOT NULL" - ",link_vector_enc BYTEA NOT NULL CHECK(LENGTH(link_vector_enc)=64)" ",coin_ev BYTEA NOT NULL" ",UNIQUE (session_hash, cnc_index, newcoin_index)" ")"); @@ -827,25 +825,23 @@ postgres_prepare (PGconn *db_conn) 1, NULL); - /* Used in #postgres_insert_refresh_commit_link() to + /* Used in #postgres_insert_transfer_public_key() to store commitments */ - PREPARE ("insert_refresh_commit_link", - "INSERT INTO refresh_commit_link " + PREPARE ("insert_transfer_public_key", + "INSERT INTO refresh_transfer_public_key " "(session_hash" ",transfer_pub" ",cnc_index" - ",link_secret_enc" ") VALUES " - "($1, $2, $3, $4);", - 4, NULL); + "($1, $2, $3);", + 3, NULL); - /* Used in #postgres_get_refresh_commit_link() to + /* Used in #postgres_get_refresh_transfer_public_key() to retrieve original commitments during /refresh/reveal */ - PREPARE ("get_refresh_commit_link", + PREPARE ("get_refresh_transfer_public_key", "SELECT" " transfer_pub" - ",link_secret_enc" - " FROM refresh_commit_link" + " FROM refresh_transfer_public_key" " WHERE session_hash=$1 AND cnc_index=$2", 2, NULL); @@ -856,19 +852,17 @@ postgres_prepare (PGconn *db_conn) "(session_hash" ",cnc_index" ",newcoin_index" - ",link_vector_enc" ",coin_ev" ") VALUES " - "($1, $2, $3, $4, $5);", - 5, NULL); + "($1, $2, $3, $4);", + 4, NULL); /* Used in #postgres_get_refresh_commit_coins() to retrieve the original coin envelopes, to either be verified or signed. */ PREPARE ("get_refresh_commit_coin", "SELECT" - " link_vector_enc" - ",coin_ev" + " coin_ev" " FROM refresh_commit_coin" " WHERE session_hash=$1 AND cnc_index=$2 AND newcoin_index=$3", 3, NULL); @@ -1068,8 +1062,7 @@ postgres_prepare (PGconn *db_conn) 3, NULL); /* Used in #postgres_get_link_data_list(). We use the session_hash - to obtain the "noreveal_index" for that session, and then select - the encrypted link vectors (link_vector_enc) and the + to obtain the "noreveal_index" for that session, and then select the corresponding signatures (ev_sig) and the denomination keys from the respective tables (namely refresh_melts and refresh_order) using the session_hash as the primary filter (on join) and the @@ -1081,7 +1074,7 @@ postgres_prepare (PGconn *db_conn) being exchangeed in the refresh ops. NOTE: There may be more efficient ways to express the same query. */ PREPARE ("get_link", - "SELECT link_vector_enc,ev_sig,ro.denom_pub" + "SELECT ev_sig,ro.denom_pub" " FROM refresh_sessions rs " " JOIN refresh_order ro USING (session_hash)" " JOIN refresh_commit_coin rcc USING (session_hash)" @@ -1100,9 +1093,9 @@ postgres_prepare (PGconn *db_conn) NOTE: This may (in theory) return multiple results, one per session that the old coin was melted into. */ PREPARE ("get_transfer", - "SELECT transfer_pub,link_secret_enc,session_hash" + "SELECT transfer_pub,session_hash" " FROM refresh_sessions rs" - " JOIN refresh_commit_link rcl USING (session_hash)" + " JOIN refresh_transfer_public_key rcl USING (session_hash)" " WHERE rs.old_coin_pub=$1" " AND rcl.cnc_index=rs.noreveal_index", 1, NULL); @@ -3078,7 +3071,6 @@ postgres_insert_refresh_commit_coins (void *cls, GNUNET_PQ_query_param_auto_from_type (session_hash), GNUNET_PQ_query_param_uint16 (&cnc_index), GNUNET_PQ_query_param_uint16 (&coin_off), - GNUNET_PQ_query_param_auto_from_type (&commit_coins[i].refresh_link), GNUNET_PQ_query_param_fixed_size (commit_coins[i].coin_ev, commit_coins[i].coin_ev_size), GNUNET_PQ_query_param_end @@ -3184,8 +3176,6 @@ postgres_get_refresh_commit_coins (void *cls, } { struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("link_vector_enc", - &commit_coins[i].refresh_link), GNUNET_PQ_result_spec_variable_size ("coin_ev", &c_buf, &c_buf_size), @@ -3216,28 +3206,27 @@ postgres_get_refresh_commit_coins (void *cls, * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension) - * @param[out] link link information to store return + * @param tp transfer public key to store * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success */ static int -postgres_insert_refresh_commit_link (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t cnc_index, - const struct TALER_RefreshCommitLinkP *link) +postgres_insert_refresh_transfer_public_key (void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct GNUNET_HashCode *session_hash, + uint16_t cnc_index, + const struct TALER_TransferPublicKeyP *tp) { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (session_hash), - GNUNET_PQ_query_param_auto_from_type (&link->transfer_pub), + GNUNET_PQ_query_param_auto_from_type (tp), GNUNET_PQ_query_param_uint16 (&cnc_index), - GNUNET_PQ_query_param_auto_from_type (&link->shared_secret_enc), GNUNET_PQ_query_param_end }; PGresult *result; result = GNUNET_PQ_exec_prepared (session->conn, - "insert_refresh_commit_link", + "insert_transfer_public_key", params); if (PGRES_COMMAND_OK != PQresultStatus (result)) { @@ -3264,17 +3253,17 @@ postgres_insert_refresh_commit_link (void *cls, * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension) - * @param[out] link information to return + * @param[out] tp information to return * @return #GNUNET_SYSERR on internal error, * #GNUNET_NO if commitment was not found * #GNUNET_OK on success */ static int -postgres_get_refresh_commit_link (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t cnc_index, - struct TALER_RefreshCommitLinkP *link) +postgres_get_refresh_transfer_public_key (void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct GNUNET_HashCode *session_hash, + uint16_t cnc_index, + struct TALER_TransferPublicKeyP *tp) { struct GNUNET_PQ_QueryParam params[] = { GNUNET_PQ_query_param_auto_from_type (session_hash), @@ -3284,7 +3273,7 @@ postgres_get_refresh_commit_link (void *cls, PGresult *result; result = GNUNET_PQ_exec_prepared (session->conn, - "get_refresh_commit_link", + "get_refresh_transfer_public_key", params); if (PGRES_TUPLES_OK != PQresultStatus (result)) { @@ -3300,9 +3289,7 @@ postgres_get_refresh_commit_link (void *cls, { struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("transfer_pub", - &link->transfer_pub), - GNUNET_PQ_result_spec_auto_from_type ("link_secret_enc", - &link->shared_secret_enc), + tp), GNUNET_PQ_result_spec_end }; @@ -3376,11 +3363,11 @@ postgres_get_melt_commitment (void *cls, goto cleanup; } if (GNUNET_OK != - postgres_get_refresh_commit_link (cls, - session, - session_hash, - cnc_index, - &mc->commit_links[cnc_index])) + postgres_get_refresh_transfer_public_key (cls, + session, + session_hash, + cnc_index, + &mc->transfer_pubs[cnc_index])) { GNUNET_break (0); goto cleanup; @@ -3486,8 +3473,6 @@ postgres_get_link_data_list (void *cls, pos = GNUNET_new (struct TALER_EXCHANGEDB_LinkDataList); { struct GNUNET_PQ_ResultSpec rs[] = { - GNUNET_PQ_result_spec_auto_from_type ("link_vector_enc", - &pos->link_data_enc), GNUNET_PQ_result_spec_rsa_signature ("ev_sig", &sig), GNUNET_PQ_result_spec_rsa_public_key ("denom_pub", @@ -3567,10 +3552,8 @@ postgres_get_transfer (void *cls, { struct GNUNET_HashCode session_hash; struct TALER_TransferPublicKeyP transfer_pub; - struct TALER_EncryptedLinkSecretP shared_secret_enc; struct GNUNET_PQ_ResultSpec rs[] = { GNUNET_PQ_result_spec_auto_from_type ("transfer_pub", &transfer_pub), - GNUNET_PQ_result_spec_auto_from_type ("link_secret_enc", &shared_secret_enc), GNUNET_PQ_result_spec_auto_from_type ("session_hash", &session_hash), GNUNET_PQ_result_spec_end }; @@ -3584,8 +3567,7 @@ postgres_get_transfer (void *cls, } tdc (tdc_cls, &session_hash, - &transfer_pub, - &shared_secret_enc); + &transfer_pub); } PQclear (result); return GNUNET_OK; @@ -4424,8 +4406,8 @@ libtaler_plugin_exchangedb_postgres_init (void *cls) plugin->insert_refresh_commit_coins = &postgres_insert_refresh_commit_coins; plugin->get_refresh_commit_coins = &postgres_get_refresh_commit_coins; plugin->free_refresh_commit_coins = &postgres_free_refresh_commit_coins; - plugin->insert_refresh_commit_link = &postgres_insert_refresh_commit_link; - plugin->get_refresh_commit_link = &postgres_get_refresh_commit_link; + plugin->insert_refresh_transfer_public_key = &postgres_insert_refresh_transfer_public_key; + plugin->get_refresh_transfer_public_key = &postgres_get_refresh_transfer_public_key; plugin->get_melt_commitment = &postgres_get_melt_commitment; plugin->free_melt_commitment = &common_free_melt_commitment; plugin->insert_refresh_out = &postgres_insert_refresh_out; diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index e1fdeb2bc..e8e8f3a03 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -412,7 +412,7 @@ GNUNET_NETWORK_STRUCT_BEGIN struct TALER_TransferSecretP { /** - * Secret used to encrypt/decrypt the `struct TALER_LinkSecretP`. + * Secret used to derive private inputs for refreshed coins. * Must be (currently) a hash as this is what * #GNUNET_CRYPTO_ecc_ecdh() returns to us. */ @@ -421,49 +421,6 @@ struct TALER_TransferSecretP /** - * @brief Secret used to decrypt refresh links. - */ -struct TALER_LinkSecretP -{ - /** - * Secret used to decrypt the refresh link data. - */ - char key[sizeof (struct GNUNET_HashCode)]; -}; - - -/** - * @brief Encrypted secret used to decrypt refresh links. - */ -struct TALER_EncryptedLinkSecretP -{ - /** - * Encrypted secret, must be the given size! - */ - char enc[sizeof (struct TALER_LinkSecretP)]; -}; - - -/** - * @brief Representation of an refresh link in cleartext. - */ -struct TALER_RefreshLinkDecryptedP -{ - - /** - * Private key of the coin. - */ - struct TALER_CoinSpendPrivateKeyP coin_priv; - - /** - * Blinding key. - */ - struct TALER_DenominationBlindingKeyP blinding_key; - -}; - - -/** * Length of the raw value in the Taler wire transfer identifier * (in binary representation). */ @@ -540,44 +497,6 @@ struct TALER_RefreshLinkEncryptedP GNUNET_NETWORK_STRUCT_END - - -/** - * Decrypt the shared @a secret from the information in the - * encrypted link secret @e secret_enc using the transfer - * private key and the coin's public key. - * - * @param secret_enc encrypted link secret - * @param trans_priv transfer private key - * @param coin_pub coin public key - * @param[out] secret set to the shared secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_link_decrypt_secret (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferPrivateKeyP *trans_priv, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_LinkSecretP *secret); - - -/** - * Decrypt the shared @a secret from the information in the - * encrypted link secret @e secret_enc using the transfer - * public key and the coin's private key. - * - * @param secret_enc encrypted link secret - * @param trans_pub transfer public key - * @param coin_priv coin private key - * @param[out] secret set to the shared secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error - */ -int -TALER_link_decrypt_secret2 (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferPublicKeyP *trans_pub, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - struct TALER_LinkSecretP *secret); - - /** * Given the coin and the transfer private keys, compute the * transfer secret. (Technically, we only need one of the two @@ -596,78 +515,68 @@ TALER_link_derive_transfer_secret (const struct TALER_CoinSpendPrivateKeyP *coin /** - * Encrypt the shared @a secret to generate the encrypted link secret. - * Also creates the transfer key. + * Decrypt the shared @a secret from the information in the + * @a trans_priv and @a coin_pub. * - * @param secret link secret to encrypt + * @param trans_priv transfer private key * @param coin_pub coin public key - * @param[out] trans_priv set to transfer private key - * @param[out] trans_pub set to transfer public key - * @param[out] secret_enc set to the encryptd @a secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + * @param[out] secret set to the shared secret */ -int -TALER_link_encrypt_secret (const struct TALER_LinkSecretP *secret, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_TransferPrivateKeyP *trans_priv, - struct TALER_TransferPublicKeyP *trans_pub, - struct TALER_EncryptedLinkSecretP *secret_enc); +void +TALER_link_reveal_transfer_secret (const struct TALER_TransferPrivateKeyP *trans_priv, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_TransferSecretP *transfer_secret); + /** - * Use the @a trans_sec (from ECDHE) to decrypt the @a secret_enc - * to obtain the @a secret to decrypt the linkage data. + * Decrypt the shared @a secret from the information in the + * @a trans_priv and @a coin_pub. * - * @param secret_enc encrypted secret - * @param trans_sec transfer secret - * @param secret shared secret for refresh link decryption - * @return #GNUNET_OK on success + * @param trans_pub transfer private key + * @param coin_priv coin public key + * @param[out] secret set to the shared secret */ -int -TALER_transfer_decrypt (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferSecretP *trans_sec, - struct TALER_LinkSecretP *secret); +void +TALER_link_recover_transfer_secret (const struct TALER_TransferPublicKeyP *trans_pub, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_TransferSecretP *transfer_secret); /** - * Use the @a trans_sec (from ECDHE) to encrypt the @a secret - * to obtain the @a secret_enc. - * - * @param secret shared secret for refresh link decryption - * @param trans_sec transfer secret - * @param[out] secret_enc encrypted secret - * @return #GNUNET_OK on success + * Header for serializations of coin-specific information about the + * fresh coins we generate during a melt. */ -int -TALER_transfer_encrypt (const struct TALER_LinkSecretP *secret, - const struct TALER_TransferSecretP *trans_sec, - struct TALER_EncryptedLinkSecretP *secret_enc); +struct TALER_FreshCoinP +{ + /** + * Private key of the coin. + */ + struct TALER_CoinSpendPrivateKeyP coin_priv; -/** - * Decrypt refresh link information. - * - * @param input encrypted refresh link data - * @param secret shared secret to use for decryption - * @param[out] output where to write decrypted refresh link - */ -void -TALER_refresh_decrypt (const struct TALER_RefreshLinkEncryptedP *input, - const struct TALER_LinkSecretP *secret, - struct TALER_RefreshLinkDecryptedP *output); + /** + * The blinding key. + */ + struct TALER_DenominationBlindingKeyP blinding_key; + +}; /** - * Encrypt refresh link information. + * Setup information for a fresh coin, deriving the coin private key + * and the blinding factor from the @a secret_seed with a KDF salted + * by the @a coin_num_salt. * - * @param input plaintext refresh link data - * @param secret shared secret to use for encryption - * @param[out] output where to write encrypted refresh link + * @param secret_seed seed to use for KDF to derive coin keys + * @param coin_num_salt number of the coin to include in KDF + * @param[out] fc value to initialize */ void -TALER_refresh_encrypt (const struct TALER_RefreshLinkDecryptedP *input, - const struct TALER_LinkSecretP *secret, - struct TALER_RefreshLinkEncryptedP *output); +TALER_setup_fresh_coin (const struct TALER_TransferSecretP *secret_seed, + unsigned int coin_num_salt, + struct TALER_FreshCoinP *fc); + #endif diff --git a/src/include/taler_exchangedb_plugin.h b/src/include/taler_exchangedb_plugin.h index ddc7f7714..0377806f4 100644 --- a/src/include/taler_exchangedb_plugin.h +++ b/src/include/taler_exchangedb_plugin.h @@ -445,12 +445,6 @@ struct TALER_EXCHANGEDB_RefreshCommitCoin { /** - * Encrypted data allowing those able to decrypt it to derive - * the private keys of the new coins created by the refresh. - */ - struct TALER_RefreshLinkEncryptedP refresh_link; - - /** * Blinded message to be signed (in envelope), with @e coin_env_size bytes. */ char *coin_ev; @@ -474,12 +468,6 @@ struct TALER_EXCHANGEDB_LinkDataList struct TALER_EXCHANGEDB_LinkDataList *next; /** - * Link data, used to recover the private key of the coin - * by the owner of the old coin. - */ - struct TALER_RefreshLinkEncryptedP link_data_enc; - - /** * Denomination public key, determines the value of the coin. */ struct TALER_DenominationPublicKey denom_pub; @@ -579,9 +567,9 @@ struct TALER_EXCHANGEDB_MeltCommitment struct TALER_EXCHANGEDB_RefreshCommitCoin *commit_coins[TALER_CNC_KAPPA]; /** - * Array of #TALER_CNC_KAPPA links. + * Array of #TALER_CNC_KAPPA transfer public keys. */ - struct TALER_RefreshCommitLinkP commit_links[TALER_CNC_KAPPA]; + struct TALER_TransferPublicKeyP transfer_pubs[TALER_CNC_KAPPA]; }; @@ -635,8 +623,7 @@ typedef int typedef void (*TALER_EXCHANGEDB_TransferDataCallback)(void *cls, const struct GNUNET_HashCode *session_hash, - const struct TALER_TransferPublicKeyP *transfer_pub, - const struct TALER_EncryptedLinkSecretP *shared_secret_enc); + const struct TALER_TransferPublicKeyP *transfer_pub); /** @@ -1217,15 +1204,15 @@ struct TALER_EXCHANGEDB_Plugin * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index, relating to #TALER_CNC_KAPPA - * @param link link information to store + * @param tp public key to store * @return #GNUNET_SYSERR on internal error, #GNUNET_OK on success */ int - (*insert_refresh_commit_link) (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t cnc_index, - const struct TALER_RefreshCommitLinkP *link); + (*insert_refresh_transfer_public_key) (void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct GNUNET_HashCode *session_hash, + uint16_t cnc_index, + const struct TALER_TransferPublicKeyP *tp); /** * Obtain the commited (encrypted) refresh link data @@ -1235,17 +1222,17 @@ struct TALER_EXCHANGEDB_Plugin * @param session database connection to use * @param session_hash hash to identify refresh session * @param cnc_index cut and choose index (1st dimension) - * @param[out] link information to return + * @param[out] tp information to return * @return #GNUNET_SYSERR on internal error, * #GNUNET_NO if commitment was not found * #GNUNET_OK on success */ int - (*get_refresh_commit_link) (void *cls, - struct TALER_EXCHANGEDB_Session *session, - const struct GNUNET_HashCode *session_hash, - uint16_t cnc_index, - struct TALER_RefreshCommitLinkP *link); + (*get_refresh_transfer_public_key) (void *cls, + struct TALER_EXCHANGEDB_Session *session, + const struct GNUNET_HashCode *session_hash, + uint16_t cnc_index, + struct TALER_TransferPublicKeyP *tp); /** diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h index 098799538..a4d599cd7 100644 --- a/src/include/taler_signatures.h +++ b/src/include/taler_signatures.h @@ -878,31 +878,6 @@ struct TALER_ExchangeKeyValidityPS /** - * @brief For each (old) coin being melted, we have a `struct - * RefreshCommitLinkP` that allows the user to find the shared secret - * to decrypt the respective refresh links for the new coins in the - * `struct TALER_EXCHANGEDB_RefreshCommitCoin`. - * - * Part of the construction of the refresh session's hash and - * thus of what is signed there. - */ -struct TALER_RefreshCommitLinkP -{ - /** - * Transfer public key, used to decrypt the @e shared_secret_enc - * in combintation with the corresponding private key of the - * coin. - */ - struct TALER_TransferPublicKeyP transfer_pub; - - /** - * Encrypted shared secret to decrypt the link. - */ - struct TALER_EncryptedLinkSecretP shared_secret_enc; -}; - - -/** * @brief Information signed by the exchange's master * key affirming the SEPA details for the exchange. */ diff --git a/src/util/crypto.c b/src/util/crypto.c index 3200e2a05..771744c7e 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -73,92 +73,32 @@ TALER_gcrypt_init () /** - * Derive symmetric key material for refresh operations from - * a given shared secret for link decryption. - * - * @param secret the shared secret - * @param[out] iv set to initialization vector - * @param[out] skey set to session key - */ -static void -derive_refresh_key (const struct TALER_LinkSecretP *secret, - struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - struct GNUNET_CRYPTO_SymmetricSessionKey *skey) -{ - static const char ctx_key[] = "taler-link-skey"; - static const char ctx_iv[] = "taler-link-iv"; - - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), - ctx_key, strlen (ctx_key), - secret, sizeof (struct TALER_LinkSecretP), - NULL, 0)); - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), - ctx_iv, strlen (ctx_iv), - secret, sizeof (struct TALER_LinkSecretP), - NULL, 0)); -} - - -/** - * Derive symmetric key material for refresh operations from - * a given shared secret for key decryption. - * - * @param secret the shared secret - * @param[out] iv set to initialization vector - * @param[out] skey set to session key - */ -static void -derive_transfer_key (const struct TALER_TransferSecretP *secret, - struct GNUNET_CRYPTO_SymmetricInitializationVector *iv, - struct GNUNET_CRYPTO_SymmetricSessionKey *skey) -{ - static const char ctx_key[] = "taler-transfer-skey"; - static const char ctx_iv[] = "taler-transfer-iv"; - - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), - ctx_key, strlen (ctx_key), - secret, sizeof (struct TALER_TransferSecretP), - NULL, 0)); - GNUNET_assert (GNUNET_YES == - GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), - ctx_iv, strlen (ctx_iv), - secret, sizeof (struct TALER_TransferSecretP), - NULL, 0)); -} - - -/** - * Use the @a trans_sec (from ECDHE) to decrypt the @a secret_enc - * to obtain the @a secret to decrypt the linkage data. + * Check if a coin is valid; that is, whether the denomination key exists, + * is not expired, and the signature is correct. * - * @param secret_enc encrypted secret - * @param trans_sec transfer secret - * @param secret shared secret for refresh link decryption - * @return #GNUNET_OK on success + * @param coin_public_info the coin public info to check for validity + * @return #GNUNET_YES if the coin is valid, + * #GNUNET_NO if it is invalid + * #GNUNET_SYSERROR if an internal error occured */ int -TALER_transfer_decrypt (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferSecretP *trans_sec, - struct TALER_LinkSecretP *secret) +TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) { - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - ssize_t s; + struct GNUNET_HashCode c_hash; - GNUNET_assert (sizeof (struct TALER_EncryptedLinkSecretP) == - sizeof (struct TALER_LinkSecretP)); - derive_transfer_key (trans_sec, &iv, &skey); - s = GNUNET_CRYPTO_symmetric_decrypt (secret_enc, - sizeof (struct TALER_LinkSecretP), - &skey, - &iv, - secret); - if (sizeof (struct TALER_LinkSecretP) != s) - return GNUNET_SYSERR; - return GNUNET_OK; + 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)) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "coin signature is invalid\n"); + return GNUNET_NO; + } + return GNUNET_YES; } @@ -191,244 +131,73 @@ TALER_link_derive_transfer_secret (const struct TALER_CoinSpendPrivateKeyP *coin /** - * Use the @a trans_sec (from ECDHE) to encrypt the @a secret - * to obtain the @a secret_enc. - * - * @param secret shared secret for refresh link decryption - * @param trans_sec transfer secret - * @param[out] secret_enc encrypted secret - * @return #GNUNET_OK on success - */ -int -TALER_transfer_encrypt (const struct TALER_LinkSecretP *secret, - const struct TALER_TransferSecretP *trans_sec, - struct TALER_EncryptedLinkSecretP *secret_enc) -{ - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - ssize_t s; - - GNUNET_assert (sizeof (struct TALER_EncryptedLinkSecretP) == - sizeof (struct TALER_LinkSecretP)); - derive_transfer_key (trans_sec, &iv, &skey); - s = GNUNET_CRYPTO_symmetric_encrypt (secret, - sizeof (struct TALER_LinkSecretP), - &skey, - &iv, - secret_enc); - if (sizeof (struct TALER_LinkSecretP) != s) - return GNUNET_SYSERR; - return GNUNET_OK; -} - - -/** - * Decrypt refresh link information. - * - * @param input encrypted refresh link data - * @param secret shared secret to use for decryption - * @param[out] output where to write decrypted data - */ -void -TALER_refresh_decrypt (const struct TALER_RefreshLinkEncryptedP *input, - const struct TALER_LinkSecretP *secret, - struct TALER_RefreshLinkDecryptedP *output) -{ - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - - derive_refresh_key (secret, &iv, &skey); - GNUNET_assert (sizeof (struct TALER_RefreshLinkEncryptedP) == - sizeof (struct TALER_RefreshLinkDecryptedP)); - GNUNET_assert (sizeof (struct TALER_RefreshLinkEncryptedP) == - GNUNET_CRYPTO_symmetric_decrypt (input, - sizeof (struct TALER_RefreshLinkEncryptedP), - &skey, - &iv, - output)); -} - - -/** - * Encrypt refresh link information. - * - * @param input plaintext refresh link data - * @param secret shared secret to use for encryption - * @param[out] output where to write encrypted link data - */ -void -TALER_refresh_encrypt (const struct TALER_RefreshLinkDecryptedP *input, - const struct TALER_LinkSecretP *secret, - struct TALER_RefreshLinkEncryptedP *output) -{ - struct GNUNET_CRYPTO_SymmetricInitializationVector iv; - struct GNUNET_CRYPTO_SymmetricSessionKey skey; - - derive_refresh_key (secret, &iv, &skey); - GNUNET_assert (sizeof (struct TALER_RefreshLinkEncryptedP) == - sizeof (struct TALER_RefreshLinkDecryptedP)); - GNUNET_assert (sizeof (struct TALER_RefreshLinkEncryptedP) == - GNUNET_CRYPTO_symmetric_encrypt (input, - sizeof (struct TALER_RefreshLinkDecryptedP), - &skey, - &iv, - output)); -} - - -/** - * Check if a coin is valid; that is, whether the denomination key exists, - * is not expired, and the signature is correct. - * - * @param coin_public_info the coin public info to check for validity - * @return #GNUNET_YES if the coin is valid, - * #GNUNET_NO if it is invalid - * #GNUNET_SYSERROR if an internal error occured - */ -int -TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info) -{ - struct GNUNET_HashCode c_hash; - - 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)) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "coin signature is invalid\n"); - return GNUNET_NO; - } - return GNUNET_YES; -} - - -/** * Decrypt the shared @a secret from the information in the - * encrypted link secret @e secret_enc using the transfer - * private key and the coin's public key. + * @a trans_priv and @a coin_pub. * - * @param secret_enc encrypted link secret * @param trans_priv transfer private key * @param coin_pub coin public key * @param[out] secret set to the shared secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ -int -TALER_link_decrypt_secret (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferPrivateKeyP *trans_priv, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_LinkSecretP *secret) +void +TALER_link_reveal_transfer_secret (const struct TALER_TransferPrivateKeyP *trans_priv, + const struct TALER_CoinSpendPublicKeyP *coin_pub, + struct TALER_TransferSecretP *transfer_secret) { - struct TALER_TransferSecretP transfer_secret; - - if (GNUNET_OK != - GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv, - &coin_pub->eddsa_pub, - &transfer_secret.key)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_transfer_decrypt (secret_enc, - &transfer_secret, - secret)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv, + &coin_pub->eddsa_pub, + &transfer_secret->key)); } /** * Decrypt the shared @a secret from the information in the - * encrypted link secret @e secret_enc using the transfer - * public key and the coin's private key. + * @a trans_priv and @a coin_pub. * - * @param secret_enc encrypted link secret - * @param trans_pub transfer public key - * @param coin_priv coin private key + * @param trans_pub transfer private key + * @param coin_priv coin public key * @param[out] secret set to the shared secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error */ -int -TALER_link_decrypt_secret2 (const struct TALER_EncryptedLinkSecretP *secret_enc, - const struct TALER_TransferPublicKeyP *trans_pub, - const struct TALER_CoinSpendPrivateKeyP *coin_priv, - struct TALER_LinkSecretP *secret) +void +TALER_link_recover_transfer_secret (const struct TALER_TransferPublicKeyP *trans_pub, + const struct TALER_CoinSpendPrivateKeyP *coin_priv, + struct TALER_TransferSecretP *transfer_secret) { - struct TALER_TransferSecretP transfer_secret; - - if (GNUNET_OK != - GNUNET_CRYPTO_eddsa_ecdh (&coin_priv->eddsa_priv, - &trans_pub->ecdhe_pub, - &transfer_secret.key)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_transfer_decrypt (secret_enc, - &transfer_secret, - secret)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - return GNUNET_OK; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_eddsa_ecdh (&coin_priv->eddsa_priv, + &trans_pub->ecdhe_pub, + &transfer_secret->key)); } /** - * Encrypt the shared @a secret to generate the encrypted link secret. - * Also creates the transfer key. + * Setup information for a fresh coin. * - * @param secret link secret to encrypt - * @param coin_pub coin public key - * @param[out] trans_priv set to transfer private key - * @param[out] trans_pub set to transfer public key - * @param[out] secret_enc set to the encryptd @a secret - * @return #GNUNET_OK on success, #GNUNET_SYSERR on error + * @param secret_seed seed to use for KDF to derive coin keys + * @param coin_num_salt number of the coin to include in KDF + * @param[out] fc value to initialize */ -int -TALER_link_encrypt_secret (const struct TALER_LinkSecretP *secret, - const struct TALER_CoinSpendPublicKeyP *coin_pub, - struct TALER_TransferPrivateKeyP *trans_priv, - struct TALER_TransferPublicKeyP *trans_pub, - struct TALER_EncryptedLinkSecretP *secret_enc) +void +TALER_setup_fresh_coin (const struct TALER_TransferSecretP *secret_seed, + unsigned int coin_num_salt, + struct TALER_FreshCoinP *fc) { - struct TALER_TransferSecretP transfer_secret; - struct GNUNET_CRYPTO_EcdhePrivateKey *pk; + uint32_t be_salt = htonl (coin_num_salt); - pk = GNUNET_CRYPTO_ecdhe_key_create (); - if (GNUNET_OK != - GNUNET_CRYPTO_ecdh_eddsa (pk, - &coin_pub->eddsa_pub, - &transfer_secret.key)) - { - GNUNET_break (0); - GNUNET_free (pk); - return GNUNET_SYSERR; - } - if (GNUNET_OK != - TALER_transfer_encrypt (secret, - &transfer_secret, - secret_enc)) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - trans_priv->ecdhe_priv = *pk; - GNUNET_CRYPTO_ecdhe_key_get_public (pk, - &trans_pub->ecdhe_pub); - GNUNET_free (pk); - return GNUNET_OK; + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_kdf (fc, + sizeof (*fc), + secret_seed, + sizeof (*secret_seed), + &be_salt, + sizeof (be_salt), + "taler-coin-derivation", + strlen ("taler-coin-derivation"), + NULL, 0)); + /* FIXME: twiddle the bits of the private key */ } + + /* end of crypto.c */ diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c index f442cefbd..f28ae8003 100644 --- a/src/util/test_crypto.c +++ b/src/util/test_crypto.c @@ -25,58 +25,6 @@ /** - * Test low-level link encryption/decryption APIs. - * - * @return 0 on success - */ -static int -test_basics () -{ - struct TALER_EncryptedLinkSecretP secret_enc; - struct TALER_TransferSecretP trans_sec; - struct TALER_LinkSecretP secret; - struct TALER_LinkSecretP secret2; - struct TALER_RefreshLinkEncryptedP rl_enc; - struct TALER_RefreshLinkDecryptedP rl; - struct TALER_RefreshLinkDecryptedP rld; - - GNUNET_log_setup ("test-crypto", - "WARNING", - NULL); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &secret, - sizeof (secret)); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &rl, - sizeof (rl)); - TALER_refresh_encrypt (&rl, - &secret, - &rl_enc); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &trans_sec, - sizeof (trans_sec)); - GNUNET_assert (GNUNET_OK == - TALER_transfer_encrypt (&secret, - &trans_sec, - &secret_enc)); - GNUNET_assert (GNUNET_OK == - TALER_transfer_decrypt (&secret_enc, - &trans_sec, - &secret2)); - GNUNET_assert (0 == memcmp (&secret, - &secret2, - sizeof (secret))); - TALER_refresh_decrypt (&rl_enc, - &secret2, - &rld); - GNUNET_assert (0 == memcmp (&rld, - &rl, - sizeof (struct TALER_RefreshLinkDecryptedP))); - return 0; -} - - -/** * Test high-level link encryption/decryption API. * * @return 0 on success @@ -85,46 +33,53 @@ static int test_high_level () { struct GNUNET_CRYPTO_EddsaPrivateKey *pk; - struct TALER_LinkSecretP secret; - struct TALER_LinkSecretP secret2; - struct TALER_CoinSpendPublicKeyP coin_pub; struct TALER_CoinSpendPrivateKeyP coin_priv; + struct TALER_CoinSpendPublicKeyP coin_pub; + struct GNUNET_CRYPTO_EcdhePrivateKey *pk2; struct TALER_TransferPrivateKeyP trans_priv; struct TALER_TransferPublicKeyP trans_pub; - struct TALER_EncryptedLinkSecretP secret_enc; + struct TALER_TransferSecretP secret; + struct TALER_TransferSecretP secret2; + struct TALER_FreshCoinP fc1; + struct TALER_FreshCoinP fc2; pk = GNUNET_CRYPTO_eddsa_key_create (); - GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, - &secret, - sizeof (secret)); - GNUNET_CRYPTO_eddsa_key_get_public (pk, + coin_priv.eddsa_priv = *pk; + GNUNET_free (pk); + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv.eddsa_priv, &coin_pub.eddsa_pub); - GNUNET_assert (GNUNET_OK == - TALER_link_encrypt_secret (&secret, - &coin_pub, - &trans_priv, - &trans_pub, - &secret_enc)); - GNUNET_assert (GNUNET_OK == - TALER_link_decrypt_secret (&secret_enc, - &trans_priv, - &coin_pub, - &secret2)); + pk2 = GNUNET_CRYPTO_ecdhe_key_create (); + trans_priv.ecdhe_priv = *pk2; + GNUNET_free (pk2); + GNUNET_CRYPTO_ecdhe_key_get_public (&trans_priv.ecdhe_priv, + &trans_pub.ecdhe_pub); + TALER_link_derive_transfer_secret (&coin_priv, + &trans_priv, + &secret); + TALER_link_reveal_transfer_secret (&trans_priv, + &coin_pub, + &secret2); GNUNET_assert (0 == memcmp (&secret, &secret2, sizeof (secret))); - coin_priv.eddsa_priv = *pk; - GNUNET_assert (GNUNET_OK == - TALER_link_decrypt_secret2 (&secret_enc, - &trans_pub, - &coin_priv, - &secret2)); + TALER_link_recover_transfer_secret (&trans_pub, + &coin_priv, + &secret2); GNUNET_assert (0 == memcmp (&secret, &secret2, sizeof (secret))); - GNUNET_free (pk); + TALER_setup_fresh_coin (&secret, + 0, + &fc1); + TALER_setup_fresh_coin (&secret, + 1, + &fc2); + GNUNET_assert (0 != + memcmp (&fc1, + &fc2, + sizeof (struct TALER_FreshCoinP))); return 0; } @@ -133,11 +88,9 @@ int main(int argc, const char *const argv[]) { - if (0 != test_basics ()) - return 1; if (0 != test_high_level ()) return 1; - return 0; + return 0; } /* end of test_crypto.c */ |