aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2015-03-10 17:00:12 +0100
committerChristian Grothoff <christian@grothoff.org>2015-03-10 17:00:12 +0100
commit7e26ae385896a974d8a90234a155c32b383e70f7 (patch)
tree1bbcf3e317744c9fa024bba5a6e46c84520dc9e5
parente3b8f5117e8028f3183871ab0efb0c6f2ff959eb (diff)
downloadexchange-7e26ae385896a974d8a90234a155c32b383e70f7.tar.gz
exchange-7e26ae385896a974d8a90234a155c32b383e70f7.zip
clean up refresh logic and use of signatures
-rw-r--r--src/include/taler_signatures.h48
-rw-r--r--src/mint/taler-mint-httpd_refresh.c293
-rw-r--r--src/mint/taler-mint-httpd_responses.c7
3 files changed, 145 insertions, 203 deletions
diff --git a/src/include/taler_signatures.h b/src/include/taler_signatures.h
index 9e3068a78..b1b578236 100644
--- a/src/include/taler_signatures.h
+++ b/src/include/taler_signatures.h
@@ -65,7 +65,7 @@
65 * Signature where the refresh session confirms 65 * Signature where the refresh session confirms
66 * the commits. 66 * the commits.
67 */ 67 */
68#define TALER_SIGNATURE_REFRESH_MELT 6 68#define TALER_SIGNATURE_REFRESH_MELT_SESSION 6
69 69
70/** 70/**
71 * Signature where the mint (current signing key) 71 * Signature where the mint (current signing key)
@@ -221,7 +221,7 @@ struct TALER_DepositConfirmation
221 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub; 221 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
222 222
223 /** 223 /**
224 * The Merachant's public key. 224 * The Merchant's public key.
225 */ 225 */
226 struct GNUNET_CRYPTO_EddsaPublicKey merchant; 226 struct GNUNET_CRYPTO_EddsaPublicKey merchant;
227 227
@@ -232,7 +232,7 @@ struct TALER_DepositConfirmation
232 * Message signed by a coin to indicate that the coin should 232 * Message signed by a coin to indicate that the coin should
233 * be melted. 233 * be melted.
234 */ 234 */
235struct RefreshMeltSignatureBody 235struct RefreshMeltCoinSignature
236{ 236{
237 /** 237 /**
238 * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN. 238 * Purpose is #TALER_SIGNATURE_REFRESH_MELT_COIN.
@@ -245,42 +245,46 @@ struct RefreshMeltSignatureBody
245 struct GNUNET_HashCode melt_hash; 245 struct GNUNET_HashCode melt_hash;
246 246
247 /** 247 /**
248 * Signature of the client over the melt request (thereby
249 * indirectly including all of the information the client
250 * sent).
251 */
252 struct GNUNET_CRYPTO_EddsaSignature melt_client_signature;
253
254 /**
255 * Public key of the refresh session for which
256 * @e melt_client_signature must be a valid signature.
257 */
258 struct GNUNET_CRYPTO_EddsaPublicKey session_key;
259
260 /**
261 * How much of the value of the coin should be melted? 248 * How much of the value of the coin should be melted?
262 * This amount includes the fees, so the final amount contributed 249 * This amount includes the fees, so the final amount contributed
263 * to the melt is this value minus the fee for melting the coin. 250 * to the melt is this value minus the fee for melting the coin.
264 */ 251 */
265 struct TALER_AmountNBO amount; 252 struct TALER_AmountNBO amount;
253
254 /**
255 * The coin's public key.
256 */
257 struct GNUNET_CRYPTO_EcdsaPublicKey coin_pub;
266}; 258};
267 259
268 260
269/** 261/**
270 * Message signed during melting committing the client to the 262 * Message signed by a coin to indicate that the coin should
271 * hashed inputs. 263 * be melted.
272 */ 264 */
273struct RefreshCommitSignatureBody 265struct RefreshMeltSessionSignature
274{ 266{
275 /** 267 /**
276 * Purpose is #TALER_SIGNATURE_REFRESH_MELT. 268 * Purpose is #TALER_SIGNATURE_REFRESH_MELT_SESSION
277 */ 269 */
278 struct GNUNET_CRYPTO_EccSignaturePurpose purpose; 270 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
279 271
280 /** 272 /**
281 * Session state the client commits itself to. 273 * Which melting operation should the coin become a part of.
274 */
275 struct GNUNET_HashCode melt_hash;
276
277 /**
278 * Public key of the refresh session for which
279 * @e melt_client_signature must be a valid signature.
282 */ 280 */
283 struct GNUNET_HashCode commit_hash; 281 struct GNUNET_CRYPTO_EddsaPublicKey session_key;
282
283 /**
284 * What is the total value of the coins created during the
285 * refresh, excluding fees?
286 */
287 struct TALER_AmountNBO amount;
284}; 288};
285 289
286 290
diff --git a/src/mint/taler-mint-httpd_refresh.c b/src/mint/taler-mint-httpd_refresh.c
index 6c3cbbc71..d36e42085 100644
--- a/src/mint/taler-mint-httpd_refresh.c
+++ b/src/mint/taler-mint-httpd_refresh.c
@@ -36,109 +36,6 @@
36 36
37 37
38/** 38/**
39 * Verify a signature that is encoded in a JSON object. Extracts
40 * the signature and its associated purpose and checks that it
41 * matches the specified @a purpose and @a pub public key. Any
42 * errors are reported via appropriate response messages.
43 *
44 * @param connection the connection to send errors to
45 * @param json_sig the JSON object with the signature
46 * @param the public key that the signature was created with
47 * @param purpose the signed message
48 * @return #GNUNET_YES if the signature was valid
49 * #GNUNET_NO if the signature was invalid
50 * #GNUNET_SYSERR on internal error
51 */
52static int
53request_json_check_signature (struct MHD_Connection *connection,
54 const json_t *json_sig,
55 const struct GNUNET_CRYPTO_EddsaPublicKey *pub,
56 const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
57{
58 struct GNUNET_CRYPTO_EddsaSignature signature;
59 int size;
60 uint32_t purpose_num;
61 int res;
62 json_t *el;
63
64 /* TODO: use specification array to simplify the parsing! */
65 res = GNUNET_MINT_parse_navigate_json (connection,
66 json_sig,
67 JNAV_FIELD,
68 "sig",
69 JNAV_RET_DATA,
70 &signature,
71 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
72
73 if (GNUNET_OK != res)
74 return res;
75
76 res = GNUNET_MINT_parse_navigate_json (connection,
77 json_sig,
78 JNAV_FIELD,
79 "purpose",
80 JNAV_RET_TYPED_JSON,
81 JSON_INTEGER,
82 &el);
83
84 if (GNUNET_OK != res)
85 return res;
86
87 purpose_num = json_integer_value (el);
88
89 if (purpose_num != ntohl (purpose->purpose))
90 {
91 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
92 "signature invalid (purpose wrong)\n");
93 return TALER_MINT_reply_json_pack (connection,
94 MHD_HTTP_BAD_REQUEST,
95 "{s:s}",
96 "error", "signature invalid (purpose)");
97 }
98
99 res = GNUNET_MINT_parse_navigate_json (connection,
100 json_sig,
101 JNAV_FIELD, "size",
102 JNAV_RET_TYPED_JSON,
103 JSON_INTEGER,
104 &el);
105
106 if (GNUNET_OK != res)
107 return res;
108
109 size = json_integer_value (el);
110
111 if (size != ntohl (purpose->size))
112 {
113 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
114 "signature invalid (size wrong)\n");
115 return TALER_MINT_reply_json_pack (connection,
116 MHD_HTTP_BAD_REQUEST,
117 GNUNET_NO, GNUNET_SYSERR,
118 "{s:s}",
119 "error",
120 "signature invalid (size)");
121 }
122
123 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (purpose_num,
124 purpose,
125 &signature,
126 pub))
127 {
128 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
129 "signature invalid (did not verify)\n");
130 return TALER_MINT_reply_json_pack (connection,
131 MHD_HTTP_UNAUTHORIZED,
132 "{s:s}",
133 "error",
134 "invalid signature (verification)");
135 }
136
137 return GNUNET_OK;
138}
139
140
141/**
142 * Handle a "/refresh/melt" request after the main JSON parsing has happened. 39 * Handle a "/refresh/melt" request after the main JSON parsing has happened.
143 * We now need to validate the coins being melted and the session signature 40 * We now need to validate the coins being melted and the session signature
144 * and then hand things of to execute the melt operation. 41 * and then hand things of to execute the melt operation.
@@ -150,7 +47,7 @@ request_json_check_signature (struct MHD_Connection *connection,
150 * @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array 47 * @param coin_count number of coins to be melted, size of y-dimension of @commit_coin array
151 * @param coin_public_infos array with @a coin_count entries about the coins 48 * @param coin_public_infos array with @a coin_count entries about the coins
152 * @param coin_melt_details array with @a coin_count entries with melting details 49 * @param coin_melt_details array with @a coin_count entries with melting details
153 * @param melt_sig_json signature affirming the overall melt operation 50 * @param commit_hash hash over the data that the client commits to
154 * @param commit_client_sig signature of the client over this commitment 51 * @param commit_client_sig signature of the client over this commitment
155 * @param kappa size of x-dimension of @commit_coin and @commit_link arrays 52 * @param kappa size of x-dimension of @commit_coin and @commit_link arrays
156 * @param commit_coin 2d array of coin commitments (what the mint is to sign 53 * @param commit_coin 2d array of coin commitments (what the mint is to sign
@@ -168,18 +65,17 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
168 unsigned int coin_count, 65 unsigned int coin_count,
169 struct TALER_CoinPublicInfo *coin_public_infos, 66 struct TALER_CoinPublicInfo *coin_public_infos,
170 const struct MeltDetails *coin_melt_details, 67 const struct MeltDetails *coin_melt_details,
171 const json_t *melt_sig_json, 68 const struct GNUNET_HashCode *commit_hash,
172 const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig, 69 const struct GNUNET_CRYPTO_EddsaSignature *commit_client_sig,
173 unsigned int kappa, 70 unsigned int kappa,
174 struct RefreshCommitCoin *const* commit_coin, 71 struct RefreshCommitCoin *const* commit_coin,
175 struct RefreshCommitLink *const* commit_link) 72 struct RefreshCommitLink *const* commit_link)
176 73
177{ 74{
178 int res;
179 unsigned int i; 75 unsigned int i;
180 struct GNUNET_HashContext *hash_context; 76 struct GNUNET_HashContext *hash_context;
181 struct GNUNET_HashCode melt_hash; 77 struct GNUNET_HashCode melt_hash;
182 struct RefreshMeltSignatureBody body; 78 struct RefreshMeltSessionSignature body;
183 char *buf; 79 char *buf;
184 size_t buf_size; 80 size_t buf_size;
185 struct MintKeyState *key_state; 81 struct MintKeyState *key_state;
@@ -207,18 +103,26 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
207 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)); 103 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
208 GNUNET_CRYPTO_hash_context_finish (hash_context, 104 GNUNET_CRYPTO_hash_context_finish (hash_context,
209 &melt_hash); 105 &melt_hash);
106 // FIXME: what about the `commit_hash`?
210 107
211 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); 108 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_SESSION);
212 body.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); 109 body.purpose.size = htonl (sizeof (struct RefreshMeltSessionSignature));
213 body.melt_hash = melt_hash; 110 body.melt_hash = melt_hash;
214 body.amount = TALER_amount_hton (coin_melt_details->melt_amount); 111 body.amount = TALER_amount_hton (coin_melt_details->melt_amount);
215 112
216 if (GNUNET_OK != 113 if (GNUNET_OK != GNUNET_CRYPTO_eddsa_verify (TALER_SIGNATURE_REFRESH_MELT_SESSION,
217 (res = request_json_check_signature (connection, 114 &body.purpose,
218 melt_sig_json, 115 commit_client_sig,
219 refresh_session_pub, 116 refresh_session_pub))
220 &body.purpose))) 117 {
221 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; 118 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
119 "signature invalid (did not verify)\n");
120 return TALER_MINT_reply_json_pack (connection,
121 MHD_HTTP_UNAUTHORIZED,
122 "{s:s}",
123 "error",
124 "invalid signature (verification)");
125 }
222 126
223 // FIXME: badness, use proper way to set to zero... 127 // FIXME: badness, use proper way to set to zero...
224 key_state = TALER_MINT_key_state_acquire (); 128 key_state = TALER_MINT_key_state_acquire ();
@@ -276,15 +180,9 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
276 180
277 181
278/** 182/**
279 * Extract public coin information from a JSON object and verify 183 * Extract public coin information from a JSON object.
280 * that the signature shows that this coin is to be melted into
281 * the given @a session_pub melting session, and that this is
282 * a valid coin (we know the denomination key and the signature
283 * on it is valid). Essentially, this does all of the per-coin
284 * checks that can be done before the transaction starts.
285 * 184 *
286 * @param connection the connection to send error responses to 185 * @param connection the connection to send error responses to
287 * @param session_pub public key of the session the coin is melted into
288 * @param coin_info the JSON object to extract the coin info from 186 * @param coin_info the JSON object to extract the coin info from
289 * @param r_public_info[OUT] set to the coin's public information 187 * @param r_public_info[OUT] set to the coin's public information
290 * @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid) 188 * @param r_melt_detail[OUT] set to details about the coin's melting permission (if valid)
@@ -293,19 +191,15 @@ handle_refresh_melt_binary (struct MHD_Connection *connection,
293 * #GNUNET_SYSERR on internal error 191 * #GNUNET_SYSERR on internal error
294 */ 192 */
295static int 193static int
296get_and_verify_coin_public_info (struct MHD_Connection *connection, 194get_coin_public_info (struct MHD_Connection *connection,
297 const struct GNUNET_CRYPTO_EddsaPublicKey *session_pub, 195 json_t *coin_info,
298 json_t *coin_info, 196 struct TALER_CoinPublicInfo *r_public_info,
299 struct TALER_CoinPublicInfo *r_public_info, 197 struct MeltDetails *r_melt_detail)
300 struct MeltDetails *r_melt_detail)
301{ 198{
302 int ret; 199 int ret;
303 struct GNUNET_CRYPTO_EcdsaSignature melt_sig; 200 struct GNUNET_CRYPTO_EcdsaSignature melt_sig;
304 struct GNUNET_CRYPTO_rsa_Signature *sig; 201 struct GNUNET_CRYPTO_rsa_Signature *sig;
305 struct GNUNET_CRYPTO_rsa_PublicKey *pk; 202 struct GNUNET_CRYPTO_rsa_PublicKey *pk;
306 struct RefreshMeltConfirmSignRequestBody body;
307 struct MintKeyState *key_state;
308 struct TALER_MINT_DenomKeyIssuePriv *dki;
309 struct TALER_Amount amount; 203 struct TALER_Amount amount;
310 struct GNUNET_MINT_ParseFieldSpec spec[] = { 204 struct GNUNET_MINT_ParseFieldSpec spec[] = {
311 TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub), 205 TALER_MINT_PARSE_FIXED ("coin_pub", &r_public_info->coin_pub),
@@ -316,6 +210,7 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
316 TALER_MINT_PARSE_END 210 TALER_MINT_PARSE_END
317 }; 211 };
318 212
213 memset (&amount, 0, sizeof (amount)); // FIXME: #3636!
319 ret = TALER_MINT_parse_json_data (connection, 214 ret = TALER_MINT_parse_json_data (connection,
320 coin_info, 215 coin_info,
321 spec); 216 spec);
@@ -323,17 +218,68 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
323 return ret; 218 return ret;
324 /* FIXME: include amount of coin value to be melted here (#3636!) and 219 /* FIXME: include amount of coin value to be melted here (#3636!) and
325 in what we return!? */ 220 in what we return!? */
326 memset (&amount, 0, sizeof (amount)); // FIXME: #3636! 221
327 body.purpose.size = htonl (sizeof (struct RefreshMeltConfirmSignRequestBody)); 222 /* check mint signature on the coin */
328 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_CONFIRM); 223 r_public_info->denom_sig = sig;
329 body.session_pub = *session_pub; 224 r_public_info->denom_pub = pk;
330 if (GNUNET_OK != 225 if (GNUNET_OK !=
331 GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_CONFIRM, 226 TALER_test_coin_valid (r_public_info))
227 {
228 TALER_MINT_release_parsed_data (spec);
229 r_public_info->denom_sig = NULL;
230 r_public_info->denom_pub = NULL;
231 return (MHD_YES ==
232 TALER_MINT_reply_json_pack (connection,
233 MHD_HTTP_NOT_FOUND,
234 "{s:s}",
235 "error", "coin invalid"))
236 ? GNUNET_NO : GNUNET_SYSERR;
237 }
238 r_melt_detail->melt_sig = melt_sig;
239 r_melt_detail->melt_amount = amount;
240 TALER_MINT_release_parsed_data (spec);
241 return GNUNET_OK;
242}
243
244
245/**
246 * Verify that the signature shows that this coin is to be melted into
247 * the given @a session_pub melting session, and that this is a valid
248 * coin (we know the denomination key and the signature on it is
249 * valid). Essentially, this does all of the per-coin checks that can
250 * be done before the transaction starts.
251 *
252 * @param connection the connection to send error responses to
253 * @param melt_hash hash over refresh session the coin is melted into
254 * @param r_public_info the coin's public information
255 * @param r_melt_detail details about the coin's melting permission (if valid)
256 * @return #GNUNET_YES if coin public info in JSON was valid
257 * #GNUNET_NO JSON was invalid, response was generated
258 * #GNUNET_SYSERR on internal error
259 */
260static int
261verify_coin_public_info (struct MHD_Connection *connection,
262 const struct GNUNET_HashCode *melt_hash,
263 const struct TALER_CoinPublicInfo *r_public_info,
264 const struct MeltDetails *r_melt_detail)
265{
266 struct RefreshMeltCoinSignature body;
267 struct MintKeyState *key_state;
268 struct TALER_MINT_DenomKeyIssuePriv *dki;
269
270 /* FIXME: include amount of coin value to be melted here (#3636!) and
271 in what we return!? */
272 body.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature));
273 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN);
274 body.melt_hash = *melt_hash;
275 body.amount = TALER_amount_hton (r_melt_detail->melt_amount);
276 body.coin_pub = r_public_info->coin_pub;
277 if (GNUNET_OK !=
278 GNUNET_CRYPTO_ecdsa_verify (TALER_SIGNATURE_REFRESH_MELT_COIN,
332 &body.purpose, 279 &body.purpose,
333 &melt_sig, 280 &r_melt_detail->melt_sig,
334 &r_public_info->coin_pub)) 281 &r_public_info->coin_pub))
335 { 282 {
336 TALER_MINT_release_parsed_data (spec);
337 if (MHD_YES != 283 if (MHD_YES !=
338 TALER_MINT_reply_json_pack (connection, 284 TALER_MINT_reply_json_pack (connection,
339 MHD_HTTP_UNAUTHORIZED, 285 MHD_HTTP_UNAUTHORIZED,
@@ -344,7 +290,7 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
344 } 290 }
345 key_state = TALER_MINT_key_state_acquire (); 291 key_state = TALER_MINT_key_state_acquire ();
346 dki = TALER_MINT_get_denom_key (key_state, 292 dki = TALER_MINT_get_denom_key (key_state,
347 pk); 293 r_public_info->denom_pub);
348 /* FIXME: need to check if denomination key is still 294 /* FIXME: need to check if denomination key is still
349 valid for issuing! (#3634) */ 295 valid for issuing! (#3634) */
350 if (NULL == dki) 296 if (NULL == dki)
@@ -355,25 +301,6 @@ get_and_verify_coin_public_info (struct MHD_Connection *connection,
355 "denom_pub"); 301 "denom_pub");
356 } 302 }
357 TALER_MINT_key_state_release (key_state); 303 TALER_MINT_key_state_release (key_state);
358
359 /* check mint signature on the coin */
360 r_public_info->denom_sig = sig;
361 r_public_info->denom_pub = pk;
362 if (GNUNET_OK !=
363 TALER_test_coin_valid (r_public_info))
364 {
365 TALER_MINT_release_parsed_data (spec);
366 r_public_info->denom_sig = NULL;
367 r_public_info->denom_pub = NULL;
368 return (MHD_YES ==
369 TALER_MINT_reply_json_pack (connection,
370 MHD_HTTP_NOT_FOUND,
371 "{s:s}",
372 "error", "coin invalid"))
373 ? GNUNET_NO : GNUNET_SYSERR;
374 }
375 r_melt_detail->melt_sig = melt_sig;
376 r_melt_detail->melt_amount = amount;
377 return GNUNET_OK; 304 return GNUNET_OK;
378} 305}
379 306
@@ -478,9 +405,9 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
478 unsigned int coin_count; 405 unsigned int coin_count;
479 struct GNUNET_HashCode commit_hash; 406 struct GNUNET_HashCode commit_hash;
480 struct GNUNET_HashContext *hash_context; 407 struct GNUNET_HashContext *hash_context;
481 struct RefreshCommitSignatureBody body;
482 struct RefreshCommitCoin *commit_coin[kappa]; 408 struct RefreshCommitCoin *commit_coin[kappa];
483 struct RefreshCommitLink *commit_link[kappa]; 409 struct RefreshCommitLink *commit_link[kappa];
410 const struct GNUNET_CRYPTO_EddsaSignature commit_client_sig;
484 411
485 num_new_denoms = json_array_size (new_denoms); 412 num_new_denoms = json_array_size (new_denoms);
486 denom_pubs = GNUNET_malloc (num_new_denoms * 413 denom_pubs = GNUNET_malloc (num_new_denoms *
@@ -509,11 +436,10 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
509 for (i=0;i<coin_count;i++) 436 for (i=0;i<coin_count;i++)
510 { 437 {
511 /* decode JSON data on coin to melt */ 438 /* decode JSON data on coin to melt */
512 res = get_and_verify_coin_public_info (connection, 439 res = get_coin_public_info (connection,
513 refresh_session_pub, 440 json_array_get (melt_coins, i),
514 json_array_get (melt_coins, i), 441 &coin_public_infos[i],
515 &coin_public_infos[i], 442 &coin_melt_details[i]);
516 &coin_melt_details[i]);
517 if (GNUNET_OK != res) 443 if (GNUNET_OK != res)
518 { 444 {
519 for (j=0;j<i;j++) 445 for (j=0;j<i;j++)
@@ -635,24 +561,34 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
635 } 561 }
636 GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash); 562 GNUNET_CRYPTO_hash_context_finish (hash_context, &commit_hash);
637 563
638 /* verify commit signature */
639 body.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT);
640 body.purpose.size = htonl (sizeof (struct RefreshCommitSignatureBody));
641 body.commit_hash = commit_hash;
642 564
643 if (GNUNET_OK != 565 res = GNUNET_MINT_parse_navigate_json (connection,
644 (res = request_json_check_signature (connection, 566 commit_signature,
645 commit_signature, 567 JNAV_FIELD,
646 refresh_session_pub, 568 "sig",
647 &body.purpose))) 569 JNAV_RET_DATA,
570 &commit_client_sig,
571 sizeof (struct GNUNET_CRYPTO_EddsaSignature));
572
573 if (GNUNET_OK != res)
574 return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
575
576
577 for (i=0;i<coin_count;i++)
648 { 578 {
649 free_commit_coins (commit_coin, kappa, num_newcoins); 579 /* verify signatures ons coin to melt */
650 free_commit_links (commit_link, kappa, num_oldcoins); 580 res = verify_coin_public_info (connection,
651 return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; 581 &commit_hash,
582 &coin_public_infos[i],
583 &coin_melt_details[i]);
584 if (GNUNET_OK != res)
585 {
586 res = (GNUNET_NO == res) ? MHD_YES : MHD_NO;
587 goto cleanup;
588 }
652 } 589 }
653 590
654 /* execute commit */ 591 /* execute commit */
655 /* FIXME: we must also store the signature! (#3635) */
656 res = handle_refresh_melt_binary (connection, 592 res = handle_refresh_melt_binary (connection,
657 refresh_session_pub, 593 refresh_session_pub,
658 num_new_denoms, 594 num_new_denoms,
@@ -660,11 +596,12 @@ handle_refresh_melt_json (struct MHD_Connection *connection,
660 coin_count, 596 coin_count,
661 coin_public_infos, 597 coin_public_infos,
662 coin_melt_details, 598 coin_melt_details,
663 melt_sig_json, 599 &commit_hash,
664 NULL /* FIXME: 3635! */, 600 &commit_client_sig,
665 kappa, 601 kappa,
666 commit_coin, 602 commit_coin,
667 commit_link); 603 commit_link);
604 cleanup:
668 free_commit_coins (commit_coin, kappa, num_newcoins); 605 free_commit_coins (commit_coin, kappa, num_newcoins);
669 free_commit_links (commit_link, kappa, num_oldcoins); 606 free_commit_links (commit_link, kappa, num_oldcoins);
670 for (j=0;j<coin_count;j++) 607 for (j=0;j<coin_count;j++)
diff --git a/src/mint/taler-mint-httpd_responses.c b/src/mint/taler-mint-httpd_responses.c
index 83c81e800..2faeb5ca8 100644
--- a/src/mint/taler-mint-httpd_responses.c
+++ b/src/mint/taler-mint-httpd_responses.c
@@ -355,15 +355,16 @@ compile_transaction_history (const struct TALER_MINT_DB_TransactionList *tl)
355 } 355 }
356 case TALER_MINT_DB_TT_REFRESH_MELT: 356 case TALER_MINT_DB_TT_REFRESH_MELT:
357 { 357 {
358 struct RefreshMeltSignatureBody ms; 358 struct RefreshMeltCoinSignature ms;
359 const struct RefreshMelt *melt = pos->details.melt; 359 const struct RefreshMelt *melt = pos->details.melt;
360 360
361 type = "melt"; 361 type = "melt";
362 value = melt->amount; 362 value = melt->amount;
363 ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT); 363 ms.purpose.purpose = htonl (TALER_SIGNATURE_REFRESH_MELT_COIN);
364 ms.purpose.size = htonl (sizeof (struct RefreshMeltSignatureBody)); 364 ms.purpose.size = htonl (sizeof (struct RefreshMeltCoinSignature));
365 ms.melt_hash = melt->melt_hash; 365 ms.melt_hash = melt->melt_hash;
366 ms.amount = TALER_amount_hton (melt->amount); 366 ms.amount = TALER_amount_hton (melt->amount);
367 ms.coin_pub = melt->coin.coin_pub;
367 transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose, 368 transaction = TALER_JSON_from_ecdsa_sig (&ms.purpose,
368 &melt->coin_sig); 369 &melt->coin_sig);
369 } 370 }