donau

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

commit 475618382a9741af99dc906cf94a6de257cb2dd3
parent 111f573e63fa5d9a25c3a7f521e8fa3e96028d24
Author: Casaburi Johannes <johannes.casaburi@students.bfh.ch>
Date:   Tue, 16 Apr 2024 21:24:58 +0200

doc fixes, work on submit route, fix format

Diffstat:
Mdoc/flows/protocol/definitions.tex | 2+-
Mdoc/flows/protocol/main.pdf | 0
Mdoc/flows/protocol/main.tex | 54+++++++++++++++++++++++++++---------------------------
Msrc/donau/donau-httpd.c | 44++++++++++++++------------------------------
Msrc/donau/donau-httpd_post-batch-issue.c | 31++++++++++++++++---------------
Msrc/donau/donau-httpd_post-submit-receipts.c | 32++++++++++++++++----------------
Msrc/donau/donau-httpd_submit-receipts.h | 2+-
Msrc/donaudb/pg_insert_issued_receipt.c | 17++++++++---------
Msrc/include/donau_crypto_lib.h | 4++--
Msrc/lib/donau_api_batch_issue_receipts.c | 10+++++-----
Msrc/util/charity_signatures.c | 10++++++----
11 files changed, 96 insertions(+), 110 deletions(-)

diff --git a/doc/flows/protocol/definitions.tex b/doc/flows/protocol/definitions.tex @@ -137,7 +137,7 @@ \begin{displaymath} \sigma := sign(\langle i, \Sigma{\vec{r}}, \texttt{Year}\rangle, D^{priv}) \end{displaymath} - The \textbf{Donation Statement} is the signature over the sum (amount donated) of all the Donation Receitps $\Sigma{\vec{r}}$, that a donor has received from donating throughout the year where $i$ is \textbf{Donor Identifier}. + The \textbf{Donation Statement} is the signature over the sum (amount donated) of all the \textbf{Donation Receitps} $\Sigma{\vec{r}}$, that a donor has received from donating throughout the year where $i$ is the \textbf{Donor Identifier}. These signatures attest the amount donated in a particular year by a specific donor. diff --git a/doc/flows/protocol/main.pdf b/doc/flows/protocol/main.pdf Binary files differ. diff --git a/doc/flows/protocol/main.tex b/doc/flows/protocol/main.tex @@ -72,21 +72,21 @@ \emph{In our example, there are $3$ \textbf{Unique Donor Identifiers}: one per \textbf{Donation Unit}}. \footnote{If one Donation Unit is present more than once, then there is more than one Unique Donor Identifier required for said Donation Unit. This depends upon the offered Donation Units.} - \begin{align} + \begin{align*} i :&= H(\texttt{TAXID, S})\\\\ u_1 :&= \langle i, \texttt{N}_1 \rangle \\ u_2 :&= \langle i, \texttt{N}_2 \rangle \\ u_3 :&= \langle i, \texttt{N}_3 \rangle - \end{align} + \end{align*} where $S$ is the salt and $N$ a Nonce. \item The donor blinds the \textbf{Unique Donor Identifiers} using a \emph{different} blinding factor $b$ for every \textbf{Unique Donor Identifier}. - \begin{align} + \begin{align*} \overline u_1 :&= blind (u_1, b_1, K_1^{pub}) \\ \overline u_2 :&= blind (u_2, b_2, K_2^{pub}) \\ \overline u_3 :&= blind (u_3, b_3, K_4^{pub}) - \end{align} + \end{align*} \item So far, the \textbf{Unique Donor Identifiers} do not carry information about their value. The \emph{intended effective value is now indicated} by grouping each \textbf{Unique Donor Identifier} with the according hash of the \textbf{Donation Unit} public key $K^{pub}_x$. @@ -96,16 +96,16 @@ \emph{Note: The public key is not in relation with the sequential index of the \textbf{BKP}, it only relates to the value of the pair!} - \begin{align} + \begin{align*} \overline \mu_1 :&= \langle \overline u_1, h({K^{pub}_1}) \rangle \\ \overline \mu_2 :&= \langle \overline u_2, h({K^{pub}_2}) \rangle \\ \overline \mu_3 :&= \langle \overline u_3, h({K^{pub}_4}) \rangle - \end{align} - \begin{align} + \end{align*} + \begin{align*} \vec{\mu} :&= \langle \overline \mu_1, \overline \mu_2,\overline \mu_3 \rangle - \end{align} + \end{align*} \item The donor sends all \textbf{BKP}'s $\vec{\mu}$ as well as the corresponding \textbf{payment} to the charity. \end{enumerate} @@ -116,9 +116,9 @@ \item The charity signs (using EdDSA) a structure containing all unsigned $BKP$'s coming from the donor. - \begin{align} + \begin{align*} \sigma_c = sign(\vec{\mu}, C^{priv}) - \end{align} + \end{align*} \item The charity sends this structure $\vec{\mu}$ and the signature $\sigma_c$ to the Donau. \end{enumerate} @@ -129,19 +129,19 @@ \begin{enumerate} \item verifies the signature $\sigma_c$ on the structure. - \begin{align} + \begin{align*} verify(\vec{\mu},\sigma_c, C^{pub}) - \end{align} + \end{align*} \item increments the current amount of donations received per year of the charity. This value is increased by the total amount of the \textbf{Blinded Unique Donor Identifier (BUDI)}'s, if the increment does not exceed the annual limit. \item blind signs all the \textbf{BUDI}'s using the \textbf{Donation Unit} private keys $K_x^{priv}$ matching the public keys used in the hash $h(K^{pub})$ which was inturn used in the \textbf{BKP}'s. - \begin{align} + \begin{align*} \overline{\beta_1} = blind\_sign(\overline u_1, K_1^{priv}) \\ \overline{\beta_2} = blind\_sign(\overline u_2, K_2^{priv}) \\ \overline{\beta_3} = blind\_sign(\overline u_3, K_4^{priv}) - \end{align} + \end{align*} \item sends back all created blind signatures $\overline{\beta_1}, \overline{\beta_2}, \overline{\beta_3}$ to the charity. @@ -151,32 +151,32 @@ \item The donor verifies the signatures. - \begin{align} + \begin{align*} verify\_blind(u_1,\overline{\beta_1}, K_1^{pub}) \\ verify\_blind(u_2,\overline{\beta_2}, K_2^{pub}) \\ verify\_blind(u_3,\overline{\beta_3}, K_4^{pub}) - \end{align} + \end{align*} \item The donor unblinds the signatures of the \textbf{BUDI}'s to get the signatures of the \textbf{Unique Donor Identifier (UDI)}'s. This results in a collection of \textbf{Donation Receipt (DR)}'s each consisting of the \textbf{UDI}, the signature $\beta$ and the hash of the \textbf{Donation Unit} public key $h(K_x^{pub})$. - \begin{align} + \begin{align*} \beta_1 &= unblind(\overline{\beta_1}, b_1, K_1^{pub}) \\ \beta_2 &= unblind(\overline{\beta_2}, b_2, K_2^{pub}) \\ \beta_3 &= unblind(\overline{\beta_3}, b_3, K_4^{pub}) - \end{align} - \begin{align} + \end{align*} + \begin{align*} r_1 &= \langle UDI_1, \beta_1, h(K_1^{pub}) \rangle \\ r_2 &= \langle UDI_2, \beta_2, h(K_2^{pub}) \rangle \\ r_3 &= \langle UDI_3, \beta_3, h(K_4^{pub}) \rangle - \end{align} + \end{align*} \end{enumerate} \subsection{After effective tax period: get tax statement for period from Donau} \subsubsection{Donor sends the \textbf{Donation Receipts} to the Donau to get the final \textbf{Donation Statement}.} \begin{enumerate} - \item The donor sends the collection of all \textbf{Donation Receipts} $\{r_1, r_2, r_3\}$ to the Donau. This happens textbf{manually} once per period. + \item The donor sends the collection of all \textbf{Donation Receipts} $\{r_1, r_2, r_3\}$ to the Donau. This happens \textbf{manually} once per period. It is not done continuously to obtain \emph{unlinkability} between the \emph{issuance} of the \textbf{Donation Receipts} (which happens upon donation) and their \emph{submission} for the \textbf{Donation Statement}. @@ -195,24 +195,24 @@ This results in a final signature called the \textbf{Donation Statement}. - \begin{align} + \begin{align*} \sigma_s = sign(\langle i, \texttt{amount}_{Total}, \texttt{year}) \rangle, D^{priv}) - \end{align} + \end{align*} \end{enumerate} \subsubsection{Donor sends the QR Code to a validator (e.g. tax office)} \begin{enumerate} \item The donor generates a QR code which contains the following: - \begin{align} + \begin{align*} \texttt{QR} = \langle \texttt{taxid}, \texttt{salt}, \texttt{year}, \texttt{amount}, \text{$\sigma_s$} \rangle - \end{align} + \end{align*} \item The validator scans the QR code and verifies the \textbf{Donation Statement} $\sigma_s$. - \begin{align} + \begin{align*} verify(\langle i, \texttt{amount}_{Total}, \texttt{year}) \rangle,\sigma_s, D^{pub}) - \end{align} + \end{align*} \end{enumerate} diff --git a/src/donau/donau-httpd.c b/src/donau/donau-httpd.c @@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2014-2023 Taler Systems SA + Copyright (C) 2024 Taler Systems SA TALER is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software @@ -16,9 +16,7 @@ /** * @file donau-httpd.c * @brief Serve the HTTP interface of the donau - * @author Florian Dold - * @author Benedikt Mueller - * @author Christian Grothoff + * @author Johannes Casaburi */ #include <taler/platform.h> #include <gnunet/gnunet_util_lib.h> @@ -35,6 +33,7 @@ #include "donau-httpd_keys.h" #include "donau-httpd_charity.h" #include "donau-httpd_batch-issue.h" +#include "donau-httpd_submit-receipts.h" #include "donau-httpd_history.h" #include "donau-httpd_terms.h" #include "donaudb_plugin.h" @@ -505,12 +504,14 @@ handle_mhd_request (void *cls, .nargs = 1, .nargs_is_upper_bound = true }, - /** - etc - - Add routes here (also make sure to add the - corresponding lines in the makefile) - */ + /* POST submitted receipts */ + { + .url = "submit", + .method = MHD_HTTP_METHOD_POST, + .handler.post = &DH_handler_submit_receipts_post, + .nargs = 1, + .nargs_is_upper_bound = true + }, /* mark end of list */ { .url = NULL @@ -746,18 +747,6 @@ donau_serve_process_config (void) req_max = ULLONG_MAX; } - // if (GNUNET_OK != - // GNUNET_CONFIGURATION_get_value_time (DH_cfg, - // "donau", - // "MAX_KEYS_CACHING", - // &DH_max_keys_caching)) - // { - // GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - // "donau", - // "MAX_KEYS_CACHING", - // "valid relative time expected"); - // return GNUNET_SYSERR; - // } if (GNUNET_OK != TALER_config_get_currency (DH_cfg, &DH_currency)) @@ -767,6 +756,7 @@ donau_serve_process_config (void) "CURRENCY"); return GNUNET_SYSERR; } + { unsigned long long cfd; @@ -906,7 +896,6 @@ do_shutdown (void *cls) GNUNET_CURL_gnunet_rc_destroy (donau_curl_rc); donau_curl_rc = NULL; } - // TALER_TEMPLATING_done (); } @@ -944,6 +933,7 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } + if (GNUNET_OK != DH_keys_init ()) { @@ -951,13 +941,7 @@ run (void *cls, GNUNET_SCHEDULER_shutdown (); return; } - // if (GNUNET_OK != - // TALER_TEMPLATING_init ("donau")) - // { - // global_ret = EXIT_FAILURE; - // GNUNET_SCHEDULER_shutdown (); - // return; - // } + if (GNUNET_SYSERR == DH_plugin->preflight (DH_plugin->cls)) { diff --git a/src/donau/donau-httpd_post-batch-issue.c b/src/donau/donau-httpd_post-batch-issue.c @@ -35,7 +35,6 @@ #include "donau-httpd_keys.h" - /** * Parse a bkp encoded in JSON. * @@ -165,8 +164,8 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, bkps = GNUNET_new_array - (num_bkps, - struct DONAU_BlindedUniqueDonationIdentifierKeyPair); + (num_bkps, + struct DONAU_BlindedUniqueDonationIdentifierKeyPair); json_array_foreach (budikeypairs, index, bkp_obj) { if (GNUNET_SYSERR == @@ -223,10 +222,10 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, "got charity from db!\n"); /* verify charity signature */ if (GNUNET_OK != - DONAU_charity_budi_key_pair_verify (num_bkps, - bkps, - &charity_meta.charity_pub, - &charity_sig)) + DONAU_charity_bkp_verify (num_bkps, + bkps, + &charity_meta.charity_pub, + &charity_sig)) { GNUNET_break_op (0); return TALER_MHD_reply_with_error ( @@ -253,15 +252,16 @@ DH_handler_issue_receipts_post (struct DH_RequestContext *rc, &bkps[i].h_donation_unit_pub, sizeof (bkps[i].h_donation_unit_pub)); GNUNET_CRYPTO_hash_context_read (hc, - bkps[i].blinded_udi.blinded_message, - sizeof (bkps[i].blinded_udi.blinded_message)); + bkps[i].blinded_udi.blinded_message, + sizeof (bkps[i].blinded_udi.blinded_message + )); } GNUNET_CRYPTO_hash_context_read (hc, - &charity_sig, - sizeof (struct DONAU_CharitySignatureP)); + &charity_sig, + sizeof (struct DONAU_CharitySignatureP)); GNUNET_CRYPTO_hash_context_read (hc, - &year, - sizeof (uint64_t)); + &year, + sizeof (uint64_t)); GNUNET_CRYPTO_hash_context_finish (hc, &h_receipts.hash); @@ -345,8 +345,9 @@ start: bkps_sign_data[i].h_donation_unit_pub = &bkps[i].h_donation_unit_pub; bkps_sign_data[i].budi = &bkps[i].blinded_udi; } - if (TALER_EC_NONE != DH_keys_donation_unit_batch_sign (num_bkps, bkps_sign_data, - du_sigs)) + if (TALER_EC_NONE != DH_keys_donation_unit_batch_sign (num_bkps, + bkps_sign_data, + du_sigs)) return TALER_MHD_reply_with_error (rc->connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, // TODO:other EC diff --git a/src/donau/donau-httpd_post-submit-receipts.c b/src/donau/donau-httpd_post-submit-receipts.c @@ -66,15 +66,15 @@ insert_submitted_receipt (void *cls, struct MHD_Connection *connection, MHD_RESULT *mhd_ret) { - struct InsertReceiptContext *icc = cls; + struct InsertReceiptContext *irc = cls; enum GNUNET_DB_QueryStatus qs; qs = DH_plugin->insert_submitted_receipt (DH_plugin->cls, - icc->h_tax_number, - icc->nonce, - icc->donation_unit_pub, - icc->donau_sig, - icc->donation_year); + irc->h_tax_number, + irc->nonce, + irc->donation_unit_pub, + irc->donau_sig, + irc->donation_year); if (qs <= 0) { if (GNUNET_DB_STATUS_SOFT_ERROR != qs) @@ -94,23 +94,23 @@ insert_submitted_receipt (void *cls, MHD_RESULT -DH_handler_submit_receipt_post (struct DH_RequestContext *rc, - const json_t *root, - const char *const args[]) +DH_handler_submit_receipts_post (struct DH_RequestContext *rc, + const json_t *root, + const char *const args[]) { - struct InsertReceiptContext icc; + struct InsertReceiptContext irc; struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_fixed_auto ("h_tax_number", - &icc.h_tax_number), + &irc.h_tax_number), GNUNET_JSON_spec_fixed_auto ("nonce", - &icc.nonce), + &irc.nonce), GNUNET_JSON_spec_fixed_auto ("donation_unit_pub", - &icc.donation_unit_pub), + &irc.donation_unit_pub), GNUNET_JSON_spec_fixed_auto ("donau_sig", - &icc.donau_sig), + &irc.donau_sig), GNUNET_JSON_spec_uint64 ("donation_year", - &icc.donation_year), + &irc.donation_year), GNUNET_JSON_spec_end () }; @@ -138,7 +138,7 @@ DH_handler_submit_receipt_post (struct DH_RequestContext *rc, DH_MT_REQUEST_OTHER, &mhd_ret, &insert_submitted_receipt, - &icc)) + &irc)) { return mhd_ret; } diff --git a/src/donau/donau-httpd_submit-receipts.h b/src/donau/donau-httpd_submit-receipts.h @@ -33,7 +33,7 @@ * @return MHD result code */ MHD_RESULT -DH_handler_submit_receipt_post ( +DH_handler_submit_receipts_post ( struct DH_RequestContext *rc, const json_t *root, const char *const args[]); diff --git a/src/donaudb/pg_insert_issued_receipt.c b/src/donaudb/pg_insert_issued_receipt.c @@ -30,15 +30,14 @@ #include "donau_pq_lib.h" enum GNUNET_DB_QueryStatus -DH_PG_insert_issued_receipt (void *cls, - const size_t num_blinded_sig, - const struct - DONAU_BlindedDonationUnitSignature signatures[ - num_blinded_sig], - const uint64_t charity_id, - const struct DONAU_DonationReceiptHashP *h_receipt, - const struct TALER_Amount *amount_receipts_request, - const struct TALER_Amount *charity_new_amount) +DH_PG_insert_issued_receipt ( + void *cls, + const size_t num_blinded_sig, + const struct DONAU_BlindedDonationUnitSignature signatures[num_blinded_sig], + const uint64_t charity_id, + const struct DONAU_DonationReceiptHashP *h_receipt, + const struct TALER_Amount *amount_receipts_request, + const struct TALER_Amount *charity_new_amount) { struct PostgresClosure *pc = cls; diff --git a/src/include/donau_crypto_lib.h b/src/include/donau_crypto_lib.h @@ -318,7 +318,7 @@ struct DONAU_BudiHashP * @param[out] charity_sig where to write the signature */ void -DONAU_charity_budi_key_pair_sign ( +DONAU_charity_bkp_sign ( const size_t num_bkp, const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, const struct DONAU_CharityPrivateKeyP *charity_priv, @@ -335,7 +335,7 @@ DONAU_charity_budi_key_pair_sign ( * @return #GNUNET_OK if the signature is valid */ enum GNUNET_GenericReturnValue -DONAU_charity_budi_key_pair_verify ( +DONAU_charity_bkp_verify ( const size_t num_bkp, const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, const struct DONAU_CharityPublicKeyP *charity_pub, diff --git a/src/lib/donau_api_batch_issue_receipts.c b/src/lib/donau_api_batch_issue_receipts.c @@ -195,13 +195,13 @@ DONAU_charity_issue_receipt ( json_t *body; // make signature over budi-key-pair - DONAU_charity_budi_key_pair_sign (num_bkp, bkp, charity_priv, - &birh->charity_sig); + DONAU_charity_bkp_sign (num_bkp, bkp, charity_priv, + &birh->charity_sig); /* FIXME temporary test */ if (GNUNET_OK != - DONAU_charity_budi_key_pair_verify (num_bkp, bkp, - charity_pub, - &birh->charity_sig)) + DONAU_charity_bkp_verify (num_bkp, bkp, + charity_pub, + &birh->charity_sig)) { GNUNET_break_op (0); GNUNET_log (GNUNET_ERROR_TYPE_ERROR, diff --git a/src/util/charity_signatures.c b/src/util/charity_signatures.c @@ -57,7 +57,7 @@ struct DONAU_BudiKeyPairTrackPS GNUNET_NETWORK_STRUCT_END void -DONAU_charity_budi_key_pair_sign ( +DONAU_charity_bkp_sign ( const size_t num_bkp, const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, const struct DONAU_CharityPrivateKeyP *charity_priv, @@ -78,7 +78,8 @@ DONAU_charity_budi_key_pair_sign ( sizeof (bkp[i].h_donation_unit_pub)); GNUNET_CRYPTO_hash_context_read (hc, bkp[i].blinded_udi.blinded_message, - sizeof (bkp[i].blinded_udi.blinded_message)); + sizeof (bkp[i].blinded_udi.blinded_message) + ); } GNUNET_CRYPTO_hash_context_finish (hc, &tps.bkps_hash); @@ -90,7 +91,7 @@ DONAU_charity_budi_key_pair_sign ( enum GNUNET_GenericReturnValue -DONAU_charity_budi_key_pair_verify ( +DONAU_charity_bkp_verify ( const size_t num_bkp, const struct DONAU_BlindedUniqueDonationIdentifierKeyPair *bkp, const struct DONAU_CharityPublicKeyP *charity_pub, @@ -111,7 +112,8 @@ DONAU_charity_budi_key_pair_verify ( sizeof (bkp[i].h_donation_unit_pub)); GNUNET_CRYPTO_hash_context_read (hc, bkp[i].blinded_udi.blinded_message, - sizeof (bkp[i].blinded_udi.blinded_message)); + sizeof (bkp[i].blinded_udi.blinded_message) + ); } GNUNET_CRYPTO_hash_context_finish (hc, &tps.bkps_hash);