From 00d613728fdddf4f28e3c50cb2f70bfbba65e298 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sat, 8 Aug 2015 19:52:05 +0200 Subject: completing TALER_MINT_refresh_melt implementation --- src/include/taler_crypto_lib.h | 17 +++++ src/include/taler_mint_service.h | 2 +- src/mint-lib/mint_api_refresh.c | 158 ++++++++++++++++++++++++++++++++++++--- src/util/crypto.c | 28 +++++++ 4 files changed, 194 insertions(+), 11 deletions(-) diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h index 4126894a1..5f1425077 100644 --- a/src/include/taler_crypto_lib.h +++ b/src/include/taler_crypto_lib.h @@ -468,6 +468,23 @@ TALER_link_decrypt_secret2 (const struct TALER_EncryptedLinkSecretP *secret_enc, struct TALER_LinkSecretP *secret); +/** + * Given the coin and the transfer private keys, compute the + * transfer secret. (Technically, we only need one of the two + * private keys, but the caller currently trivially only has + * the two private keys, so we derive one of the public keys + * internally to this function.) + * + * @param coin_priv coin key + * @param trans_priv transfer private key + * @param[out] computed transfer secret + */ +void +TALER_link_derive_transfer_secret (const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_TransferPrivateKeyP *trans_priv, + struct TALER_TransferSecretP *ts); + + /** * Encrypt the shared @a secret to generate the encrypted link secret. * Also creates the transfer key. diff --git a/src/include/taler_mint_service.h b/src/include/taler_mint_service.h index b228acc5e..fa1f7a507 100644 --- a/src/include/taler_mint_service.h +++ b/src/include/taler_mint_service.h @@ -181,7 +181,7 @@ struct TALER_MINT_DenomPublicKey struct TALER_Amount fee_deposit; /** - *The applicable fee to refresh a coin of this denomination + *The applicable fee to melt/refresh a coin of this denomination */ struct TALER_Amount fee_refresh; }; diff --git a/src/mint-lib/mint_api_refresh.c b/src/mint-lib/mint_api_refresh.c index 566ab109b..0de367ce0 100644 --- a/src/mint-lib/mint_api_refresh.c +++ b/src/mint-lib/mint_api_refresh.c @@ -56,7 +56,7 @@ struct MeltedCoinP /** * The applicable fee for withdrawing a coin of this denomination */ - struct TALER_AmountNBO fee_withdraw; + struct TALER_AmountNBO fee_melt; /** * Transfer private keys for each cut-and-choose dimension. @@ -165,9 +165,9 @@ struct MeltedCoin struct TALER_Amount melt_amount_with_fee; /** - * The applicable fee for withdrawing a coin of this denomination + * The applicable fee for melting a coin of this denomination */ - struct TALER_Amount fee_withdraw; + struct TALER_Amount fee_melt; /** * Transfer private keys for each cut-and-choose dimension. @@ -382,8 +382,8 @@ serialize_melted_coin (const struct MeltedCoin *mc, TALER_amount_hton (&mcp.melt_amount_with_fee, &mc->melt_amount_with_fee); - TALER_amount_hton (&mcp.fee_withdraw, - &mc->fee_withdraw); + TALER_amount_hton (&mcp.fee_melt, + &mc->fee_melt); for (i=0;itransfer_priv[i]; mcp.deposit_valid_until = GNUNET_TIME_absolute_hton (mc->deposit_valid_until); @@ -462,8 +462,8 @@ deserialize_melted_coin (struct MeltedCoin *mc, mc->coin_priv = mcp.coin_priv; TALER_amount_ntoh (&mc->melt_amount_with_fee, &mcp.melt_amount_with_fee); - TALER_amount_ntoh (&mc->fee_withdraw, - &mcp.fee_withdraw); + TALER_amount_ntoh (&mc->fee_melt, + &mcp.fee_melt); for (i=0;itransfer_priv[i] = mcp.transfer_priv[i]; mc->deposit_valid_until = GNUNET_TIME_absolute_ntoh (mcp.deposit_valid_until); @@ -867,7 +867,7 @@ TALER_MINT_refresh_prepare (unsigned int num_melts, { md.melted_coins[i].coin_priv = melt_privs[i]; md.melted_coins[i].melt_amount_with_fee = melt_amounts[i]; - md.melted_coins[i].fee_withdraw = melt_pks[i].fee_withdraw; + md.melted_coins[i].fee_melt = melt_pks[i].fee_refresh; for (j=0;jmelt_amount_with_fee); + TALER_amount_hton (&melt.melt_fee, + &mc->fee_melt); + GNUNET_CRYPTO_eddsa_key_get_public (&mc->coin_priv.eddsa_priv, + &melt.coin_pub.eddsa_pub); + GNUNET_CRYPTO_eddsa_sign (&mc->coin_priv.eddsa_priv, + &melt.purpose, + &confirm_sig.eddsa_signature); + return json_pack ("{s:o, s:o, s:o, s:o, s:o}", + "coin_pub", + TALER_json_from_data (&melt.coin_pub, + sizeof (melt.coin_pub)), + "denom_pub", + TALER_json_from_rsa_public_key (mc->pub_key.rsa_public_key), + "denom_sig", 42, + TALER_json_from_rsa_signature (mc->sig.rsa_signature), + "confirm_sig", + TALER_json_from_data (&confirm_sig, + sizeof (confirm_sig)), + "value_with_fee", + TALER_json_from_amount (&mc->melt_amount_with_fee)); +} + + /** * Submit a melt request to the mint and get the mint's * response. @@ -1129,6 +1171,7 @@ TALER_MINT_refresh_melt (struct TALER_MINT_Handle *mint, json_t *transfer_pubs; json_t *secret_encs; json_t *link_encs; + json_t *tmp; struct TALER_MINT_RefreshMeltHandle *rmh; CURL *eh; struct TALER_MINT_Context *ctx; @@ -1150,7 +1193,7 @@ TALER_MINT_refresh_melt (struct TALER_MINT_Handle *mint, return NULL; } - /* FIXME: inomplete request building here: */ + /* build JSON request, each of the 6 arrays first */ new_denoms = json_array (); melt_coins = json_array (); coin_evs = json_array (); @@ -1159,16 +1202,111 @@ TALER_MINT_refresh_melt (struct TALER_MINT_Handle *mint, link_encs = json_array (); for (i=0;inum_melted_coins;i++) { + const struct MeltedCoin *mc = &md->melted_coins[i]; + + /* now melt_coins */ + json_array_append (melt_coins, + melted_coin_to_json (&md->melt_session_hash, + mc)); + + /* now transfer_pubs */ + tmp = json_array (); + for (j=0;jtransfer_priv[j].ecdhe_priv, + &transfer_pub.ecdhe_pub); + json_array_append (tmp, + TALER_json_from_data (&transfer_pub, + sizeof (transfer_pub))); + } + json_array_append (transfer_pubs, + tmp); + + /* now secret_encs */ + tmp = json_array (); for (j=0;jcoin_priv, + &mc->transfer_priv[j], + &trans_sec); + GNUNET_assert (GNUNET_OK == + TALER_transfer_encrypt (&md->link_secrets[j], + &trans_sec, + &els)); + json_array_append (tmp, + TALER_json_from_data (&els, + sizeof (els))); } + json_array_append (secret_encs, + tmp); } for (i=0;inum_fresh_coins;i++) { + /* now new_denoms */ + json_array_append (new_denoms, + TALER_json_from_rsa_public_key + (md->fresh_pks[i].rsa_public_key)); + + /* now link_encs */ + tmp = json_array (); for (j=0;jfresh_coins[j][i]; + struct TALER_RefreshLinkDecrypted rld; + struct TALER_RefreshLinkEncrypted *rle; + char *buf; + size_t buf_len; + + rld.coin_priv = fc->coin_priv; + rld.blinding_key = fc->blinding_key; + rle = TALER_refresh_encrypt (&rld, + &md->link_secrets[j]); + GNUNET_assert (NULL != rle); + buf = TALER_refresh_link_encrypted_encode (rle, + &buf_len); + GNUNET_assert (NULL != buf); + json_array_append (tmp, + TALER_json_from_data (buf, + buf_len)); + GNUNET_free (buf); + GNUNET_free (rle); } + json_array_append (link_encs, + tmp); + + /* now coin_evs */ + tmp = json_array (); + for (j=0;jfresh_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 */ + size_t coin_ev_size; + + GNUNET_CRYPTO_eddsa_key_get_public (&fc->coin_priv.eddsa_priv, + &coin_pub.eddsa_pub); + GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub, + sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), + &coin_hash); + coin_ev_size = GNUNET_CRYPTO_rsa_blind (&coin_hash, + fc->blinding_key.rsa_blinding_key, + md->fresh_pks[j].rsa_public_key, + &coin_ev); + json_array_append (tmp, + TALER_json_from_data (coin_ev, + coin_ev_size)); + GNUNET_free (coin_ev); + } + json_array_append (coin_evs, + tmp); } + /* finally, assemble main JSON request from constitutent arrays */ melt_obj = json_pack ("{s:o, s:o, s:o, s:o, s:o, s:o}", "new_denoms", new_denoms, "melt_coins", melt_coins, @@ -1177,7 +1315,7 @@ TALER_MINT_refresh_melt (struct TALER_MINT_Handle *mint, "secret_encs", secret_encs, "link_encs", link_encs); - + /* and now we can at last begin the actual request handling */ rmh = GNUNET_new (struct TALER_MINT_RefreshMeltHandle); rmh->mint = mint; rmh->melt_cb = melt_cb; diff --git a/src/util/crypto.c b/src/util/crypto.c index b803b960a..edc300878 100644 --- a/src/util/crypto.c +++ b/src/util/crypto.c @@ -162,6 +162,34 @@ TALER_transfer_decrypt (const struct TALER_EncryptedLinkSecretP *secret_enc, } +/** + * Given the coin and the transfer private keys, compute the + * transfer secret. (Technically, we only need one of the two + * private keys, but the caller currently trivially only has + * the two private keys, so we derive one of the public keys + * internally to this function.) + * + * @param coin_priv coin key + * @param trans_priv transfer private key + * @param[out] computed transfer secret + */ +void +TALER_link_derive_transfer_secret (const struct TALER_CoinSpendPrivateKeyP *coin_priv, + const struct TALER_TransferPrivateKeyP *trans_priv, + struct TALER_TransferSecretP *ts) +{ + struct TALER_CoinSpendPublicKeyP coin_pub; + + GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv, + &coin_pub.eddsa_pub); + GNUNET_assert (GNUNET_OK == + GNUNET_CRYPTO_ecdh_eddsa (&trans_priv->ecdhe_priv, + &coin_pub.eddsa_pub, + &ts->key)); + +} + + /** * Use the @a trans_sec (from ECDHE) to encrypt the @a secret * to obtain the @a secret_enc. -- cgit v1.2.3