diff options
-rw-r--r-- | src/exchange/taler-exchange-httpd_age-withdraw_reveal.c | 107 | ||||
-rw-r--r-- | src/include/taler_crypto_lib.h | 9 | ||||
-rw-r--r-- | src/util/crypto.c | 35 |
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); } } |