summaryrefslogtreecommitdiff
path: root/api-mint.rst
blob: d17fd8d5a9a6a0faa4bdcd6baa1029f75a32010f (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
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
========================
The Mint JSON API
========================

-------
General
-------

  This section describes how certain types of values are
  represented throughout the API.

  * **Timestamps**:
    Timestamps are represented in JSON as a string literal `"\\/Date(x)\\/"`, where `x` is the decimal representation
    of the number of milliseconds past the Unix Epoch (January 1, 1970).  The escaped slash (`\\/`) is interpreted in JSON simply
    as a normal slash, but distinguishes the timestamp from a normal string literal.
  * **Public key**: Public keys are represented using the Ed25519 standard
    compact format (256 bits), converted to Base32Hex (RFC 4648) for
    transmission.
  * **Signatures**: Signatures are transmitted as a JSON object with the following fields:

    * `purpose`: a unique number to state the context in which the signature is to be used in
    * `size`: the number of bytes that were hashed (using SHA-512) to create the signature; note that signatures are always done over a packed, binary representation of the data and not the JSON representations.
    * `r`: R value of the signature (256 bit, in Base32Hex).
    * `s`: S value of the signature (256 bit, in Base32Hex).

    The specific signature scheme in use (blind signature, EdDSA)
    depends on the context and can be derived from the purpose.

  * **Denominations**: Currency denominations are expressed as a JSON object with the following fields:

    * `currency`: name of the currency using ISO 4217 currency code
    * `value`: unsigned 32 bit value in the currency, note that "1" here would correspond to 1 EUR or 1 USD (depending on `currency`), not 1 cent.
    * `fraction`: unsigned 32 bit fractional value (to be added to `value`) representing an additional currency fraction, in units of 1 in one million (1/1000000) of the base currency value.  For example, a fraction of 50000000 (50 million) would correspond to 50 cents.

  * **Large numbers**: Large numbers (typically 256 bits), such as blinding factors and private keys, are transmitted in Base32Hex encoding.

-------------------
Obtaining Mint Keys
-------------------
.. http:get:: /keys

  Get a list of all denomination keys offered by the bank,
  as well as the bank's current online signing key.

  **Response on Success**

  On success, the mint responds with HTTP status code `200 OK`.
  The body of the response contains a JSON object with the following fields:

  * `denoms`: A JSON list of denomination descriptions.  Described below in detail.
  * `denoms_date`: The date when the denomination keys were last updated.
  * `denoms_sig`: A signature over the list of denomination keys and the date.
  * `signing_key`: The mint's current signing key.  Described below in detail.

  A denomination description is a JSON object with the following fields:

  * `value`: Value of the denomination.  An integer, to be interpreted
    relative to the currency provided by the mint.
  * `stamp_start`: timestamp indicating when the denomination key becomes valid.
  * `stamp_expire_withdraw`: timestamp indicating when the denomination key can't
    be used anymore to withdraw new coins.
  * `stamp_expire_deposit`: timestamp indicating when coins of this
    denomination become invalid.
  * `key`: Public key for the denomination.
  * `kappa`: Security parameter for refreshing.
  * `sig`: Signature over the expiration dates, value and the key, created
    with the mint's master key.

  The `signing_key` field contains a JSON object with the following fields:

  * `key`: The actual mint's signing public key.
  * `stamp_expire`: Expiration date for the signing key.
  * `sig`:  Signature over the `key` and `stamp_expire` by the mint master key.

  .. note::

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


------------------
Withdrawal
------------------

When transfering money to the mint via SEPA, the mint records
a *purse*, which stores the remaining money from the transaction and the
customer's withdrawal key for the purse.


.. http:get:: /withdraw/status

  Request information about a purse, including the blinding key that is necessary to
  withdraw a coin.

  :query withdraw_pub: Withdrawal key identifying the purse.

  **Success Response**

  The mint responds with a JSON object containing the following fields:

  * `balance`: Money left in this purse. A list of denominations (in case multiple currencies happen to be in the same purse).
  * `expiration`: Expiration date of the purse.
  * `sig`: Signature of the mint.

  **Error Responses**

  :status 400 Bad Request: The `withdraw_pub` parameter is missing or malformed.

  :status 404 Not Found: The withdrawal key does not belong to a purse known to the mint.


.. http:get:: /withdraw/sign

  Withdraw a coin with a given denomination key.

  :query denom: denomination key
  :query blank: coin's blinded public key
  :query withdraw_pub: withdraw / purse public key
  :query sig: signature, created with the withdrawal key

  **Success Response**:

  :status 200 OK: The request was succesful.

  The response body of a succesful request contains a JSON object with the following fields:

  * `bcsig`: The blindly signed coin.

  **Error Responses**:

  :status 400 Bad Request: A request parameter is missing or malformed.

  :status 402 Payment Required: The balance of the purse is not sufficient to withdraw a coin of the
    indicated denomination.

  :status 401 Unauthorized: The signature is invalid.

  :status 404 Not Found: The blinding key is not known to the mint.

  :status 409 Conflict: A sign request for the same `big_r` has already been sent,
    but with a different `denom` or `blank`.


------------------
Refreshing
------------------

Refreshing creates `n` new coins from `m` old coins, where the sum
of denominations of the new coins must be smaller than the sum of
the old coins' denominations plus a refreshing fee imposed by the mint.

The new coins are linkable from all old coins.

In order group multipe coins, the customer generates a refreshing session key.

.. http:post:: /refresh/melt

  "Melt" coins, marking it for refreshing.  Invalidates the coins.

  The request body must contain a JSON object with the following fields:

  :<json array melt_coins: List of coins to refresh.
  :<json array new_denoms: List of new denominations to order.
  :<json string session_pub: Session public key

  The `melt_coins` field is a list of JSON objects with the following fields:

  :json string coin_pub: Coin public key
  :json string coin_sig: Signature by the coin over the session public key
  :json string denom_pub: Denomination public key
  :json string denom_sig: Signature over the coin public key by the denomination key


  **Success Response**

  :status 200 OK: The request was succesful. In that case, the responst body is a json
    object with `kappa` blind session keys for each new coin.

  **Error Responses**

  :status 400 Bad Request: A request parameter is missing or malformed.
  :status 401 Gone: The coin `coin` has already been refreshed.
  :status 403 Forbidden: Either `csig` or `ssig` is invalid.

.. http:post:: /refresh/commit

  Commit values for the cut-and-choose in the refreshing protocol.
  The request body must be a JSON object with the following fields:

  :<json string session_pub: Session to commit values for
  :<json string session_sig: Signature over the whole commitment
  :<json array coin_evs: For each new coin, `kappa` coin blanks.
  :<json array transfer_pubs: List of transfer public keys
  :<json array new_encs: For each new coin, a list of encryptions (one for each cnc instance)
  :<json array secret_encs: For each cut-and-choose instance, the linking encryption for each old coin

  **Success Response**

  :status 202 Accepted: The mint accepted the commitment, but still needs more commitments.

  The response body contains a JSON object with the following fields:
  TODO..

  **Error Response**

  :status 400 Bad Request: A request parameter is missing or malformed.
  :status 403 Forbidden: The signature `sig` is invalid.
  :status 404 Not Found: The mint does not know the blind key `blindkey` given
    in the request.

.. http:post:: /refresh/reveal

  Reveal previously commited values to the bank.  Request body contains a JSON object with
  the following fields:

  :<json string session_pub: The session public key
  :<json array transfer_privs: Revealed transfer private keys

  **Success Response**

  :status 200 OK: All commitments were revealed successfully.  The mint responds
                  with a JSON of the following type

  :>json array bcsig_list: List of the mint's blind signatures on the ordered
                           new coins.

  :status 202 Accepted: The revealed value was accepted, but the mint requires
                        more reveals.

  **Error Responses**

  If the reveal is incomplete, the JSON object contains:

  :>json array reveal_missing: List of blinding keys with missing reveals from
                               the customer.
  :status 400 Bad Request: Request parameters incomplete or malformed.
  :status 403 Forbidden: The signature `ssig` is invalid.
  :status 404 Not Found: The blinding key is not known to the mint.
  :status 409 Conflict: The revealed value was inconsistent with the commitment.
  :status 410 Gone: A conflict occured, the money is gone.

.. http:get:: /refresh/link

  Link an old key to the refreshed coin.

  :query coin: coin public key
  :query csig: signature by the coin

  **Success Response**

  :status 200 OK: All commitments were revealed successfully.

  The mint responds with a JSON object containing the following fields:

  :>json string `link_secret_enc`: ...
  :>json array enc_list: List of encrypted values for the result coins.
  :>json array tpk_list: List of transfer public keys for the new coins.
  :>json array bscoin_list: List of blind signatures on the new coins.

  **Error Responses**

  :status 400 Bad Request: Request parameters incomplete or malformed.
  :status 403 Forbidden: The signature `csig` is invalid.
  :status 404 Not Found: The coin public key is not known to the bank, or was
                         not involved in a refresh.



--------------------
Locking and Deposit
--------------------

Locking and Deposit operations are requested by a merchant during a transaction.
For locking operation, the merchant has to obtain a lock permission for a coin
from the customer.  Similarly, for deposit operation the merchant has to obtain
deposit permission for the coin from the customer.

.. http:GET:: /lock

  Lock the given coin which is identified by the coin's public key.

  :query C: coin's public key
  :query K: denomination key with which the coin is signed
  :query ubsig: mint's unblinded signature of the coin
  :query t: timestamp indicating the lock expire time
  :query m: transaction id for the transaction between merchant and customer
  :query f: the maximum amount for which the coin has to be locked
  :query M: the public key of the merchant
  :query csig: the signature made by the customer with the coin's private key over
               the parameters `t`, `m`, `f`, `M` and the string `"LOCK"`

  The locking operation may succeed if the coin is not already locked or a
  previous lock for the coin has already expired.

  **Success response**

  :status 200: the operation succeeded

  The mint responds with a JSON object containing the following fields:

  :>json string status: The string constant `LOCK_OK`
  :>json string C: the coin's public key
  :>json integer t: timestamp indicating the lock expire time
  :>json string m: transaction id for the transaction between merchant and customer
  :>json object f: the maximum amount for which the coin has to be locked
  :>json string M: the public key of the merchant
  :>json string sig: the signature made by the mint with the corresponding
           coin's denomination key over the parameters `status`, `C`, `t`, `m`,
           `f`, `M`

  The merchant can then save this JSON object as a proof that the mint has
  agreed to transfer a maximum amount equalling to the locked amount upon a
  successful deposit request (see /deposit).

  **Failure response**

  :status 403: the locking operation has failed because the coin is already
               locked or already refreshed and the same request should not be
               repeated as it will always fail.

  In this case the response contains a proof that the given coin is already
  locked ordeposited.

  If the coin is already locked, then the response contains the existing lock
  object rendered as a JSON object with the following fields:

  :>json string status: the string constant `LOCKED`
  :>json string C: the coin's public key
  :>json integer t: the expiration time of the existing lock
  :>json string m: the transaction ID which locked the coin
  :>json object f: the amount locked for the coin
  :>json string M: the public key of the merchant who locked the coin
  :>json string csig: the signature made by the customer with the coin's private
    key over the parameters `t`, `m`, `f` and `M`

  If the coin has already been refreshed then the mint responds with a JSON
  object with the following fields:

  :>json string status: the string constant `REFRESHED`

  * ... TBD

  :status 404: the coin is not minted by this mint, or it has been expired
  :status 501: the request or one of the query parameters are not valid and the
               response body will contain an error string explaining why they are
               invalid
  :status 503: the mint is currently unavailable; the request can be retried after
               the delay indicated in the Retry-After response header

  In these failures, the response contains an error string describing the reason
  why the request has failed.

.. _deposit:
.. http:POST:: /deposit

  Deposit the given coin and ask the mint to transfer the given amount to the
  merchants bank account.  The request should contain a JSON object with the
  following fields

  :<json string C: coin's public key
  :<json string K: denomination key with which the coin is signed
  :<json string ubsig: mint's unblinded signature of the coin
  :<json string type: the string constant `"DIRECT_DEPOSIT"` or `"INCREMENTAL_DEPOSIT"`
     respectively for direct deposit or incremental deposit type of interaction
     chosen by the customer and the merchant.
  :<json string m: transaction id for the transaction between merchant and customer
  :<json object f: the maximum amount for which the coin has to be locked
  :<json string M: the public key of the merchant
  :<json string H_a: the hash of the contract made between merchant and customer
  :<json string H_wire: the hash of the merchant's payment information `wire`
  :<json string csig: the signature made by the customer with the coin's private key over
     the parameters `type`, `m`, `f`, `M`, `H_a` and, `H_wire`
  :<json object `wire`: this should be a JSON object whose format should comply to one of the
     supported wire transfer formats.  See :ref:`wireformats`

  The deposit operation succeeds if the coin is valid for making a deposit and
  is not already deposited or refreshed.

  **Success response**

  :status 200: the operation succeeded

  The mint responds with a JSON object containing the following fields:

  :>json string status: the string constant `DEPOSIT_OK`
  :>json integer t: the current timestamp
  :>json string deposit_tx: the transaction identifier of the transfer transaction made by the
     mint to deposit money into the merchant's account
  :>json string sig: signature of the mint made over the parameters `status`, `t` and
     `deposit_tx`

  :status 202: the operation is accepted but will take a while to complete;
               check back later for its reponse

  This happens when the mint cannot immediately execute the SEPA transaction.
  The response contains the following fields as part of a JSON object:

  :>json string status: the string contant `DEPOSIT_QUEUED`
  :>json integer t: the current timestamp
  :>json integer retry: timestamp indicating when the result of the request will
             be made available
  :>json string sig: the signature of the mint made over the parameters
           `status`, `t`, and `retry`

  **Failure response**

  :status 403: the deposit operation has failed because the coin has previously
               been deposited or it has been already refreshed; the request
               should not be repeated again

  In case of failure due to the coin being already deposity, the response
  contains a JSON object with the following fields:

  :>json string status: the string constant `DEPOSITED`
  :>json string C: the coin's public key
  :>json string m: ID of the past transaction which corresponding to this deposit
  :>json object f: the amount that has been deposited from this coin
  :>json string M: the public key of the merchant to whom the deposit was earlier made
  :>json string H: the hash of the contract made between the merchant identified by `M`
         and the customer
  :>json string csig: the signature made by the owner of the coin with the coin's private
            key over the parameters `m`, `f`, `M`, `H` and the string `"DEPOSIT"`
  :>json integer t: the timestamp when the deposit was made
  :>json string deposit_tx: the transaction identifier of the SEPA transaction made by the
    mint to deposit money into the merchant's account

  In case if the coin has been already refreshed, the response contains a JSON
  object with the following fields:

  :>json string status: the string constant `REFRESHED`

  * ... TBD

  :status 404: the coin is not minted by this mint, or it has been expired
  :status 501: the request or one of the query parameters are not valid and the
               response body will contain an error string explaining why they are
               invalid
  :status 503: the mint is currently unavailable; the request can be retried after
               the delay indicated in the Retry-After response header

  In these failures the response contains an error string describing the reason
  why the request has failed.

===========================
Binary Blob Specification
===========================
This section specifies the binary representation of messages used in Taler's protocols.
The message formats are given in a C-style pseudocode notation.  In contrast to real C structs,
padding is always specified explicitly, and numeric values are little endian.

.. sourcecode:: c

  struct PublicKey {
    uint8_t v[32];
  };

  struct PrivateKey {
    uint8_t d[32];
  };

  struct Timestamp {
    uint64_t val_us;
  };

  struct Signature {
    uint8_t rs[64];
  };

In our notation, the type of a field can depend on the value of another field.
For the following message, the length of the `payload` array must match the value
of the `size` field.

.. sourcecode:: c

  struct SignedData {
    uint32_t size;
    uint32_t purpose;
    uint8_t payload[size];
  };

  struct Denomination {
    uint32_t value;
    uint32_t fraction;
    uint8_t currency_code[4];
  };


In the subsequent messages, we use the following notation

.. sourcecode:: c

  signed (purpose = SOME_CONSTANT) {
    FIELDS
  } msg;

for signed data (contained in `FIELDS`) with the given purpose.  The `size` field of the
corresponding `struct SignedData` is determined by the size of `FIELDS`.

.. sourcecode:: c

  struct CoinIssue {
    // signed by the master key
    signed (purpose = COIN_ISSUE) {
      struct PublicKey key;
      struct Timestamp stamp_expire_withdraw;
      struct Timestamp stamp_expire_deposit;
      struct Timestamp stamp_start;
      uint32_t kappa;
      uint32_t padding;
      struct Denomination denom;
    };
  };

  struct CoinIssueList {
    // signed by the master key
    signed (purpose = COIN_ISSUE_LIST) {
      uint32_t n;
      struct Timestamp stamp_issue;
      struct CoinIssue coins[n];
      struct PublicKey mint_signing_key;
    };
  };

  struct PurseInformation {
    // signed with the mint signing key
    signed (purpose = PURSE_INFO) {
      struct PublicKey big_r;
      struct Timestamp stamp_expire_purse;
      struct Denomination balance;
      struct Timestamp purse_expiration;
    };
  };

  struct BlindBlankCoin {
    TODO todo;
  };

  struct BlindSignedCoin {
    TODO todo;
  };

  struct SignedCoin {
    TODO todo;
  };

  struct WithdrawRequest {
    // signed with the withdrawal key
    signed (purpose = WITHDRAW_REQUEST) {
      struct PublicKey denom_key;
      struct PublicKey big_r;
      struct BlindBlankCoin blank;
    };
  };

  struct MeltRequest {
    // signed with the coin key
    signed (purpose = MELT_COIN) {
      // signed with the session key
      signed (purpose = MELT_SESSION) {
        SignedCoin coin;
        PublicKey session;
      };
    };
  };

  struct OrderRequest {
    // signed with the session key
    signed (purpose = REFRESH_REQUEST) {
      struct PublicKey denom_key;
      struct PublicKey session;
    };
  };


In the following message, `n` is the number of coins
melted by the customer, and `KAPPA` is a security parameter determined
by the new coin's denomination.

.. sourcecode:: c

  struct OrderResponse {
    signed (purpose = ORDER_RESPONSE) {
      Denomination rest_balance;
      struct {
        PublicKey big_r;
        PublicKey old_coin;
      } challenges[KAPPA * n];
    };
  };

  struct BlindFactor {
    TODO todo;
  };

The `encrypted` block denotes an encrypted message.

.. sourcecode:: c

  struct RefreshEnc {
    encrypted {
      struct BlindFactor bf;
      struct PrivateKey tsk;
      struct PrivateKey csk;
    };
  };

  struct CommitRequest {
    signed (purpose = REFRESH_COMMIT) {
      struct PublicKey tpk;
      struct BlindBlankCoin blank;
      struct RefreshEnc enc;
    };
  };

  struct RevealRequest {
    // FIXME: does this need to be signed?
    struct PublicKey big_r;
    struct BlindFactor bf;
    struct PrivateKey csk;
  };

  struct LinkRequest {
    signed (purpose = REFRESH_LINK) {
      struct PublicKey coin;
    };
  };

  struct LinkResponse {
    uint16_t n;
    struct BlindSignedCoin coins[n];
    struct PublicKey tpks[n];
    struct RefreshEnc encs[n];
  };