donau

Donation authority for GNU Taler (experimental)
Log | Files | Refs | Submodules | README | LICENSE

commit acdadc4f9a67169ae9148918e568b5a0d85a55ad
parent 438402f33dd096c3a6209b2fe4ed808eea6a3930
Author: bohdan-potuzhnyi <bohdan.potuzhnyi@gmail.com>
Date:   Fri,  8 Aug 2025 02:34:13 +0200

very bad function + const charity id + salt hash as func

Diffstat:
Msrc/include/donau_service.h | 25++++++++++++++++++++++---
Msrc/include/donau_testing_lib.h | 2+-
Msrc/lib/donau_api_handle.c | 86++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Msrc/testing/testing_api_cmd_charity_delete.c | 8++++----
Msrc/testing/testing_api_cmd_charity_get.c | 2+-
Msrc/testing/testing_api_cmd_issue_receipts.c | 25++++++++-----------------
6 files changed, 82 insertions(+), 66 deletions(-)

diff --git a/src/include/donau_service.h b/src/include/donau_service.h @@ -412,6 +412,20 @@ DONAU_get_donation_unit_key ( /** + * Compute the salted donor tax-id hash (SHA-512). + * + * @param donor_tax_id cleartext donor tax id (ASCII/UTF-8) + * @param salt ASCII/UTF-8 salt + * @param[out] out_hash buffer of size 512/8 bytes + * @return true on success, false on invalid inputs + */ +bool + DONAU_compute_salted_tax_id_hash (const char *donor_tax_id, + const char *salt, + unsigned char out_hash[512 / 8]); + + +/** * Greedily build a multiset of donation-unit public keys that sums EXACTLY to * @a requested_amount, using donation units from @a keys for the given @a year. * @@ -453,13 +467,18 @@ DONAU_get_donation_unit_key_by_hash ( * @param bkps array of blinded unique donor identifiers * @param num_bkps length of the @a bkps array * @param year year of the donation + * @param[out] sum_out result amount (initialized to zero in @keys->currency) + * @return GNUNET_OK on success; + * GNUNET_NO on invalid input, duplication, year mismatch; + * GNUNET_SYSERR on math errors. */ -const struct TALER_Amount * +enum GNUNET_GenericReturnValue DONAU_get_donation_amount_from_bkps ( const struct DONAU_Keys *keys, const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, - const size_t num_bkps, - const uint64_t year); + size_t num_bkps, + uint64_t year, + struct TALER_Amount *sum_out); /** diff --git a/src/include/donau_testing_lib.h b/src/include/donau_testing_lib.h @@ -205,7 +205,7 @@ TALER_TESTING_get_donau_url ( #define DONAU_TESTING_SIMPLE_TRAITS(op) \ op (charity_priv, const struct DONAU_CharityPrivateKeyP) \ op (charity_pub, const struct DONAU_CharityPublicKeyP) \ - op (charity_id, uint64_t) \ + op (charity_id, const uint64_t) \ op (donau_url, const char) \ op (donau_keys, struct DONAU_Keys) \ op (donor_salt, const char) \ diff --git a/src/lib/donau_api_handle.c b/src/lib/donau_api_handle.c @@ -30,6 +30,7 @@ #include "donau_api_curl_defaults.h" #include "donau_util.h" #include "donau_json_lib.h" +#include <sodium.h> /** @@ -541,6 +542,32 @@ DONAU_get_donation_unit_key_by_hash ( } +bool +DONAU_compute_salted_tax_id_hash (const char *donor_tax_id, + const char *salt, + unsigned char out_hash[512 / 8]) +{ + if ( (NULL == donor_tax_id) || + (NULL == salt) || + (NULL == out_hash) ) + { + GNUNET_break (0); + return false; + } + + crypto_hash_sha512_state st; + crypto_hash_sha512_init (&st); + crypto_hash_sha512_update (&st, + (const unsigned char *) donor_tax_id, + strlen (donor_tax_id)); + crypto_hash_sha512_update (&st, + (const unsigned char *) salt, + strlen (salt)); + crypto_hash_sha512_final (&st, out_hash); + return true; +} + + /** * Local helper for the #DONAU_select_donation_unit_keys_for_amount() */ @@ -564,18 +591,6 @@ du_amount_desc_cmp (const void *a, const void *b) } -/** - * Greedily build a multiset of donation-unit public keys that sums EXACTLY to - * @a requested_amount, using donation units from @a keys for the given @a year. - * - * @param keys Donau keys (must match requested_amount currency) - * @param requested_amount target amount - * @param year only consider donation units for this year - * @param[out] out_keys array of selected public keys (owned by caller) - * @param[out] out_len length of @a out_keys - * @return GNUNET_OK on exact match; GNUNET_NO if exact match not possible; - * GNUNET_SYSERR on invalid input/currency mismatch. - */ enum GNUNET_GenericReturnValue DONAU_select_donation_unit_keys_for_amount ( const struct DONAU_Keys *keys, @@ -711,37 +726,34 @@ DONAU_select_donation_unit_keys_for_amount ( } -// FIXME: this API is bad *and* will leak memory! -// put point to the amount and return GNUNET_GENERIC_return_value -const struct TALER_Amount * +enum GNUNET_GenericReturnValue DONAU_get_donation_amount_from_bkps ( const struct DONAU_Keys *keys, const struct DONAU_BlindedUniqueDonorIdentifierKeyPair *bkps, size_t num_bkps, - uint64_t year) + uint64_t year, + struct TALER_Amount *sum_out) { - struct TALER_Amount *sum; - /* Sanity-checks */ if ( (NULL == keys) || (NULL == bkps) || - (0 == num_bkps) ) + (0 == num_bkps) || + (NULL == sum_out) ) { GNUNET_break (0); - return NULL; + return GNUNET_NO; } + + TALER_amount_set_zero (keys->currency, sum_out); + if (GNUNET_YES == DONAU_check_bkps_duplication (bkps, num_bkps)) { GNUNET_break (0); - return NULL; + return GNUNET_NO; } - sum = GNUNET_new (struct TALER_Amount); - TALER_amount_set_zero (keys->currency, - sum); - for (size_t i = 0; i < num_bkps; i++) { const struct DONAU_DonationUnitInformation *dui = @@ -750,8 +762,7 @@ DONAU_get_donation_amount_from_bkps ( if (NULL == dui) { GNUNET_break (0); - GNUNET_free (sum); - return NULL; + return GNUNET_SYSERR; } if (dui->year != year) { @@ -760,12 +771,11 @@ DONAU_get_donation_amount_from_bkps ( "donation unit is for year %lu\n", (unsigned long) year, (unsigned long) dui->year); - GNUNET_free (sum); - return NULL; + return GNUNET_NO; } - switch (TALER_amount_add (sum, - sum, + switch (TALER_amount_add (sum_out, + sum_out, &dui->value)) { case TALER_AAR_RESULT_POSITIVE: @@ -777,32 +787,28 @@ DONAU_get_donation_amount_from_bkps ( GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Accumulation would go negative\n"); GNUNET_break (0); - GNUNET_free (sum); - return NULL; + return GNUNET_SYSERR; case TALER_AAR_INVALID_RESULT_OVERFLOW: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Accumulation overflow\n"); GNUNET_break (0); - GNUNET_free (sum); - return NULL; + return GNUNET_SYSERR; case TALER_AAR_INVALID_NORMALIZATION_FAILED: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Normalization failed during add\n"); GNUNET_break (0); - GNUNET_free (sum); - return NULL; + return GNUNET_SYSERR; case TALER_AAR_INVALID_CURRENCIES_INCOMPATIBLE: GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Currency mismatch during add\n"); GNUNET_break (0); - GNUNET_free (sum); - return NULL; + return GNUNET_SYSERR; } } - return sum; + return GNUNET_OK; } diff --git a/src/testing/testing_api_cmd_charity_delete.c b/src/testing/testing_api_cmd_charity_delete.c @@ -117,11 +117,11 @@ status_run (void *cls, /* Get charity id from trait */ { const struct TALER_TESTING_Command *charity_post_cmd; - uint64_t *charity_id; + const uint64_t *charity_id; - charity_post_cmd = TALER_TESTING_interpreter_lookup_command (is, - ss-> - charity_reference); + charity_post_cmd = + TALER_TESTING_interpreter_lookup_command (is, + ss->charity_reference); if (GNUNET_OK != TALER_TESTING_get_trait_charity_id (charity_post_cmd, diff --git a/src/testing/testing_api_cmd_charity_get.c b/src/testing/testing_api_cmd_charity_get.c @@ -116,7 +116,7 @@ status_run (void *cls, /* Get charity id from trait */ { const struct TALER_TESTING_Command *charity_post_cmd; - uint64_t *charity_id; + const uint64_t *charity_id; charity_post_cmd = TALER_TESTING_interpreter_lookup_command (is, ss-> diff --git a/src/testing/testing_api_cmd_issue_receipts.c b/src/testing/testing_api_cmd_issue_receipts.c @@ -345,7 +345,7 @@ status_run (void *cls, /* Get charity id and the charity private key from trait */ { const struct TALER_TESTING_Command *charity_post_cmd; - uint64_t *charity_id; + const uint64_t *charity_id; const struct DONAU_CharityPrivateKeyP *charity_priv; @@ -571,7 +571,6 @@ TALER_TESTING_cmd_issue_receipts (const char *label, ss->year = year; ss->charity_reference = charity_reference; ss->expected_response_code = expected_response_code; - ss->num_bkp = 3; ss->uses_cs = uses_cs; ss->donor_salt = (const char*) salt; ss->donor_tax_id = (const char*) donor_tax_id; @@ -586,23 +585,15 @@ TALER_TESTING_cmd_issue_receipts (const char *label, GNUNET_assert (0); } - // use libsodium SHA-512 Hash for compatibility reasons with the Donau Verify app. + if (! DONAU_compute_salted_tax_id_hash (donor_tax_id, + salt, + ss->h_donor_tax_id.hash)) { - crypto_hash_sha512_state state; - size_t tax_length = strlen (donor_tax_id); - size_t salt_length = strlen (salt); - - crypto_hash_sha512_init (&state); - crypto_hash_sha512_update (&state, - (const unsigned char*) donor_tax_id, - tax_length); - crypto_hash_sha512_update (&state, - (const unsigned char*) salt, - salt_length); - GNUNET_static_assert (sizeof (ss->h_donor_tax_id.hash) == 512 / 8); - crypto_hash_sha512_final (&state, - ss->h_donor_tax_id.hash); + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Hash was not received"); + GNUNET_assert (0); } + { struct TALER_TESTING_Command cmd = { .cls = ss,