summaryrefslogtreecommitdiff
path: root/core/api-donau.rst
blob: 09f644ec33fd42bafeca97c9cf780cf6bfd74c5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
..
  This file is part of GNU TALER.
  Copyright (C) 2014-2023 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
  Foundation; either version 2.1, or (at your option) any later version.

  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License along with
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>

  @author Christian Grothoff
  @author Pius Loosli
  @author Lukas Matyja
  @author Johannes Casaburi

=====================
The Donau RESTful API
=====================

The API specified here follows the :ref:`general conventions <http-common>`
for all details not specified in the individual requests.
The `glossary <https://docs.taler.net/glossary.html#glossary>`_
defines all specific terms used in this section.

.. contents:: Table of Contents
  :local:

.. _donau-overview:

------------
API Overview
------------

This is intended to provide a quick overview of the whole REST API. For a more detailed view of the protocol, see the protocol specification.

The chapters group the families of requests frequently encountered when using the Donau API:

* :ref:`Status information<donau_status>`: get the public signing keys of the Donau, the donation unit key, the Donaus config or some entropy
* :ref:`Issue receipts<donau_issue>`: For use by charities: Issue receipts for blinded unique donor ids.
* :ref:`Submit receipts<donau_submit>`: Receive the receipts and, if valid, add all of it's donation units to the donor total. Returns a signature on the total yearly donation amount, hash of taxid+salt and year.
* :ref:`Charity administration and status information<donau_charity>`:

  * For use by administrators to add/modify a charity
  * For use by charities to get their remaining donation volume

.. include:: tos.rst

.. _donau_status:

----------------------------------------
Donau public keys and status information
----------------------------------------

This API is used by donors and charities to obtain global information about
the Donau, such as online signing keys and available donation units.  This is
typically the first call any Donau client makes, as it returns information
required to process all of the other interactions with the Donau.  The
returned information is secured by signature(s) from the Donau, especially the
long-term offline signing key of the Donau, which clients should cache.

.. http:get:: /keys

  Get a list of all donation units keys offered by the Donau,
  as well as the Donau's current online signing key (used for donation statements).

  **Request:**

  **Response:**

  :http:statuscode:`200 OK`:
    The Donau responds with a `DonauKeysResponse` object. This request should
    virtually always be successful. It only fails if the Donau is misconfigured.

  **Details:**

  .. ts:def:: DonauKeysResponse

    interface DonauKeysResponse {
      // libtool-style representation of the Donau protocol version, see
      // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
      // The format is "current:revision:age".
      version: string;

      // Financial domain this Donau operates for.
      domain: string;

      // The Donau's base URL.
      base_url: string;

      // The Donau's currency.
      currency: string;

      // How many digits should the amounts be rendered
      // with by default. Small capitals should
      // be used to render fractions beyond the number
      // given here (like on gas stations).
      currency_fraction_digits: Integer;

      // Donation Units offered by this Donau
      donation_units: DonationUnitKeyGroup[];

      // The Donau's signing keys.
      signkeys: SignKey[];

    }

  .. ts:def:: DonationUnitKeyGroup

    type DonationUnitKeyGroup =
      | DonationUnitKeyGroupRsa
      | DonationUnitKeyGroupCs;

  .. ts:def:: DonationUnitKeyGroupRsa

    interface DonationUnitKeyGroupRsa extends DonationUnitKeyGroupCommon {
      cipher: "RSA";

      donation_units: ({
        rsa_pub: RsaPublicKey;
      } & DonationUnitKeyCommon)[];
    }

  .. ts:def:: DonationUnitKeyGroupCs

    interface DonationUnitKeyGroupCs extends DonationUnitKeyGroupCommon {
      cipher: "CS";

      donation_units: ({
        cs_pub: Cs25519Point;
      } & DonationUnitKeyCommon)[];
    }

  .. ts:def:: DonationUnitKeyGroupCommon

    // Common attributes for all donation unit groups
    interface DonationUnitKeyGroupCommon {
      // How much was donated based on this donation receipt.
      value: Amount;

    }

  .. ts:def:: DonationUnitKeyCommon

    interface DonationUnitKeyCommon {

      // For which year is this donation unit key valid.
      year: Integer;

      // Set to 'true' if the Donau somehow "lost" the private key. The donation unit was not
      // revoked, but still cannot be used to withdraw receipts at this time (theoretically,
      // the private key could be recovered in the future; receipts signed with the private key
      // remain valid).
      lost?: boolean;
    }

  .. ts:def:: DonationUnitKey

    type DonationUnitKey =
      | RsaDonationUnitKey
      | CSDonationUnitKey;

  .. ts:def:: RsaDonationUnitKey

    interface RsaDonationUnitKey {
      cipher: "RSA";

      // RSA public key
      rsa_public_key: RsaPublicKey;
    }

  .. ts:def:: CSDonationUnitKey

    interface CSDonationUnitKey {
      cipher: "CS";

      // Public key of the donation unit.
      cs_public_key: Cs25519Point;

    }

  A signing key in the ``signkeys`` list is a JSON object with the following fields:

  .. ts:def:: SignKey

    interface SignKey {
      // The actual Donau's EdDSA signing public key.
      key: EddsaPublicKey;

      // Initial validity date for the signing key.
      year: Integer;

    }


  .. note::

    Both the individual donation units *and* the donation units list is signed,
    allowing customers to prove that they received an inconsistent list.

.. http:get:: /seed

  Return an entropy seed. The Donau will return a high-entropy
  value that will differ for every call.  The response is NOT in
  JSON, but simply high-entropy binary data in the HTTP body.
  This API should be used by wallets to guard themselves against
  running on low-entropy (bad PRNG) hardware. Naturally, the entropy
  returned MUST be mixed with locally generated entropy.

.. http:get:: /config

  Return the protocol version, financial domain and currency supported by this
  Donau backend.

  **Response:**

  :http:statuscode:`200 OK`:
    The body is a `DonauVersionResponse`.

  .. ts:def:: DonauVersionResponse

    interface DonauVersionResponse {
      // libtool-style representation of the Donau protocol version, see
      // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
      // The format is "current:revision:age".
      version: string;

      // Name of the protocol.
      name: "taler-donau";

      // Currency supported by this Donau.
      currency: string;

      // Financial domain by this Donau.
      domain: string;

    }


.. _donau_issue:

--------------
Issue receipts
--------------

Inspired by the Taler exchange :ref:`Withdrawal<exchange-withdrawal>`.

This API is used by the charity to obtain valid, attested donation receipts from the Donau.
Use the :ref:`charity GET route<donau_charity_get>` to see the remaining donation volume for the current year.


All incoming `BDID` are recorded under the corresponding charity_id by the Donau.

.. http:POST:: /batch-issue/$CHARITY_ID

  Send in a `IssueReceiptsRequest` and ask the Donau to sign all it's contained `BDID`.

  **Request:** `IssueReceiptsRequest`

  **Response:**

  :http:statuscode:`200 OK`:
    The request was successful, and the response is a `BSDonationReceipts`.
  :http:statuscode:`403 Forbidden`:
    The charity signature is invalid. This response comes with a standard `ErrorDetail` response.
  :http:statuscode:`404 Not found`:
    At least one of the donation unit keys is not known to the Donau. Comes with a `DonationUnitUnknownError`. This suggests a bug in the donor as it should have used current donation unit keys from :ref:`/keys<donau_status>`.
  :http:statuscode:`409 Conflict`:
    The donation volume of the charity is not sufficient to issue donation receipts vor all sent in blinded udids. The response is a `IssueError` object.
  :http:statuscode:`410 Gone`:
    The requested donation unit key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a `DonationUnitExpiredMessage`. Clients must evaluate the error code provided to understand which of the cases this is and handle it accordingly.

  **Details:**

  .. ts:def:: IssueReceiptsRequest

    interface IssueReceiptsRequest {
      charity_signature: EddsaSignature;
      year: Integer;
      bdids: BDID[];
    }

  .. ts:def:: BDID

    interface BDID {
      donau_pub_hash: HashCode;
      taxpayer_blinded_id: BDIDEnvelope;
    }

  .. ts:def:: BDIDEnvelope

    type BDIDEnvelope = RSABDIDEnvelope | CSBDIDEnvelope ;

  .. ts:def:: RSABDIDEnvelope

    interface RSABDIDEnvelope {
      cipher: "RSA" | "RSA+age_restricted";
      rsa_blinded_UDID: string;          // Crockford Base32 encoded
    }

  .. ts:def:: CSBDIDEnvelope

    // For donation unit signatures based on Blind Clause-Schnorr, the UDID
    // consists of the public nonce and two Curve25519 scalars which are two
    // blinded challenges in the Blinded Clause-Schnorr signature scheme.
    // See https://taler.net/papers/cs-thesis.pdf for details.
    interface CSBDIDEnvelope {
      cipher: "CS" | "CS+age_restricted";
      cs_nonce: string;      // Crockford Base32 encoded
      cs_blinded_c0: string; // Crockford Base32 encoded
      cs_blinded_c1: string; // Crockford Base32 encoded
    }

  .. ts:def:: BDIDBlindingKeyP

    // Secret for blinding/unblinding.
    // An RSA blinding secret, which is basically
    // a 256-bit nonce, converted to Crockford Base32.
    type BDIDBlindingKeyP = string;

  .. ts:def:: BSDonationReceipts

    interface DonationReceipts {
      blind_signed_receipt_signatures: DonationReceiptSignature[];
    }

  .. ts:def:: DonationReceiptSignature

  .. ts:def:: BlindedDonationReceiptSignature

    type BlindedDonationReceiptSignature =
      | RSABlindedDonationReceiptSignature
      | CSBlindedDonationReceiptSignature;

  .. ts:def:: RSABlindedDonationReceiptSignature

    interface RSABlindedDonationReceiptSignature {
      cipher: "RSA";

      // (blinded) RSA signature
      blinded_rsa_signature: BlindedRsaSignature;
    }

  .. ts:def:: CSBlindedDonationReceiptSignature

    interface CSBlindedDonationReceiptSignature {
      type: "CS";

      // Signer chosen bit value, 0 or 1, used
      // in Clause Blind Schnorr to make the
      // ROS problem harder.
      b: Integer;

      // Blinded scalar calculated from c_b.
      s: Cs25519Scalar;
    }


    type DonationReceiptSignature = RSADonationReceiptSignature | CSDonationReceiptSignature ;

  .. ts:def:: RSADonationReceiptSignature

    interface RSADonationReceiptSignature {
      cipher: "RSA";
      rsa_blinded_donation_receipt_sig: string;          // Crockford Base32 encoded
    }

  .. ts:def:: CSDonationReceiptSignature

    interface CSDonationReceiptSignature {
      cipher: "CS";
      cs_nonce: string;      // Crockford Base32 encoded
      cs_blinded_c0: string; // Crockford Base32 encoded
      cs_blinded_c1: string; // Crockford Base32 encoded
    }

  .. ts:def:: IssueError

    interface IssueError{
      max_per_year: Amount;
      current_year: Amount;
    }

  .. ts:def:: DonationUnitUnknownError

    interface DonationUnitUnknownError{
      unknown_hash_pub_donation_unit: HashCode[];
      donau_pub: EddsaPublicKey;
      donau_sig: EddsaSignature;
    }

  .. ts:def:: DonationUnitExpiredMessage

    interface DonationUnitExpiredMessage{
      h_donation_unit_pub: HashCode;
      donau_pub: EddsaPublicKey;
      donau_sig: EddsaSignature;
    }

.. _donau_submit:

---------------
Submit receipts
---------------

Inspired by the Taler exchange :ref:`Deposit<deposit-par>`.

.. http:POST:: /submit

  Send in donation receipts for the past fiscal year, receive signed total back.

  **Request:** `SubmitDonationReceiptsRequest`

  **Response:**

  :http:statuscode:`200 OK`:
    The request was successful, and the response is a `SubmitResponse`.
  :http:statuscode:`403 Forbidden`:
    One of the signatures is invalid. This response comes with a standard `ErrorDetail` response.
  :http:statuscode:`404 Not found`:
    At least one of the donation unit keys is not known to the Donau. Comes with a `DonationUnitUnknownError`.
  :http:statuscode:`410 Gone`:
    The requested donation unit key is not yet or no longer valid. It either before the validity start, past the expiration or was revoked. The response is a `DonationUnitExpiredMessage`. Clients must evaluate the error code provided to understand which of the cases this is and handle it accordingly.  FIXME: text does not match our use case well.

  **Details:**

  .. ts:def:: SubmitDonationReceiptsRequest

    interface SubmitDonationReceiptsRequest{
      // hashed taxpayer ID plus salt
      taxnr_hashed: HashCode;
      // All donation receipts must be for this year.
      year: Integer;
      // Receipts should be sorted by amount.
      donation_receipts: DonationReceipt[];
    }

  .. ts:def:: DonationReceipt

    interface DonationReceipt{
      donation_unit_pub_hash: HashCode;
      nonce: string;
      donau_sig: DonationSignature
    }

  .. ts:def:: DonationSignature

    type DonationSignature =
      RsaDonationSignature | CSDonationSignature;

  .. ts:def:: RsaDonationSignature

    interface RsaDonationSignature {
      cipher: "RSA";

      // RSA signature
      rsa_signature: RsaSignature;
    }

  .. ts:def:: CSDonationSignature

    interface CSDonationSignature {
      type: "CS";

      // R value component of the signature.
      cs_signature_r: Cs25519Point;

      // s value component of the signature.
      cs_signature_s: Cs25519Scalar:
    }



  .. ts:def:: SubmitResponse

    interface SubmitResponse{
      // *accepted* total
      total: Amount;
      // signature over taxid_hashed, total, year
      signature: EddsaSignature;
    }

.. _donau_charity:

---------------------------------------------
Charity administration and status information
---------------------------------------------

The administration requests require an authorized bearer token to be set in the HTTP "Authorization" Header. This token can be set by a proxy validating authentication/authorization (using e.g. LDAP).
The GET status requests require an authorized bearer token as well.

.. http:GET::  /charities

  GET all charities. Only allowed if the request comes with the administration bearer token.

  return all charities

  **Request:**

  **Reponse:**

  :http:statuscode:`200 OK`:
    The request was successful, and the response is a `Charities`.

  **Details:**

  .. ts:def:: Charities

    interface Charities{
      charities: CharitySummary[];
    }

  .. ts:def:: CharitySummary

    interface CharitySummary{
      charity_id: Integer;
      name: string;
      max_per_year: Amount;
      receipts_to_date: Amount;
    }

.. _donau_charity_get:

.. http:get:: /charities/$CHARITY_ID

  GET a specific charity. Only allowed if the request comes with the charity or administration bearer token.

  Request information about a charity.

  **Request:**

  **Response:**

  :http:statuscode:`200 OK`:
    The Donau responds with a `Charity` object
  :http:statuscode:`404 Not found`:
    The charity id does not belong to a charity known to the Donau.

  .. ts:def:: Charity

    interface Charity {
      charity_pub: EddsaPublicKey;
      name: string;
      url: string;
      max_per_year: Amount;
      receipts_to_date: Amount;
      current_year: Integer;
    }

.. http:POST:: /charity

  Add a charity. Only allowed if the request comes with the administrator bearer token.

  **Request:** `CharityRequest`

  **Response:**

  **Details:**

  :http:statuscode:`201 Created`:
    The request was successful, and the response is a `CharityResponse`.

  :http:statuscode:`403 Forbidden`:
    The request did not contain an accepted administrator bearer token in it's header.

  .. ts:def:: CharityRequest

    interface CharityRequest{
      charity_pub: EddsaPublicKey;
      name: string;
      url: string;
      max_per_year: Amount;
      receipts_to_date: Amount;
      current_year: Integer;
    }

  .. ts:def:: CharityResponse

    interface CharityResponse{
      id: Integer;
    }


.. http:PATCH:: /charities/{id}

  Modify a charity. Only allowed if the request comes with the administrator bearer token.

  **Request:** `CharityRequest`

  **Response:**

  :http:statuscode:`200 OK`:
    The request was successful.

  :http:statuscode:`403 Forbidden`:
    The request did not contain an accepted administrator bearer token in it's header.


.. http:DELETE:: /charities/{id}

  Delete (or deactivate) a charity. Only allowed if the request comes with the administrator bearer token.

  **Request:**

  **Response:**

  :http:statuscode:`204 No content`:
    The request was successful.

  :http:statuscode:`403 Forbidden`:
    The request did not contain an accepted administrator bearer token in it's header.