implementation.tex (13260B)
1 \section{Implementation}\label{implementation} 2 3 This section describes the current implementation of the Donau, which 4 consists of a REST API, an Android verification app, and the Donau 5 database. The Donau is written in C, as it reuses parts of the 6 codebase from GNU Taler exchange component. The Donau has a similar 7 architecture and uses cryptographic blinded signatures in a similar 8 way as the GNU Taler exchange does. 9 10 On the user side, donation receipts are collected in a wallet; the 11 wallet takes the users taxpayer ID and picks its own salt to create 12 the Donor Identifier \DI. 13 14 \subsection{REST API} \label{rest_api} 15 16 The detailed REST API specification of the Donau back-end is publicly 17 available under the following URL: 18 \url{https://docs.taler.net/core/api-donau.html}. The following are 19 the main API endpoints: 20 21 \subsubsection{\texttt{/keys}} 22 The \texttt{GET /keys} request returns all valid donation unit public keys 23 offered by the Donau, as well as the Donau's current EdDSA public signing key. 24 The following is an example response of a \texttt{curl 127.0.0.1:8080/keys} 25 command. Some parts of the following example responses are truncated (denoted by 26 the three dots '\texttt{...}') to make them more readable. 27 28 \begin{verbatim} 29 { 30 "version": "0:0:0", 31 "base_url": "http://localhost:8080/", 32 "currency": "EUR", 33 "signkeys": [ 34 { 35 "stamp_start": { 36 "t_s": 1717069556 37 }, 38 "stamp_expire": { 39 "t_s": 1718279156 40 }, 41 "key": "CFV2PY8164E231XZSQK30K8R6CBQ..." 42 }, 43 { 44 ... 45 } 46 ], 47 "donation_units": [ 48 { 49 "donation_unit_pub": { 50 "cipher": "RSA", 51 "rsa_public_key": "020000YC7XK99S..." 52 }, 53 "year": 2024, 54 "lost": false, 55 "value": "EUR:5" 56 }, 57 { 58 "donation_unit_pub": { 59 "cipher": "CS", 60 "cs_public_key": "7SKRQGBSEPBG24..." 61 }, 62 "year": 2024, 63 "lost": false, 64 "value": "EUR:1" 65 }, 66 { 67 ... 68 } 69 ] 70 } 71 \end{verbatim} 72 73 \subsubsection{\texttt{/charities}} 74 75 In order for a charity to be able to issue receipts by a specific 76 Donau it must be registered by this Donau. The Donau provides an API 77 to manage charities. By default only the Donau administrator can 78 change the list of registered charities. The charity itself is able 79 to request a donation report to keep track of their total donations in 80 the current year. The response includes the maximum donation amount 81 and the current donated amount for the charity of the current year. 82 83 \begin{figure}[ht] 84 \includegraphics[width=0.5\textwidth]{donau_flow_register_charity} 85 \caption{The tax authority registers a new charity in the Donau. 86 A charity first requests to be added to the Donau, including its Charity EdDSA public key in its request. 87 The tax authority them adds the charity by sending a POST request to the {\tt 88 /charities} endpoint with the relevant data on the charity 89 }\label{fig:donau_flow_register_charity} 90 \end{figure} 91 92 The following is an example response of a \texttt{curl 127.0.0.1:8080/charities} command. 93 There is only one charity named \texttt{example} registered with a donation limit of 10 euros. 94 95 \begin{verbatim} 96 { 97 "charities": [ 98 { 99 "charity_pub": "ABETNXT9ZF606FRF3WD5...", 100 "url": "example.com", 101 "name": "example", 102 "max_per_year": "EUR:10", 103 "receipts_to_date": "EUR:0", 104 "current_year": 2024 105 } 106 ] 107 } 108 \end{verbatim} 109 110 To insert a charity a \texttt{POST} request can be sent using 111 \texttt{curl -d @charity.json -X POST http://127.0.0.1:8080/charities}. 112 113 The following is an example of a 114 \texttt{charity.json} entry 115 116 \begin{verbatim} 117 { 118 "charity_pub": "ABETNXT9ZF606FRF3WD5...", 119 "charity_name": "mycharity", 120 "charity_url": "mycharity.example.com", 121 "max_per_year": "EUR:1000", 122 "receipts_to_date": "EUR:0", 123 "current_year": 2024 124 } 125 \end{verbatim} 126 127 The response consists of the charity ID generated by the database. 128 \begin{verbatim} 129 { 130 "charity-id": 1 131 } 132 \end{verbatim} 133 134 135 \subsubsection{\texttt{/batch-issue}} 136 Only recognized charities are allowed to issue receipts for their donors. 137 A \texttt{POST} issue receipt request includes an array of \texttt{BKP}s. A 138 \texttt{BKP} consists of a \texttt{BUDI} and a hash of a public donation unit 139 key (see section~\ref{notation_and_definitions}). 140 The charity signs the request with its own EdDSA private key. The 141 corresponding public key was given to the Donau in the registration process of 142 the charity. 143 After the Donau checks the signature from the charity it signs the 144 \texttt{BUDI}s with the corresponding donation unit private key. Before the 145 signatures are returned to the charity the Donau saves a hash of the request 146 and all donation unit signatures to detect replays (see section~\ref{donau_database}). 147 148 \begin{figure}[ht] 149 \includegraphics[width=0.5\textwidth]{donau_flow_issue_receipt} 150 \caption{Flow of the issue receipt process} \label{fig:donau_flow_issue_receipt} 151 \end{figure} 152 153 The following is an example response of a \\ 154 \texttt{curl -d @issue.json -X POST http://127.0.0.1:8080/batch-issue/1} 155 request showing a \texttt{issue.json} entry. 156 The number at the end of the URL is the charity ID. 157 158 159 160 \begin{verbatim} 161 { 162 "budikeypairs": [ 163 { 164 "h_donaton_unit_pub": "130C2KDHTAFDQFB8XED...", 165 "blinded_udi": { 166 "cipher": "RSA", 167 "rsa_blinded_identifier": "AXPTEE24W28S9XN..." 168 } 169 } 170 ], 171 "charity_sig": "JEJ0QMDXD416XKSK1SG0DETJEH...", 172 "year": 2024 173 } 174 \end{verbatim} 175 176 \begin{verbatim} 177 { 178 "blind_signatures": [ 179 { 180 "blinded_signature": { 181 "cipher": "RSA", 182 "blinded_rsa_signature": "16XHNWSCDRVKHF..." 183 } 184 } 185 ], 186 "issued_amount: "EUR:15" 187 } 188 \end{verbatim} 189 190 \subsubsection{\texttt{/batch-submit}} 191 The batch-submit route is used by the donor to summarize their donation 192 receipts into one donation statement, which then gets signed by the Donau with 193 their EdDSA signature. 194 The request is composed of the donation receipts (see section~\ref{donau_creates_donation_receipt}), 195 the corresponding year and the Donor Identification \DI, which is the salted hash of the donor's taxpayer ID. 196 When processing the request, the Donau checks the validity of the donation 197 receipts and searches its database for other saved donation receipts made in the requested 198 year. 199 The Donau computes 200 a donation statement, consisting of a signature over 201 the total value of the donation units of all donation receipts of the year, 202 the salted hash of the taxpayer ID, and the current year, 203 and stores this in its database along with the submitted receipts (see section~\ref{donau_database}). 204 205 In our implementation the Donau does not return this donation statement under 206 this call but under the {\tt donation-statement} request, see below. 207 208 The following is an example of a \\ 209 \texttt{curl -d @submit.json -X POST http://127.0.0.1:8080/batch-submit} 210 request. If successful, the Donau returns the \texttt{HTTP 201} status code 211 with an empty response. 212 The following record would be stored. 213 214 \begin{verbatim} 215 { 216 "h_donor_tax_id": "N2NYR2SFNGZSS388R2SB0VK...", 217 "donation_year": 2024, 218 "donation_receipts": [ 219 { 220 "h_donaton_unit_pub": "130C2KDHTAFDQFB8X...", 221 "nonce": "JEQC39G", 222 "donation_unit_sig": 223 { 224 "cipher": "RSA", 225 "rsa_signature": "GQBXPNE4JT5W53T3CVP6E..." 226 } 227 } 228 ] 229 } 230 \end{verbatim} 231 232 \subsubsection{\texttt{/donation-statement}} 233 To obtain the donation statement, the donor submits a GET request for a specified year and taxpayer ID. 234 235 The following is an example response of a \\ 236 \texttt{curl http://127.0.0.1:8080/donation-statement/2024/N2NYR2SFNGZSS388R2SB...} \\ 237 request. 238 239 The last parameter of the URL is the \DI. 240 241 \begin{verbatim} 242 { 243 "total": "EUR:15", 244 "donation_statement": "C1JVDP25AR001W5AHMAZ...", 245 "donau_pub": "63f62b7901311c2187bfcde6304d1..." 246 } 247 \end{verbatim} 248 249 \begin{figure}[ht] 250 \includegraphics[width=0.5\textwidth]{donau_flow_submit_receipt} 251 \caption{Donor requests a donation statement from the Donau} \label{fig:donau_flow_submit_receipt} 252 \end{figure} 253 254 \subsection{Donau client} 255 The REST client removes some of the complexity of sending requests to the Donau 256 server. It converts request parameters into JSON and parses JSON responses into 257 a usable format. 258 259 \subsection{Donau database}\label{donau_database} 260 The Donau database contains five tables as shown in figure~\ref{fig:db_physical_model}. 261 The \texttt{donation\_units} and 262 \texttt{donau\_sign\_keys} table store the keys necessary for signing and 263 creating donation receipts. Donation receipts that are issued to be signed by 264 the donau are stored in the \texttt{receipts\_issued} table while the receipts 265 that are already signed are stored in the \texttt{receipts\_submitted} table. 266 The \texttt{history} table keeps the donation records of the past years. 267 268 \begin{figure}[ht] 269 \includegraphics[width=0.5\textwidth]{db_physical_model} 270 \caption{Donau database model (generated by \url{https://dbdiagram.io/})} \label{fig:db_physical_model} 271 \end{figure} 272 \subsubsection{\tt charities} 273 Each registered charity has an entry in this table. There may be a donation 274 limit imposed by local law which prevents further donations if the limit is 275 reached. 276 277 \begin{itemize} 278 \item \texttt{charity\_id:} Unique ID generated by the database. 279 \item \texttt{charity\_pub:} Charity EdDSA public key 280 \item \texttt{charity\_name:} Name of the charity 281 \item \texttt{charity\_url:} Charity URL 282 \item \texttt{max\_per\_year:} The annual donation limit according to local law. 283 \item \texttt{receipts\_to\_date:} The current amount of donations in the current year. Reset to 0 when incrementing the \texttt{current\_year}. 284 \item \texttt{current\_year:} Current year 285 \end{itemize} 286 287 \subsubsection{\tt donation\_units} 288 Table containing all the valid donation units the Donau knows about. 289 \begin{itemize} 290 \item \texttt{donation\_unit\_serial:} Unique ID generated by the database. 291 \item \texttt{h\_donation\_unit\_pub:} Hash value of the donation unit public key \texttt{donation\_unit\_pub} 292 \item \texttt{donation\_unit\_pub:} The donation unit public key. Is either an RSA or Schnorr public key. 293 \item \texttt{validity\_year:} The year, for which the donation unit is valid. 294 \item \texttt{value:} The amount and currency that this donation unit represents. 295 \end{itemize} 296 297 \subsubsection{\tt donau\_sign\_keys} 298 Contains all Donau EdDSA signing keys. 299 \begin{itemize} 300 \item \texttt{dsk\_serial:} Unique ID generated by the database. 301 \item \texttt{donau\_pub:} Donau EdDSA public key. 302 \item \texttt{valid\_from:} Year the signing key becomes valid. 303 \item \texttt{expire\_sign:} Year the signing key becomes invalid. 304 \item \texttt{expire\_legal:} Year the signing key legally expires. 305 \end{itemize} 306 307 \subsubsection{\tt receipts\_issued} 308 Contains all issued donation receipts sent to the Donau. 309 \begin{itemize} 310 \item \texttt{receipt\_id:} Unique ID generated by the database. 311 \item \texttt{blinded\_sig:} Array of blinded signatures. These are the \texttt{BKP}'s the Donau blind signed. 312 \item \texttt{charity\_id:} The ID of the charity that received the donation. 313 \item \texttt{receipt\_hash:} Hash value over all the blinded donation receipt received plus the hash of the donation units public key. 314 \item \texttt{amount:} The amount and currency this donation receipt contains. 315 \end{itemize} 316 317 \subsubsection{\tt receipts\_submitted} 318 Contains all submitted donation receipts sent to the Donor. By storing the 319 signature \texttt{donation\_unit\_sig}, the idempotence of the API is kept in 320 case the private key is replaced. 321 \begin{itemize} 322 \item \texttt{receipt\_id:} Unique ID generated by the database. 323 \item \texttt{h\_tax\_number:} The hash of the tax number and salt (called 324 $\DI$ in Section~\ref{technical}). 325 \item \texttt{nonce:} The nonce used in the \texttt{Unique Donor Identifier} 326 \item \texttt{donation\_unit\_pub:} Reference to public key used to sign. 327 \item \texttt{donation\_unit\_sig:} The unblinded signature the Donau made. 328 \item \texttt{donation\_year:} The year the donation was made. 329 \end{itemize} 330 331 \subsubsection{\tt history} 332 History of the yearly donations for each charity. This data provides a record 333 of donations each year. It could also provide valuable information that could 334 be used in statistics to analyze general donations over the year. 335 \begin{itemize} 336 \item \texttt{charity\_id:} Unique ID generated by the database. 337 \item \texttt{final\_amount:} The final amount that was donated to the charity 338 \item \texttt{donation\_year:} The year in which the donations where made. 339 \end{itemize} 340 341 \subsection{Android Verification App}\label{android_verification_app} 342 The Android app is part of the verification process used by the tax authority 343 to check the donation statement (see 344 section~\ref{donor_sends_final_statement_to_a_validator}). 345 The app decodes the submitted QR code from the donor, 346 parses the signed values and the signature, 347 and uses them to verify the signature. 348 The arguments of the QR code are defined in section~\ref{donor_sends_final_statement_to_a_validator} 349 and encoded as colon-delimited base64 values: 350 351 \begin{verbatim} 352 YEAR:TOTALAMOUNT:TAXID:TAXIDSALT:ED25519SIGNATURE 353 \end{verbatim} 354 355 Finally, the values and the verification result are displayed.