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