aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/exchange/taler-exchange-httpd_age-withdraw_reveal.c107
-rw-r--r--src/include/taler_crypto_lib.h9
-rw-r--r--src/util/crypto.c35
3 files changed, 113 insertions, 38 deletions
diff --git a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
index cdb8115f8..7ecd0b373 100644
--- a/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
+++ b/src/exchange/taler-exchange-httpd_age-withdraw_reveal.c
@@ -29,13 +29,30 @@
#include "taler-exchange-httpd_keys.h"
/**
+ * Clients have to prove that the public keys for all age groups larger than
+ * the allowed maximum age group are derived by scalar multiplication from this
+ * Edx25519 public key (in Crockford Base32 encoding):
+ *
+ * DZJRF6HXN520505XDAWM8NMH36QV9J3VH77265WQ09EBQ76QSKCG
+ *
+ * The private key was chosen randomly and then deleted.
+ */
+static struct GNUNET_CRYPTO_Edx25519PublicKey publishedBaseKey = {
+ .q_y = { 0x6f, 0xe5, 0x87, 0x9a, 0x3d, 0xa9, 0x44, 0x20,
+ 0x80, 0xbd, 0x6a, 0xb9, 0x44, 0x56, 0x91, 0x19,
+ 0xaf, 0xb4, 0xc8, 0x7b, 0x89, 0xce, 0x23, 0x17,
+ 0x97, 0x20, 0x5c, 0xbb, 0x9c, 0xd7, 0xcc, 0xd9},
+};
+
+/**
* State for an /age-withdraw/$ACH/reveal operation.
*/
struct AgeRevealContext
{
/**
- * Commitment for the age-withdraw operation.
+ * Commitment for the age-withdraw operation, previously called by the
+ * client.
*/
struct TALER_AgeWithdrawCommitmentHashP ach;
@@ -63,11 +80,6 @@ struct AgeRevealContext
struct TEH_DenominationKey *denom_keys;
/**
- * #num_coins hases of blinded coins.
- */
- struct TALER_BlindedCoinHashP *coin_evs;
-
- /**
* Total sum of all denominations' values
**/
struct TALER_Amount total_amount;
@@ -78,6 +90,11 @@ struct AgeRevealContext
struct TALER_Amount total_fee;
/**
+ * #num_coins hashes of blinded coins.
+ */
+ struct TALER_BlindedCoinHashP *coin_evs;
+
+ /**
* #num_coins*(kappa - 1) disclosed coins.
*/
struct GNUNET_CRYPTO_EddsaPrivateKey *disclosed_coins;
@@ -504,7 +521,7 @@ are_denominations_valid (
if (0 != TALER_amount_cmp (&sum, amount_with_fee))
{
- GNUNET_break (0);
+ GNUNET_break_op (0);
*result = TALER_MHD_reply_with_ec (connection,
TALER_EC_EXCHANGE_AGE_WITHDRAW_AMOUNT_INCORRECT,
NULL);
@@ -516,6 +533,61 @@ are_denominations_valid (
}
+/**
+ * Checks the validity of the disclosed coins as follows:
+ * - Derives and calculates the disclosed coins'
+ * - public keys,
+ * - nonces (if applicable),
+ * - age commitments,
+ * - blindings
+ * - blinded hashes
+ * - Computes h_commitment with those calculated and the undisclosed hashes
+ * - Compares h_commitment with the value from the original commitment
+ * - Verifies that all public keys in indices larger than max_age_group are
+ * derived from the constant public key.
+ *
+ * The derivation of the blindings, (potential) nonces and age-commitment from
+ * a coin's private keys is defined in
+ * https://docs.taler.net/design-documents/024-age-restriction.html#withdraw
+ *
+ * @param connection HTTP-connection to the client
+ * @param h_commitment_orig Original commitment
+ * @param max_age_group Maximum age group allowed for the age restriction
+ * @param noreveal_idx Index that was given to the client in response to the age-withdraw request
+ * @param num_coins Number of coins
+ * @param coin_evs The Hashes of the undisclosed, blinded coins
+ * @param discloded_coins The private keys of the disclosed coins
+ * @param denom_keys The array of denomination keys. Needed to detect Clause-Schnorr-based denominations
+ * @param[out] result On error, a HTTP-response will be queued and result set accordingly
+ * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
+ */
+static enum GNUNET_GenericReturnValue
+verify_commitment_and_max_age (
+ struct MHD_Connection *connection,
+ const struct TALER_AgeWithdrawCommitmentHashP *h_commitment_orig,
+ uint32_t max_age_group,
+ uint32_t noreveal_idx,
+ uint32_t num_coins,
+ const struct TALER_BlindedCoinHashP *coin_evs,
+ const struct GNUNET_CRYPTO_EddsaPrivateKey *disclosed_coins,
+ const struct TEH_DenominationKey *denom_keys,
+ MHD_RESULT *result)
+{
+ struct TALER_BlindedCoinHashP *disclosed_evs; /* Will contain all calculated hashes */
+
+ disclosed_evs = GNUNET_new_array (
+ num_coins * (TALER_CNC_KAPPA - 1),
+ struct TALER_BlindedCoinHashP);
+
+ for (uint32_t i = 0; i < num_coins; i++)
+ {
+ /* FIXME:oec: Calculate new coins and blinded hashes */
+ }
+
+ return GNUNET_SYSERR;
+}
+
+
MHD_RESULT
TEH_handler_age_withdraw_reveal (
struct TEH_RequestContext *rc,
@@ -583,15 +655,24 @@ TEH_handler_age_withdraw_reveal (
&result))
break;
+ /* Verify the computed h_commitment equals the committed one and that
+ * coins have a maximum age group of max_age_group */
+ if (GNUNET_OK != verify_commitment_and_max_age (
+ rc->connection,
+ &actx.commitment.h_commitment,
+ actx.commitment.max_age_group,
+ actx.commitment.noreveal_index,
+ actx.num_coins,
+ actx.coin_evs,
+ actx.disclosed_coins,
+ actx.denom_keys,
+ &result))
+ break;
+
+ /* TODO:oec: sign the coins */
} while(0);
- /* TODO:oec: compute the disclosed blinded coins */
- /* TODO:oec: generate h_commitment_comp */
- /* TODO:oec: compare h_commitment_comp against h_commitment */
- /* TODO:oec: sign the coins */
- /* TODO:oec: send response */
-
age_reveal_context_free (&actx);
GNUNET_JSON_parse_free (spec);
return result;
diff --git a/src/include/taler_crypto_lib.h b/src/include/taler_crypto_lib.h
index db50efa10..c285a38ee 100644
--- a/src/include/taler_crypto_lib.h
+++ b/src/include/taler_crypto_lib.h
@@ -1309,13 +1309,8 @@ struct TALER_AgeAttestation
#endif
};
-
-extern const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash;
-#define TALER_AgeCommitmentHash_isNullOrZero(ph) \
- ((NULL == ph) || \
- (0 == memcmp (ph, \
- &TALER_ZeroAgeCommitmentHash, \
- sizeof(struct TALER_AgeCommitmentHash))))
+#define TALER_AgeCommitmentHash_isNullOrZero(ph) ((NULL == ph) || \
+ GNUNET_is_zero (ph))
/**
* @brief Type of public signing keys for verifying blindly signed coins.
diff --git a/src/util/crypto.c b/src/util/crypto.c
index 5cbba8135..bb14b6cdc 100644
--- a/src/util/crypto.c
+++ b/src/util/crypto.c
@@ -27,11 +27,6 @@
#include <gcrypt.h>
/**
- * Used in TALER_AgeCommitmentHash_isNullOrZero for comparison
- */
-const struct TALER_AgeCommitmentHash TALER_ZeroAgeCommitmentHash = {0};
-
-/**
* Function called by libgcrypt on serious errors.
* Prints an error message and aborts the process.
*
@@ -426,19 +421,23 @@ TALER_coin_pub_hash (const struct TALER_CoinSpendPublicKeyP *coin_pub,
{
/* Coin comes with age commitment. Take the hash of the age commitment
* into account */
- const size_t key_s = sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey);
- const size_t age_s = sizeof(struct TALER_AgeCommitmentHash);
- char data[key_s + age_s];
-
- GNUNET_memcpy (&data[0],
- &coin_pub->eddsa_pub,
- key_s);
- GNUNET_memcpy (&data[key_s],
- ach,
- age_s);
- GNUNET_CRYPTO_hash (&data,
- key_s + age_s,
- &coin_h->hash);
+ struct GNUNET_HashContext *hash_context;
+
+ hash_context = GNUNET_CRYPTO_hash_context_start ();
+
+ GNUNET_CRYPTO_hash_context_read (
+ hash_context,
+ &coin_pub->eddsa_pub,
+ sizeof(struct GNUNET_CRYPTO_EcdsaPublicKey));
+
+ GNUNET_CRYPTO_hash_context_read (
+ hash_context,
+ ach,
+ sizeof(struct TALER_AgeCommitmentHash));
+
+ GNUNET_CRYPTO_hash_context_finish (
+ hash_context,
+ &coin_h->hash);
}
}