aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--src/benchmark/taler-exchange-benchmark.c6
-rw-r--r--src/exchange-lib/exchange_api_payback.c14
-rw-r--r--src/exchange-lib/exchange_api_refresh.c119
-rw-r--r--src/exchange-lib/exchange_api_reserve.c82
-rw-r--r--src/exchange-lib/test_exchange_api.c46
-rw-r--r--src/include/taler_crypto_lib.h180
-rw-r--r--src/include/taler_exchange_service.h13
-rw-r--r--src/include/taler_util.h2
-rw-r--r--src/util/crypto.c137
-rw-r--r--src/util/test_crypto.c51
11 files changed, 416 insertions, 240 deletions
diff --git a/ChangeLog b/ChangeLog
index ab96d8aca..2f123098b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Tue Oct 31 13:43:55 CET 2017
+ Extended crypto API to provide planchet generation functions
+ explicitly (to be used on withdraw, refresh and tipping).
+ Renamed a few API calls to better reflect their functions.
+ Changed a few function signatures to use new structs. -CG
+
Wed Oct 18 15:20:29 CEST 2017
Releasing Taler v0.4.0. -CG
diff --git a/src/benchmark/taler-exchange-benchmark.c b/src/benchmark/taler-exchange-benchmark.c
index 93afb683b..a90773ba0 100644
--- a/src/benchmark/taler-exchange-benchmark.c
+++ b/src/benchmark/taler-exchange-benchmark.c
@@ -981,6 +981,7 @@ withdraw_coin (struct Coin *coin)
struct TALER_Amount left;
const struct TALER_EXCHANGE_Keys *keys;
struct Reserve *r;
+ struct TALER_PlanchetSecretsP ps;
keys = TALER_EXCHANGE_get_keys (exchange);
r = &reserves[coin->reserve_index];
@@ -996,12 +997,13 @@ withdraw_coin (struct Coin *coin)
GNUNET_assert (NULL != (coin->pk = find_pk (keys, &amount)));
if (warm >= WARM_THRESHOLD)
num_withdraw++;
+ ps.coin_priv = coin->coin_priv;
+ ps.blinding_key = blinding_key;
coin->wsh =
TALER_EXCHANGE_reserve_withdraw (exchange,
coin->pk,
&r->reserve_priv,
- &coin->coin_priv,
- &blinding_key,
+ &ps,
&reserve_withdraw_cb,
coin);
GNUNET_assert (GNUNET_SYSERR !=
diff --git a/src/exchange-lib/exchange_api_payback.c b/src/exchange-lib/exchange_api_payback.c
index 40b713857..ec0cda150 100644
--- a/src/exchange-lib/exchange_api_payback.c
+++ b/src/exchange-lib/exchange_api_payback.c
@@ -260,8 +260,7 @@ handle_payback_finished (void *cls,
* @param exchange the exchange handle; the exchange must be ready to operate
* @param pk kind of coin to pay back
* @param denom_sig signature over the coin by the exchange using @a pk
- * @param coin_priv the coin's private key,
- * @param blinding_key where to fetch the coin's blinding key
+ * @param ps secret internals of the original planchet
* @param payback_cb the callback to call when the final result for this request is available
* @param payback_cb_cls closure for @a payback_cb
* @return NULL
@@ -272,8 +271,7 @@ struct TALER_EXCHANGE_PaybackHandle *
TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKeyP *blinding_key,
+ const struct TALER_PlanchetSecretsP *ps,
TALER_EXCHANGE_PaybackResultCallback payback_cb,
void *payback_cb_cls)
{
@@ -288,12 +286,12 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange,
MAH_handle_is_ready (exchange));
pr.purpose.purpose = htonl (TALER_SIGNATURE_WALLET_COIN_PAYBACK);
pr.purpose.size = htonl (sizeof (struct TALER_PaybackRequestPS));
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
+ GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
&pr.coin_pub.eddsa_pub);
pr.h_denom_pub = pk->h_key;
- pr.coin_blind = *blinding_key;
+ pr.coin_blind = ps->blinding_key;
GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_eddsa_sign (&coin_priv->eddsa_priv,
+ GNUNET_CRYPTO_eddsa_sign (&ps->coin_priv.eddsa_priv,
&pr.purpose,
&coin_sig.eddsa_signature));
@@ -304,7 +302,7 @@ TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange,
"denom_sig", GNUNET_JSON_from_rsa_signature (denom_sig->rsa_signature),
"coin_pub", GNUNET_JSON_from_data_auto (&pr.coin_pub),
"coin_sig", GNUNET_JSON_from_data_auto (&coin_sig),
- "coin_blind_key_secret", GNUNET_JSON_from_data_auto (blinding_key)
+ "coin_blind_key_secret", GNUNET_JSON_from_data_auto (&ps->blinding_key)
);
if (NULL == payback_obj)
{
diff --git a/src/exchange-lib/exchange_api_refresh.c b/src/exchange-lib/exchange_api_refresh.c
index 510b6e409..305747f63 100644
--- a/src/exchange-lib/exchange_api_refresh.c
+++ b/src/exchange-lib/exchange_api_refresh.c
@@ -236,18 +236,16 @@ free_melted_coin (struct MeltedCoin *mc)
static void
free_melt_data (struct MeltData *md)
{
- unsigned int i;
-
free_melted_coin (&md->melted_coin);
if (NULL != md->fresh_pks)
{
- for (i=0;i<md->num_fresh_coins;i++)
+ for (unsigned int i=0;i<md->num_fresh_coins;i++)
if (NULL != md->fresh_pks[i].rsa_public_key)
GNUNET_CRYPTO_rsa_public_key_free (md->fresh_pks[i].rsa_public_key);
GNUNET_free (md->fresh_pks);
}
- for (i=0;i<TALER_CNC_KAPPA;i++)
+ for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
GNUNET_free (md->fresh_coins[i]);
/* Finally, clean up a bit...
(NOTE: compilers might optimize this away, so this is
@@ -600,8 +598,6 @@ deserialize_melt_data (const char *buf,
{
struct MeltData *md;
struct MeltDataP mdp;
- unsigned int i;
- unsigned int j;
size_t off;
int ok;
@@ -615,7 +611,7 @@ deserialize_melt_data (const char *buf,
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++)
+ for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
md->fresh_coins[i] = GNUNET_new_array (md->num_fresh_coins,
struct TALER_PlanchetSecretsP);
off = sizeof (struct MeltDataP);
@@ -624,14 +620,14 @@ deserialize_melt_data (const char *buf,
&buf[off],
buf_size - off,
&ok);
- for (i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++)
+ for (unsigned int i=0;(i<md->num_fresh_coins)&&(GNUNET_YES == ok);i++)
off += deserialize_denomination_key (&md->fresh_pks[i],
&buf[off],
buf_size - off,
&ok);
- for (i=0;i<TALER_CNC_KAPPA;i++)
- for(j=0;(j<md->num_fresh_coins)&&(GNUNET_YES == ok);j++)
+ for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
+ for (unsigned int j=0;(j<md->num_fresh_coins)&&(GNUNET_YES == ok);j++)
off += deserialize_fresh_coin (&md->fresh_coins[i][j],
&buf[off],
buf_size - off,
@@ -704,8 +700,6 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
{
struct MeltData md;
char *buf;
- unsigned int i;
- unsigned int j;
struct GNUNET_HashContext *hash_context;
struct TALER_Amount total;
struct TALER_CoinSpendPublicKeyP coin_pub;
@@ -715,7 +709,7 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
&coin_pub.eddsa_pub);
hash_context = GNUNET_CRYPTO_hash_context_start ();
/* build up melt data structure */
- for (i=0;i<TALER_CNC_KAPPA;i++)
+ for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
{
struct GNUNET_CRYPTO_EcdhePrivateKey *tpk;
struct TALER_TransferPublicKeyP tp;
@@ -747,18 +741,18 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
= GNUNET_CRYPTO_rsa_signature_dup (melt_sig->rsa_signature);
md.fresh_pks = GNUNET_new_array (fresh_pks_len,
struct TALER_DenominationPublicKey);
- for (i=0;i<fresh_pks_len;i++)
+ for (unsigned int i=0;i<fresh_pks_len;i++)
md.fresh_pks[i].rsa_public_key
= GNUNET_CRYPTO_rsa_public_key_dup (fresh_pks[i].key.rsa_public_key);
- for (i=0;i<TALER_CNC_KAPPA;i++)
+ for (unsigned int i=0;i<TALER_CNC_KAPPA;i++)
{
md.fresh_coins[i] = GNUNET_new_array (fresh_pks_len,
struct TALER_PlanchetSecretsP);
- for (j=0;j<fresh_pks_len;j++)
+ for (unsigned int j=0;j<fresh_pks_len;j++)
{
TALER_planchet_setup_refresh (&trans_sec[i],
- j,
- &md.fresh_coins[i][j]);
+ j,
+ &md.fresh_coins[i][j]);
}
}
@@ -766,7 +760,7 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
GNUNET_assert (GNUNET_OK ==
TALER_amount_get_zero (melt_amount->currency,
&total));
- for (j=0;j<fresh_pks_len;j++)
+ for (unsigned int j=0;j<fresh_pks_len;j++)
{
if ( (GNUNET_OK !=
TALER_amount_add (&total,
@@ -795,7 +789,7 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
/* next, add all of the hashes from the denomination keys to the
hash_context */
- for (i=0;i<fresh_pks_len;i++)
+ for (unsigned int i=0;i<fresh_pks_len;i++)
{
char *buf;
size_t buf_size;
@@ -820,28 +814,18 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
sizeof (struct TALER_AmountNBO));
}
- for (i = 0; i < TALER_CNC_KAPPA; i++)
+ for (unsigned int i = 0; i < TALER_CNC_KAPPA; i++)
{
- for (j = 0; j < fresh_pks_len; j++)
+ for (unsigned int j = 0; j < fresh_pks_len; j++)
{
const struct TALER_PlanchetSecretsP *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_PlanchetDetail pd;
fc = &md.fresh_coins[i][j];
- 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);
- if (GNUNET_YES !=
- GNUNET_CRYPTO_rsa_blind (&coin_hash,
- &fc->blinding_key.bks,
- md.fresh_pks[j].rsa_public_key,
- &coin_ev,
- &coin_ev_size))
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&md.fresh_pks[j],
+ fc,
+ &pd))
{
GNUNET_break_op (0);
GNUNET_CRYPTO_hash_context_abort (hash_context);
@@ -849,9 +833,9 @@ TALER_EXCHANGE_refresh_prepare (const struct TALER_CoinSpendPrivateKeyP *melt_pr
return NULL;
}
GNUNET_CRYPTO_hash_context_read (hash_context,
- coin_ev,
- coin_ev_size);
- GNUNET_free (coin_ev);
+ pd.coin_ev,
+ pd.coin_ev_size);
+ GNUNET_free (pd.coin_ev);
}
}
GNUNET_CRYPTO_hash_context_finish (hash_context,
@@ -1294,22 +1278,12 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
for (i=0;i<md->num_fresh_coins;i++)
{
const struct TALER_PlanchetSecretsP *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 */
- 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);
- if (GNUNET_YES !=
- GNUNET_CRYPTO_rsa_blind (&coin_hash,
- &fc->blinding_key.bks,
- md->fresh_pks[i].rsa_public_key,
- &coin_ev,
- &coin_ev_size))
+ struct TALER_PlanchetDetail pd;
+
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&md->fresh_pks[i],
+ fc,
+ &pd))
{
/* This should have been noticed during the preparation stage. */
GNUNET_break (0);
@@ -1322,9 +1296,9 @@ TALER_EXCHANGE_refresh_melt (struct TALER_EXCHANGE_Handle *exchange,
}
GNUNET_assert (0 ==
json_array_append_new (tmp,
- GNUNET_JSON_from_data (coin_ev,
- coin_ev_size)));
- GNUNET_free (coin_ev);
+ GNUNET_JSON_from_data (pd.coin_ev,
+ pd.coin_ev_size)));
+ GNUNET_free (pd.coin_ev);
}
GNUNET_assert (0 ==
json_array_append_new (coin_evs,
@@ -1510,13 +1484,13 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh,
struct TALER_DenominationPublicKey *pk;
json_t *jsonai;
struct GNUNET_CRYPTO_RsaSignature *blind_sig;
- struct GNUNET_CRYPTO_RsaSignature *sig;
struct TALER_CoinSpendPublicKeyP coin_pub;
struct GNUNET_HashCode coin_hash;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_rsa_signature ("ev_sig", &blind_sig),
GNUNET_JSON_spec_end()
};
+ struct TALER_FreshCoin coin;
fc = &rrh->md->fresh_coins[rrh->noreveal_index][i];
pk = &rrh->md->fresh_pks[i];
@@ -1533,31 +1507,28 @@ refresh_reveal_ok (struct TALER_EXCHANGE_RefreshRevealHandle *rrh,
return GNUNET_SYSERR;
}
- /* unblind the signature */
- sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
- &fc->blinding_key.bks,
- pk->rsa_public_key);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
-
- /* verify the signature */
+ /* needed to verify the signature, and we didn't store it earlier,
+ hence recomputing it here... */
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);
-
if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (&coin_hash,
- sig,
- pk->rsa_public_key))
+ TALER_planchet_to_coin (pk,
+ blind_sig,
+ fc,
+ &coin_hash,
+ &coin))
{
GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_CRYPTO_rsa_signature_free (blind_sig);
GNUNET_JSON_parse_free (outer_spec);
return GNUNET_SYSERR;
}
- coin_privs[i] = fc->coin_priv;
- sigs[i].rsa_signature = sig;
+ GNUNET_CRYPTO_rsa_signature_free (blind_sig);
+ coin_privs[i] = coin.coin_priv;
+ sigs[i] = coin.sig;
}
GNUNET_JSON_parse_free (outer_spec);
return GNUNET_OK;
diff --git a/src/exchange-lib/exchange_api_reserve.c b/src/exchange-lib/exchange_api_reserve.c
index 22e0e3d25..ef505d87d 100644
--- a/src/exchange-lib/exchange_api_reserve.c
+++ b/src/exchange-lib/exchange_api_reserve.c
@@ -693,9 +693,9 @@ struct TALER_EXCHANGE_ReserveWithdrawHandle
TALER_EXCHANGE_ReserveWithdrawResultCallback cb;
/**
- * Key used to blind the value.
+ * Secrets of the planchet.
*/
- struct TALER_DenominationBlindingKeyP blinding_key;
+ struct TALER_PlanchetSecretsP ps;
/**
* Denomination key we are withdrawing.
@@ -739,8 +739,7 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
const json_t *json)
{
struct GNUNET_CRYPTO_RsaSignature *blind_sig;
- struct GNUNET_CRYPTO_RsaSignature *sig;
- struct TALER_DenominationSignature dsig;
+ struct TALER_FreshCoin fc;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_rsa_signature ("ev_sig", &blind_sig),
GNUNET_JSON_spec_end()
@@ -754,29 +753,28 @@ reserve_withdraw_ok (struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh,
GNUNET_break_op (0);
return GNUNET_SYSERR;
}
- sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
- &wsh->blinding_key.bks,
- wsh->pk->key.rsa_public_key);
- GNUNET_CRYPTO_rsa_signature_free (blind_sig);
if (GNUNET_OK !=
- GNUNET_CRYPTO_rsa_verify (&wsh->c_hash,
- sig,
- wsh->pk->key.rsa_public_key))
+ TALER_planchet_to_coin (&wsh->pk->key,
+ blind_sig,
+ &wsh->ps,
+ &wsh->c_hash,
+ &fc))
{
GNUNET_break_op (0);
- GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_JSON_parse_free (spec);
return GNUNET_SYSERR;
}
+ GNUNET_JSON_parse_free (spec);
+
/* signature is valid, return it to the application */
- dsig.rsa_signature = sig;
wsh->cb (wsh->cb_cls,
MHD_HTTP_OK,
TALER_EC_NONE,
- &dsig,
+ &fc.sig,
json);
/* make sure callback isn't called again after return */
wsh->cb = NULL;
- GNUNET_CRYPTO_rsa_signature_free (sig);
+ GNUNET_CRYPTO_rsa_signature_free (fc.sig.rsa_signature);
return GNUNET_OK;
}
@@ -978,9 +976,7 @@ handle_reserve_withdraw_finished (void *cls,
* @param exchange the exchange handle; the exchange must be ready to operate
* @param pk kind of coin to create
* @param reserve_priv private key of the reserve to withdraw from
- * @param coin_priv where to fetch the coin's private key,
- * caller must have committed this value to disk before the call (with @a pk)
- * @param blinding_key where to fetch the coin's blinding key
+ * @param ps secrets of the planchet
* caller must have committed this value to disk before the call (with @a pk)
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for the above callback
@@ -992,44 +988,33 @@ struct TALER_EXCHANGE_ReserveWithdrawHandle *
TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKeyP *blinding_key,
+ const struct TALER_PlanchetSecretsP *ps,
TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls)
{
struct TALER_EXCHANGE_ReserveWithdrawHandle *wsh;
struct TALER_WithdrawRequestPS req;
struct TALER_ReserveSignatureP reserve_sig;
- struct TALER_CoinSpendPublicKeyP coin_pub;
struct GNUNET_CURL_Context *ctx;
struct TALER_Amount amount_with_fee;
- char *coin_ev;
- size_t coin_ev_size;
json_t *withdraw_obj;
CURL *eh;
+ struct TALER_PlanchetDetail pd;
+ if (GNUNET_OK !=
+ TALER_planchet_prepare (&pk->key,
+ ps,
+ &pd))
+ {
+ GNUNET_break_op (0);
+ return NULL;
+ }
wsh = GNUNET_new (struct TALER_EXCHANGE_ReserveWithdrawHandle);
wsh->exchange = exchange;
wsh->cb = res_cb;
wsh->cb_cls = res_cb_cls;
wsh->pk = pk;
-
- GNUNET_CRYPTO_eddsa_key_get_public (&coin_priv->eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
- sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
- &wsh->c_hash);
- if (GNUNET_YES !=
- GNUNET_CRYPTO_rsa_blind (&wsh->c_hash,
- &blinding_key->bks,
- pk->key.rsa_public_key,
- &coin_ev,
- &coin_ev_size))
- {
- GNUNET_break_op (0);
- GNUNET_free (wsh);
- return NULL;
- }
+ wsh->c_hash = pd.c_hash;
GNUNET_CRYPTO_eddsa_key_get_public (&reserve_priv->eddsa_priv,
&wsh->reserve_pub.eddsa_pub);
req.purpose.size = htonl (sizeof (struct TALER_WithdrawRequestPS));
@@ -1042,7 +1027,7 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
{
/* exchange gave us denomination keys that overflow like this!? */
GNUNET_break_op (0);
- GNUNET_free (coin_ev);
+ GNUNET_free (pd.coin_ev);
GNUNET_free (wsh);
return NULL;
}
@@ -1050,10 +1035,9 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
&amount_with_fee);
TALER_amount_hton (&req.withdraw_fee,
&pk->fee_withdraw);
- GNUNET_CRYPTO_rsa_public_key_hash (pk->key.rsa_public_key,
- &req.h_denomination_pub);
- GNUNET_CRYPTO_hash (coin_ev,
- coin_ev_size,
+ req.h_denomination_pub = pd.denom_pub_hash;
+ GNUNET_CRYPTO_hash (pd.coin_ev,
+ pd.coin_ev_size,
&req.h_coin_envelope);
GNUNET_assert (GNUNET_OK ==
GNUNET_CRYPTO_eddsa_sign (&reserve_priv->eddsa_priv,
@@ -1062,11 +1046,11 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
withdraw_obj = json_pack ("{s:o, s:o," /* denom_pub and coin_ev */
" s:o, s:o}",/* reserve_pub and reserve_sig */
"denom_pub", GNUNET_JSON_from_rsa_public_key (pk->key.rsa_public_key),
- "coin_ev", GNUNET_JSON_from_data (coin_ev,
- coin_ev_size),
+ "coin_ev", GNUNET_JSON_from_data (pd.coin_ev,
+ pd.coin_ev_size),
"reserve_pub", GNUNET_JSON_from_data_auto (&wsh->reserve_pub),
"reserve_sig", GNUNET_JSON_from_data_auto (&reserve_sig));
- GNUNET_free (coin_ev);
+ GNUNET_free (pd.coin_ev);
if (NULL == withdraw_obj)
{
GNUNET_break (0);
@@ -1074,7 +1058,7 @@ TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
}
- wsh->blinding_key = *blinding_key;
+ wsh->ps = *ps;
wsh->url = MAH_path_to_url (exchange, "/reserve/withdraw");
eh = curl_easy_init ();
diff --git a/src/exchange-lib/test_exchange_api.c b/src/exchange-lib/test_exchange_api.c
index 70fb3ffdc..7c0dfa982 100644
--- a/src/exchange-lib/test_exchange_api.c
+++ b/src/exchange-lib/test_exchange_api.c
@@ -341,14 +341,9 @@ struct Command
struct TALER_DenominationSignature sig;
/**
- * Set (by the interpreter) to the coin's private key.
+ * Private key material of the coin, set by the interpreter.
*/
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * Blinding key used for the operation.
- */
- struct TALER_DenominationBlindingKeyP blinding_key;
+ struct TALER_PlanchetSecretsP ps;
/**
* Withdraw handle (while operation is running).
@@ -1984,7 +1979,7 @@ get_public_key_from_coin_command (const struct Command *coin,
switch (coin->oc)
{
case OC_WITHDRAW_SIGN:
- GNUNET_CRYPTO_eddsa_key_get_public (&coin->details.reserve_withdraw.coin_priv.eddsa_priv,
+ GNUNET_CRYPTO_eddsa_key_get_public (&coin->details.reserve_withdraw.ps.coin_priv.eddsa_priv,
&coin_pub->eddsa_pub);
break;
case OC_REFRESH_REVEAL:
@@ -2016,7 +2011,6 @@ interpreter_run (void *cls)
struct Command *cmd = &is->commands[is->ip];
const struct Command *ref;
struct TALER_ReservePublicKeyP reserve_pub;
- struct TALER_CoinSpendPublicKeyP coin_pub;
struct TALER_Amount amount;
struct GNUNET_TIME_Absolute execution_date;
json_t *sender_details;
@@ -2165,27 +2159,14 @@ interpreter_run (void *cls)
return;
}
- /* create coin's private key */
- {
- struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
-
- priv = GNUNET_CRYPTO_eddsa_key_create ();
- cmd->details.reserve_withdraw.coin_priv.eddsa_priv = *priv;
- GNUNET_free (priv);
- }
- GNUNET_CRYPTO_eddsa_key_get_public (&cmd->details.reserve_withdraw.coin_priv.eddsa_priv,
- &coin_pub.eddsa_pub);
- GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
- &cmd->details.reserve_withdraw.blinding_key,
- sizeof (cmd->details.reserve_withdraw.blinding_key));
+ TALER_planchet_setup_random (&cmd->details.reserve_withdraw.ps);
cmd->details.reserve_withdraw.wsh
= TALER_EXCHANGE_reserve_withdraw (exchange,
- cmd->details.reserve_withdraw.pk,
- &ref->details.admin_add_incoming.reserve_priv,
- &cmd->details.reserve_withdraw.coin_priv,
- &cmd->details.reserve_withdraw.blinding_key,
- &reserve_withdraw_cb,
- is);
+ cmd->details.reserve_withdraw.pk,
+ &ref->details.admin_add_incoming.reserve_priv,
+ &cmd->details.reserve_withdraw.ps,
+ &reserve_withdraw_cb,
+ is);
if (NULL == cmd->details.reserve_withdraw.wsh)
{
GNUNET_break (0);
@@ -2217,7 +2198,7 @@ interpreter_run (void *cls)
switch (ref->oc)
{
case OC_WITHDRAW_SIGN:
- coin_priv = &ref->details.reserve_withdraw.coin_priv;
+ coin_priv = &ref->details.reserve_withdraw.ps.coin_priv;
coin_pk = ref->details.reserve_withdraw.pk;
coin_pk_sig = &ref->details.reserve_withdraw.sig;
break;
@@ -2376,7 +2357,7 @@ interpreter_run (void *cls)
GNUNET_assert (NULL != ref);
GNUNET_assert (OC_WITHDRAW_SIGN == ref->oc);
- melt_priv = ref->details.reserve_withdraw.coin_priv;
+ melt_priv = ref->details.reserve_withdraw.ps.coin_priv;
if (GNUNET_OK !=
TALER_string_to_amount (md->amount,
&melt_amount))
@@ -2478,7 +2459,7 @@ interpreter_run (void *cls)
/* finally, use private key from withdraw sign command */
cmd->details.refresh_link.rlh
= TALER_EXCHANGE_refresh_link (exchange,
- &ref->details.reserve_withdraw.coin_priv,
+ &ref->details.reserve_withdraw.ps.coin_priv,
&link_cb,
is);
if (NULL == cmd->details.refresh_link.rlh)
@@ -2745,8 +2726,7 @@ interpreter_run (void *cls)
= TALER_EXCHANGE_payback (exchange,
ref->details.reserve_withdraw.pk,
&ref->details.reserve_withdraw.sig,
- &ref->details.reserve_withdraw.coin_priv,
- &ref->details.reserve_withdraw.blinding_key,
+ &ref->details.reserve_withdraw.ps,
&payback_cb,
is);
return;
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index 39de34b8a..d5024e6c8 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -396,7 +396,83 @@ int
TALER_test_coin_valid (const struct TALER_CoinPublicInfo *coin_public_info);
-/* ****************** Refresh crypto primitives ************* */
+GNUNET_NETWORK_STRUCT_BEGIN
+
+/**
+ * Header for serializations of coin-specific information about the
+ * fresh coins we generate. These are the secrets that arise during
+ * planchet generation, which is the first stage of creating a new
+ * coin.
+ */
+struct TALER_PlanchetSecretsP
+{
+
+ /**
+ * Private key of the coin.
+ */
+ struct TALER_CoinSpendPrivateKeyP coin_priv;
+
+ /**
+ * The blinding key.
+ */
+ struct TALER_DenominationBlindingKeyP blinding_key;
+
+};
+
+GNUNET_NETWORK_STRUCT_END
+
+
+/**
+ * Details about a planchet that the customer wants to obtain
+ * a withdrawal authorization. This is the information that
+ * will need to be sent to the exchange to obtain the blind
+ * signature required to turn a planchet into a coin.
+ */
+struct TALER_PlanchetDetail
+{
+ /**
+ * Hash of the denomination public key.
+ */
+ struct GNUNET_HashCode denom_pub_hash;
+
+ /**
+ * Hash of the coin's public key. Kept around so we do not need to
+ * compute it again. Can be recomputed by hashing the public key
+ * of @a coin_priv if storage is at a premium.
+ */
+ struct GNUNET_HashCode c_hash;
+
+ /**
+ * Blinded coin (see GNUNET_CRYPTO_rsa_blind()). Note: is malloc()'ed!
+ */
+ char *coin_ev;
+
+ /**
+ * Number of bytes in @a coin_ev.
+ */
+ size_t coin_ev_size;
+};
+
+
+/**
+ * Information about a (fresh) coin, returned from the API when we
+ * finished creating a coin. Note that @e sig needs to be freed
+ * using the appropriate code.
+ */
+struct TALER_FreshCoin
+{
+
+ /**
+ * The exchange's signature over the coin's public key.
+ */
+ struct TALER_DenominationSignature sig;
+
+ /**
+ * The coin's private key.
+ */
+ struct TALER_CoinSpendPrivateKeyP coin_priv;
+
+};
GNUNET_NETWORK_STRUCT_BEGIN
@@ -426,6 +502,7 @@ struct TALER_TransferSecretP
*/
#define TALER_WIRE_TRANSFER_IDENTIFIER_LEN_STR "32"
+
/**
* Raw value of a wire transfer subjects, without the checksum.
*/
@@ -472,6 +549,68 @@ struct TALER_WireTransferIdentifierP
GNUNET_NETWORK_STRUCT_END
+
+/**
+ * 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 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_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
+ unsigned int coin_num_salt,
+ struct TALER_PlanchetSecretsP *fc);
+
+
+/**
+ * Setup information for a fresh coin.
+ *
+ * @param[out] ps value to initialize
+ */
+void
+TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps);
+
+
+/**
+ * Prepare a planchet for tipping. Creates and blinds a coin.
+ *
+ * @param dk denomination key for the coin to be created
+ * @param ps secret planchet internals (for #TALER_planchet_to_coin)
+ * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and
+ * other withdraw operations
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
+ const struct TALER_PlanchetSecretsP *ps,
+ struct TALER_PlanchetDetail *pd);
+
+
+/**
+ * Obtain a coin from the planchet's secrets and the blind signature
+ * of the exchange.
+ *
+ * @param dk denomination key, must match what was given to #TALER_planchet_prepare()
+ * @param blind_sig blind signature from the exchange
+ * @param ps secrets from #TALER_planchet_prepare()
+ * @param c_hash hash of the coin's public key for verification of the signature
+ * @param[out] coin set to the details of the fresh coin
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk,
+ const struct GNUNET_CRYPTO_RsaSignature *blind_sig,
+ const struct TALER_PlanchetSecretsP *ps,
+ const struct GNUNET_HashCode *c_hash,
+ struct TALER_FreshCoin *coin);
+
+
+/* ****************** Refresh crypto primitives ************* */
+
+
/**
* Given the coin and the transfer private keys, compute the
* transfer secret. (Technically, we only need one of the two
@@ -516,44 +655,5 @@ TALER_link_recover_transfer_secret (const struct TALER_TransferPublicKeyP *trans
const struct TALER_CoinSpendPrivateKeyP *coin_priv,
struct TALER_TransferSecretP *transfer_secret);
-GNUNET_NETWORK_STRUCT_BEGIN
-
-/**
- * Header for serializations of coin-specific information about the
- * fresh coins we generate during a melt.
- */
-struct TALER_PlanchetSecretsP
-{
-
- /**
- * Private key of the coin.
- */
- struct TALER_CoinSpendPrivateKeyP coin_priv;
-
- /**
- * The blinding key.
- */
- struct TALER_DenominationBlindingKeyP blinding_key;
-
-};
-
-GNUNET_NETWORK_STRUCT_END
-
-
-/**
- * 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 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_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
- unsigned int coin_num_salt,
- struct TALER_PlanchetSecretsP *fc);
-
-
#endif
diff --git a/src/include/taler_exchange_service.h b/src/include/taler_exchange_service.h
index 814078a02..3b4562a69 100644
--- a/src/include/taler_exchange_service.h
+++ b/src/include/taler_exchange_service.h
@@ -976,9 +976,7 @@ typedef void
* @param exchange the exchange handle; the exchange must be ready to operate
* @param pk kind of coin to create
* @param reserve_priv private key of the reserve to withdraw from
- * @param coin_priv where to fetch the coin's private key,
- * caller must have committed this value to disk before the call (with @a pk)
- * @param blinding_key where to fetch the coin's blinding key
+ * @param ps secrets of the planchet
* caller must have committed this value to disk before the call (with @a pk)
* @param res_cb the callback to call when the final result for this request is available
* @param res_cb_cls closure for @a res_cb
@@ -990,8 +988,7 @@ struct TALER_EXCHANGE_ReserveWithdrawHandle *
TALER_EXCHANGE_reserve_withdraw (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_ReservePrivateKeyP *reserve_priv,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKeyP *blinding_key,
+ const struct TALER_PlanchetSecretsP *ps,
TALER_EXCHANGE_ReserveWithdrawResultCallback res_cb,
void *res_cb_cls);
@@ -1540,8 +1537,7 @@ typedef void
* @param exchange the exchange handle; the exchange must be ready to operate
* @param pk kind of coin to pay back
* @param denom_sig signature over the coin by the exchange using @a pk
- * @param coin_priv the coin's private key,
- * @param blinding_key where to fetch the coin's blinding key
+ * @param ps secret internals of the original planchet
* @param payback_cb the callback to call when the final result for this request is available
* @param payback_cb_cls closure for @a payback_cb
* @return NULL
@@ -1552,8 +1548,7 @@ struct TALER_EXCHANGE_PaybackHandle *
TALER_EXCHANGE_payback (struct TALER_EXCHANGE_Handle *exchange,
const struct TALER_EXCHANGE_DenomPublicKey *pk,
const struct TALER_DenominationSignature *denom_sig,
- const struct TALER_CoinSpendPrivateKeyP *coin_priv,
- const struct TALER_DenominationBlindingKeyP *blinding_key,
+ const struct TALER_PlanchetSecretsP *ps,
TALER_EXCHANGE_PaybackResultCallback payback_cb,
void *payback_cb_cls);
diff --git a/src/include/taler_util.h b/src/include/taler_util.h
index 34e07a351..84d4f5dee 100644
--- a/src/include/taler_util.h
+++ b/src/include/taler_util.h
@@ -134,6 +134,4 @@ const struct GNUNET_OS_ProjectData *
TALER_project_data_default (void);
-
-
#endif
diff --git a/src/util/crypto.c b/src/util/crypto.c
index 378b73dc4..efc74850d 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -171,23 +171,49 @@ TALER_link_recover_transfer_secret (const struct TALER_TransferPublicKeyP *trans
/**
+ * Set the bits in the private EdDSA key so that they match
+ * the specification.
+ *
+ * @param[in,out] pk private key to patch
+ */
+static void
+patch_private_key (struct GNUNET_CRYPTO_EddsaPrivateKey *pk)
+{
+ uint8_t *p = (uint8_t *) pk;
+
+ /* Taken from like 170-172 of libgcrypt/cipher/ecc.c
+ * We note that libgcrypt stores the private key in the reverse order
+ * from many Ed25519 implementatons. */
+ p[0] &= 0x7f; /* Clear bit 255. */
+ p[0] |= 0x40; /* Set bit 254. */
+ p[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */
+
+ /* FIXME: Run GNUNET_CRYPTO_ecdhe_key_create several times and inspect
+ * the output to verify that the same bits are set and cleared.
+ * Is it worth also adding a test case that runs gcry_pk_testkey on
+ * this key after first parsing it into libgcrypt's s-expression mess
+ * ala decode_private_eddsa_key from gnunet/src/util/crypto_ecc.c?
+ * It'd run check_secret_key but not test_keys from libgcrypt/cipher/ecc.c */
+}
+
+
+/**
* Setup information for a fresh coin.
*
* @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
+ * @param[out] ps value to initialize
*/
void
TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
- unsigned int coin_num_salt,
- struct TALER_PlanchetSecretsP *fc)
+ unsigned int coin_num_salt,
+ struct TALER_PlanchetSecretsP *ps)
{
uint32_t be_salt = htonl (coin_num_salt);
- uint8_t *p;
GNUNET_assert (GNUNET_OK ==
- GNUNET_CRYPTO_kdf (fc,
- sizeof (*fc),
+ GNUNET_CRYPTO_kdf (ps,
+ sizeof (*ps),
&be_salt,
sizeof (be_salt),
secret_seed,
@@ -195,24 +221,97 @@ TALER_planchet_setup_refresh (const struct TALER_TransferSecretP *secret_seed,
"taler-coin-derivation",
strlen ("taler-coin-derivation"),
NULL, 0));
+ patch_private_key (&ps->coin_priv.eddsa_priv);
+}
- /* Taken from like 170-172 of libgcrypt/cipher/ecc.c
- * We note that libgcrypt stores the private key in the reverse order
- * from many Ed25519 implementatons. */
- p = (uint8_t *) &(fc->coin_priv);
- p[0] &= 0x7f; /* Clear bit 255. */
- p[0] |= 0x40; /* Set bit 254. */
- p[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */
- /* FIXME: Run GNUNET_CRYPTO_ecdhe_key_create several times and inspect
- * the output to verify that the same bits are set and cleared.
- * Is it worth also adding a test case that runs gcry_pk_testkey on
- * this key after first parsing it into libgcrypt's s-expression mess
- * ala decode_private_eddsa_key from gnunet/src/util/crypto_ecc.c?
- * It'd run check_secret_key but not test_keys from libgcrypt/cipher/ecc.c */
+/**
+ * Setup information for a fresh coin.
+ *
+ * @param[out] ps value to initialize
+ */
+void
+TALER_planchet_setup_random (struct TALER_PlanchetSecretsP *ps)
+{
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG,
+ ps,
+ sizeof (*ps));
+ patch_private_key (&ps->coin_priv.eddsa_priv);
+}
+
+
+/**
+ * Prepare a planchet for tipping. Creates and blinds a coin.
+ *
+ * @param dk denomination key for the coin to be created
+ * @param ps secret planchet internals (for #TALER_planchet_to_coin)
+ * @param[out] pd set to the planchet detail for TALER_MERCHANT_tip_pickup() and
+ * other withdraw operations
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_planchet_prepare (const struct TALER_DenominationPublicKey *dk,
+ const struct TALER_PlanchetSecretsP *ps,
+ struct TALER_PlanchetDetail *pd)
+{
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+
+ GNUNET_CRYPTO_eddsa_key_get_public (&ps->coin_priv.eddsa_priv,
+ &coin_pub.eddsa_pub);
+ GNUNET_CRYPTO_hash (&coin_pub.eddsa_pub,
+ sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey),
+ &pd->c_hash);
+ if (GNUNET_YES !=
+ GNUNET_CRYPTO_rsa_blind (&pd->c_hash,
+ &ps->blinding_key.bks,
+ dk->rsa_public_key,
+ &pd->coin_ev,
+ &pd->coin_ev_size))
+ {
+ GNUNET_break_op (0);
+ return GNUNET_SYSERR;
+ }
+ GNUNET_CRYPTO_rsa_public_key_hash (dk->rsa_public_key,
+ &pd->denom_pub_hash);
+ return GNUNET_OK;
}
+/**
+ * Obtain a coin from the planchet's secrets and the blind signature
+ * of the exchange.
+ *
+ * @param dk denomination key, must match what was given to #TALER_planchet_prepare()
+ * @param blind_sig blind signature from the exchange
+ * @param ps secrets from #TALER_planchet_prepare()
+ * @param c_hash hash of the coin's public key for verification of the signature
+ * @param[out] coin set to the details of the fresh coin
+ * @return #GNUNET_OK on success
+ */
+int
+TALER_planchet_to_coin (const struct TALER_DenominationPublicKey *dk,
+ const struct GNUNET_CRYPTO_RsaSignature *blind_sig,
+ const struct TALER_PlanchetSecretsP *ps,
+ const struct GNUNET_HashCode *c_hash,
+ struct TALER_FreshCoin *coin)
+{
+ struct GNUNET_CRYPTO_RsaSignature *sig;
+ sig = GNUNET_CRYPTO_rsa_unblind (blind_sig,
+ &ps->blinding_key.bks,
+ dk->rsa_public_key);
+ if (GNUNET_OK !=
+ GNUNET_CRYPTO_rsa_verify (c_hash,
+ sig,
+ dk->rsa_public_key))
+ {
+ GNUNET_break_op (0);
+ GNUNET_CRYPTO_rsa_signature_free (sig);
+ return GNUNET_SYSERR;
+ }
+ coin->sig.rsa_signature = sig;
+ coin->coin_priv = ps->coin_priv;
+ return GNUNET_OK;
+}
/* end of crypto.c */
diff --git a/src/util/test_crypto.c b/src/util/test_crypto.c
index 953ad94df..4713b3a35 100644
--- a/src/util/test_crypto.c
+++ b/src/util/test_crypto.c
@@ -71,11 +71,11 @@ test_high_level ()
&secret2,
sizeof (secret)));
TALER_planchet_setup_refresh (&secret,
- 0,
- &fc1);
+ 0,
+ &fc1);
TALER_planchet_setup_refresh (&secret,
- 1,
- &fc2);
+ 1,
+ &fc2);
GNUNET_assert (0 !=
memcmp (&fc1,
&fc2,
@@ -84,12 +84,55 @@ test_high_level ()
}
+/**
+ * Test the basic planchet functionality of creating a fresh planchet
+ * and extracting the respective signature.
+ *
+ * @return 0 on success
+ */
+static int
+test_planchets ()
+{
+ struct TALER_PlanchetSecretsP ps;
+ struct TALER_DenominationPrivateKey dk_priv;
+ struct TALER_DenominationPublicKey dk_pub;
+ struct TALER_PlanchetDetail pd;
+ struct GNUNET_CRYPTO_RsaSignature *blind_sig;
+ struct TALER_FreshCoin coin;
+
+ dk_priv.rsa_private_key = GNUNET_CRYPTO_rsa_private_key_create (1024);
+ dk_pub.rsa_public_key = GNUNET_CRYPTO_rsa_private_key_get_public (dk_priv.rsa_private_key);
+ TALER_planchet_setup_random (&ps);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_planchet_prepare (&dk_pub,
+ &ps,
+ &pd));
+ blind_sig = GNUNET_CRYPTO_rsa_sign_blinded (dk_priv.rsa_private_key,
+ pd.coin_ev,
+ pd.coin_ev_size);
+ GNUNET_assert (NULL != blind_sig);
+ GNUNET_assert (GNUNET_OK ==
+ TALER_planchet_to_coin (&dk_pub,
+ blind_sig,
+ &ps,
+ &pd.c_hash,
+ &coin));
+ GNUNET_CRYPTO_rsa_signature_free (blind_sig);
+ GNUNET_CRYPTO_rsa_signature_free (coin.sig.rsa_signature);
+ GNUNET_CRYPTO_rsa_private_key_free (dk_priv.rsa_private_key);
+ GNUNET_CRYPTO_rsa_public_key_free (dk_pub.rsa_public_key);
+ return 0;
+}
+
+
int
main(int argc,
const char *const argv[])
{
if (0 != test_high_level ())
return 1;
+ if (0 != test_planchets ())
+ return 1;
return 0;
}