aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-10-31 14:02:54 +0100
committerChristian Grothoff <christian@grothoff.org>2017-10-31 14:02:54 +0100
commit2f2930f1ba0f1708fc4455c66173fd61188a3369 (patch)
treed09c8fa13d7bbd90fd94ceaa2d642e6f2693a9d3
parentec8146de92d92db2cb0e9453d5ef1b538b852354 (diff)
major API refactoring, adding planchet generation and coin extraction APIs to the Taler crypto library, thereby simplifying code in withdraw, refresh, tipping, payback and testcases; slight API incompatibilities to previous versions are introduced
-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;
}