taler-docs

Documentation for GNU Taler components, APIs and protocols
Log | Files | Refs | README | LICENSE

api-sync.rst (18904B)


      1 ..
      2   This file is part of GNU TALER.
      3   Copyright (C) 2018-2021 Taler Systems SA
      4 
      5   TALER is free software; you can redistribute it and/or modify it under the
      6   terms of the GNU Affero General Public License as published by the Free Software
      7   Foundation; either version 3.0, or (at your option) any later version.
      8 
      9   TALER is distributed in the hope that it will be useful, but WITHOUT ANY
     10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     11   A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more details.
     12 
     13   You should have received a copy of the GNU Affero General Public License along with
     14   TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
     15 
     16   @author Christian Grothoff
     17 
     18 .. _sync-api:
     19 
     20 ======================================
     21 Backup and Synchronization RESTful API
     22 ======================================
     23 
     24 The backup and synchronization service uses an EdDSA key
     25 to identify the "account" of the user.  The key is Crockford
     26 Base32-encoded in the URI to access the data and used to sign requests
     27 as well as to encrypt the contents (see below).  These signatures are
     28 provided in detached form as HTTP headers.
     29 
     30 Once the user activates backup or synchronization, the client should
     31 display the key as a QR code as well as in text format together
     32 with the synchronization service's URL and ask the user to print this
     33 key material and keep it safe.
     34 
     35 The actual format of the backup is not relevant for the
     36 backup and synchronization service, as the service must only ever see
     37 a padded and encrypted version of the data.
     38 
     39 However, there are a few general rules that will apply to
     40 any version of the backup.  Still, except for the
     41 32-byte minimum upload size, the synchronization service
     42 itself cannot enforce these rules.
     43 
     44 *  First, the database should be compressed (i.e. gzip), then
     45    padded to a power of 2 in kilobytes or a multiple of
     46    megabytes, then encrypted and finally protected with
     47    an HDKF.
     48 *  The encryption should use an SHA-512 nonce which
     49    is prefixed to the actual database, and combined with
     50    the master key to create the encryption symmetric secret.
     51    With every revision of the backup (but only real
     52    revisions or merge operations), a fresh nonce must be
     53    used to ensure that the symmetric secret differs every
     54    time.  HKDFs are used to derive symmetric key material
     55    for authenticated encryption (encrypt-then-mac or a
     56    modern AEAD-cipher like Keccak).  Given that AES is more
     57    easily available and will likely increase the code of
     58    the wallet less, AES plus a SHA-512 HMAC should suffice
     59    for now.
     60 *  The client must enable merging databases in a way that is
     61    associative and commutative.  For most activities, this implies
     62    merging lists, applying expirations, dropping duplicates and
     63    sorting the result.  For deletions (operations by which the user
     64    removed records prior to their scheduled expiration), it means
     65    keeping a summarizing log of all deletion operations and applying
     66    the deletions after each merge.  A summarizing log of a deletion
     67    operation would combine two deletion operations of the form
     68    "delete all transactions smaller than amount X before time T" and
     69    "delete all transactions smaller than amount Y before time T"
     70    into "delete all transactions smaller than amount max(X,Y) before
     71    time T".  Similar summarizations should be applied to all
     72    deletion operations supported by the client.  Deletion operations
     73    themselves are associated with an expiration time reflecting the
     74    expiration of the longest lasting record that they explicitly
     75    deleted.
     76    Purchases do not have an expiration time, thus they create
     77    a challenge if an individual purchase is deleted. Thus, when
     78    an individual purchase is deleted, the client is to keep track
     79    of the deletion with a deletion record. The deletion record
     80    still includes the purchase amount and purchase date.  Thus,
     81    when purchases are deleted "in bulk" in a way that would have
     82    covered the individual deletion, such deletion records may
     83    still be subsumed by a more general deletion clause.  In addition
     84    to the date and amount, the deletion record should only contain
     85    a salted hash of the original purchase record's primary key,
     86    so as to minimize information leakage.
     87 *  The database should contain a "last modified" timestamp to ensure
     88    we do not go backwards in time if the synchronization service is
     89    malicious.  Merging two databases means taking the max of the
     90    "last modified" timestamps, not setting it to the current time.
     91    The client should reject a "fast forward" database update if the
     92    result would imply going back in time.  If the client receives a
     93    database with a timestamp into the future, it must still
     94    increment it by the smallest possible amount when uploading an
     95    update.
     96 *  In general, the merge operation should be implemented in such a way
     97    that it deals gracefully with adversarial devices from rogue
     98    devices connected to the same account.
     99 
    100 It is assumed that the synchronization service is only ever accessed
    101 over TLS, and that the synchronization service is trusted to not build
    102 user's location profiles by linking client IP addresses and client
    103 keys.
    104 
    105 .. contents:: Table of Contents
    106   :local:
    107 
    108 
    109 ---------------
    110 Version History
    111 ---------------
    112 
    113 The current protocol version is **v2**.
    114 
    115 * No components use Sync at this point, so there are no dependencies.
    116 
    117 **Version history:**
    118 
    119 * ``v2``: add the ``implementation`` field to ``/config``
    120 
    121 **Upcoming versions:**
    122 
    123 * ``vBLOBS``: changes for blob backups
    124 * ``vBACKUP``: changes for incremental backups
    125 
    126 **Ideas for future version:**
    127 
    128 * ``vXXX``: marker for features not yet targeted for release
    129 
    130 .. include:: tos.rst
    131 
    132 -----------------------
    133 Receiving Configuration
    134 -----------------------
    135 
    136 .. http:get:: /config
    137 
    138   Obtain the key configuration settings of the storage service.
    139 
    140   **Response:**
    141 
    142   Returns a `SyncTermsOfServiceResponse`.
    143 
    144   .. ts:def:: SyncTermsOfServiceResponse
    145 
    146     interface SyncTermsOfServiceResponse {
    147       // Name of the service
    148       name: "sync";
    149 
    150       // Maximum backup size supported.
    151       storage_limit_in_megabytes: Integer;
    152 
    153       // Fee for an account, per year.
    154       annual_fee: Amount;
    155 
    156       // Maximum liability of the provider in case of data loss.
    157       liability_limit: Amount;
    158 
    159       // libtool-style representation of the Sync protocol version, see
    160       // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
    161       // The format is "current:revision:age".
    162       version: string;
    163 
    164       // Release version of the source code.
    165       // The format is MAJOR.MINOR.MICOR[-GITDATA]
    166       // and generally follows the "-v" option of the codebase.
    167       build_version: string;
    168 
    169       // URN of the implementation (needed to interpret 'revision' in version).
    170       // @since **v2**, may become mandatory in the future.
    171       implementation?: string;
    172 
    173     }
    174 
    175 .. _sync:
    176 
    177 ----------------------
    178 Recovering Backup Data
    179 ----------------------
    180 
    181 .. http:get:: /backups/${ACCOUNT-KEY}
    182 
    183   Download latest version of the backup.
    184   The returned headers must include "Etags" based on
    185   the hash of the (encrypted) database. The server must
    186   check the client's caching headers and only return the
    187   full database if it has changed since the last request
    188   of the client.
    189 
    190   This method is generally only performed once per device
    191   when the private key and URL of a synchronization service are
    192   first given to the client on the respective device.  Once a
    193   client has made a backup, it should always use the POST method.
    194 
    195   A signature is not required, as (1) the account-key should
    196   be reasonably private and thus unauthorized users should not
    197   know how to produce the correct request, and (2) the
    198   information returned is encrypted to the private key anyway
    199   and thus virtually useless even to an attacker who somehow
    200   managed to obtain the public key.
    201 
    202   **Response**
    203 
    204   :http:statuscode:`200 OK`:
    205     The body contains the current version of the backup
    206     as known to the server.
    207 
    208   :http:statuscode:`204 No content`:
    209     This is a fresh account, no previous backup data exists at
    210     the server.
    211 
    212   :http:statuscode:`304 Not modified`:
    213     The version available at the server is identical to that
    214     specified in the ``If-None-Match`` header.
    215 
    216   :http:statuscode:`404 Not found`:
    217     The backup service is unaware of a matching account.
    218 
    219   :http:statuscode:`410 Gone`:
    220     The backup service has closed operations.  The body will
    221     contain the latest version still available at the server.
    222     The body may be empty if no version is available.
    223     The user should be urged to find another provider.
    224 
    225   :http:statuscode:`429 Too many requests`:
    226     This account has exceeded thresholds for the number of
    227     requests.  The client should try again later, and may want
    228     to decrease its synchronization frequency.
    229 
    230   .. note::
    231 
    232     "200 OK" responses include an HTTP header
    233     "Sync-Signature" with the signature of the
    234     client from the original upload, and an
    235     "Sync-Previous" with the version that was
    236     being updated (unless this is the first revision).
    237     "Sync-Previous" is only given to enable
    238     signature validation.
    239 
    240 
    241 ---------------------
    242 Uploading Backup Data
    243 ---------------------
    244 
    245 .. http:post:: /backups/${ACCOUNT-KEY}
    246 
    247   Upload a new version of the account's database, or download the
    248   latest version.  The request SHOULD include the ``Expect: 100 Continue``
    249   header.  The client then SHOULD wait for ``100 Continue`` before proceeding
    250   with the upload, regardless of the size of the upload.
    251 
    252   **Request**
    253 
    254   The request must include a ``If-Match`` header indicating the latest
    255   version of the account's database known to the client.  If the server
    256   knows a more recent version, it will respond with a ``409 conflict``
    257   and return the server's version in the response.  The client must
    258   then merge the two versions before retrying the upload.  Note that
    259   a ``409 Conflict`` response will typically be given before the upload,
    260   (instead of ``100 continue``), but may also be given after the upload,
    261   for example due to concurrent activities from other accounts on the
    262   same account!
    263 
    264   The request MUST also include an "Sync-Signature" signing
    265   the ``If-Match`` SHA-512 value and the SHA-512 hash of the body with
    266   the account private key.
    267 
    268   Finally, the SHA-512 hash of the body MUST also be given in an
    269   ``If-None-Match`` header of the request (so that the signature can be verified
    270   before the upload is allowed to proceed).
    271 
    272   The uploaded body must have at least 32 bytes of payload (see
    273   suggested upload format beginning with an ephemeral key).
    274 
    275   :query paying:
    276      Optional argument providing an order identifier.
    277      The client is promising that it is already paying on a
    278      related order. This will cause the
    279      server to delay processing until the respective payment
    280      has arrived (if the operation requires a payment). Useful
    281      if the server previously returned a ``402 Payment required``
    282      and the client wants to proceed as soon as the payment
    283      went through.
    284   :query pay:
    285      Optional argument, any non-empty value will do,
    286      suggested is ``y`` for ``yes``.
    287      The client insists on making a payment for the respective
    288      account, even if this is not yet required. The server
    289      will respond with a ``402 Payment required``, but only
    290      if the rest of the request is well-formed (account
    291      signature must match).  Clients that do not actually
    292      intend to make a new upload but that only want to pay
    293      may attempt to upload the latest backup again, as this
    294      option will be checked before the ``304 Not modified``
    295      case.
    296   :query fresh:
    297      Optional argument, any non-empty value will do,
    298      suggested is ``y`` for ``yes``.
    299      The client insists on a fresh order to be generated, say
    300      because the one returned before was claimed (but not paid)
    301      by another wallet.
    302 
    303 
    304   **Response**
    305 
    306   :http:statuscode:`204 No content`:
    307     The transfer was successful, and the server has registered
    308     the new version.
    309 
    310   :http:statuscode:`304 Not modified`:
    311     The server is already aware of this version of the client.
    312     Returned before ``100 continue`` to avoid upload.
    313     FIXME: Might be better to use ``412 Precondition Failed`` here
    314     in the future!
    315 
    316   :http:statuscode:`400 Bad request`:
    317     Most likely, the uploaded body is too short (less than 32 bytes).
    318 
    319   :http:statuscode:`402 Payment required`:
    320     The synchronization service requires payment before the
    321     account can continue to be used.  The fulfillment URL
    322     should be the ``/$ACCOUNT-KEY`` URL, but can be safely ignored
    323     by the client.  The contract should be shown to the user
    324     in the canonical dialog, possibly in a fresh tab.
    325 
    326   :http:statuscode:`403 Forbidden`:
    327     The signature is invalid or missing (or body does not match).
    328 
    329   :http:statuscode:`409 Conflict`:
    330     The server has a more recent version than what is given
    331     in ``If-Match``.  The more recent version is returned. The
    332     client should merge the two versions and retry using the
    333     given response's "E-Tag" in the next attempt in ``If-Match``.
    334 
    335   :http:statuscode:`410 Gone`:
    336     The backup service has closed operations.  The body will
    337     contain the latest version still available at the server.
    338     The body may be empty if no version is available.
    339     The user should be urged to find another provider.
    340 
    341   :http:statuscode:`411 Length required`:
    342     The client must specify the ``Content-length`` header before
    343     attempting upload.  While technically optional by the
    344     HTTP specification, the synchronization service may require
    345     the client to provide the length upfront.
    346 
    347   :http:statuscode:`413 Request entity too large`:
    348     The requested upload exceeds the quota for the type of
    349     account.  The client should suggest to the user to
    350     migrate to another backup and synchronization service
    351     (like with ``410 Gone``).
    352 
    353   :http:statuscode:`429 Too many requests`:
    354     This account has exceeded daily thresholds for the number of
    355     requests.  The client should try again later, and may want
    356     to decrease its synchronization frequency.
    357 
    358   .. note::
    359 
    360     Responses with a body include an HTTP header
    361     "Sync-Signature" with the signature of the
    362     client from the original upload, and an
    363     "If-Match" with the version that is
    364     being updated (unless this is the first revision).
    365 
    366 
    367 
    368 ---------------------------
    369 Special constraints for Tor
    370 ---------------------------
    371 
    372 We might introduce the notion of a "constraint" into the client's
    373 database that states that the database is a "Tor wallet".  Then,
    374 synchronizing a "Tor-wallet" with a non-Tor wallet should trigger a
    375 stern warning and require user confirmation (as otherwise
    376 cross-browser synchronization may weaken the security of Tor browser
    377 users).
    378 
    379 
    380 ------------------------------------------------
    381 Discovery of backup and synchronization services
    382 ------------------------------------------------
    383 
    384 The client should keep a list of "default" synchronization services
    385 per currency (by the currency the synchronization service accepts
    386 for payment).  If a synchronization service is entirely free, it
    387 should be kept in a special list that is always available.
    388 
    389 Extending (or shortening) the list of synchronization services should
    390 be possible using the same mechanism that is used to add/remove
    391 auditors or exchanges.
    392 
    393 The client should urge the user to make use of a synchronization
    394 service upon first withdrawal, suggesting one that is free or
    395 accepts payment in the respective currency. If none is available,
    396 the client should warn the user about the lack of available
    397 backups and synchronization and suggest to the user to find a
    398 reasonable service.  Once a synchronization service is selected,
    399 the client should urge the user to print the respective key
    400 material.
    401 
    402 When the client starts the first time on a new device, it should
    403 ask the user if he wants to synchronize with an existing client,
    404 and if so, ask the user to enter the respective key and the
    405 (base) URL of the synchronization service.
    406 
    407 
    408 -------------------------
    409 Synchronization frequency
    410 -------------------------
    411 
    412 Generally, the client should attempt to synchronize at a randomized
    413 time interval between 30 and 300 seconds of being started, unless it
    414 already synchronized less than two hours ago already.  Afterwards,
    415 the client should synchronize every two hours, or after purchases
    416 exceed 5 percent of the last bulk amount that the user withdrew.
    417 In all cases the exact time of synchronization should be randomized
    418 between 30 and 300 seconds of the specified event, both to minimize
    419 obvious correlations and to spread the load.
    420 
    421 If the two hour frequency would exceed half of the rate budget offered
    422 by the synchronization provider, it should be reduced to remain below
    423 that threshold.
    424 
    425 
    426 -------------------------------
    427 Synchronization user experience
    428 -------------------------------
    429 
    430 The menu should include three entries for synchronization:
    431 
    432 * "synchronize" to manually trigger synchronization,
    433   insensitive if no synchronization provider is available
    434 * "export backup configuration" to re-display (and possibly
    435   print) the synchronization and backup parameters (URL and
    436   private key), insensitive if no synchronization
    437   provider is available, and
    438 * "import backup configuration" to:
    439 
    440   * import another device's synchronization options
    441     (by specifying URL and private key, or possibly
    442     scanning a QR code), or
    443   * select a synchronization provider from the list,
    444     including manual specification of a URL; here
    445     confirmation should only be possible if the provider
    446     is free or can be paid for; in this case, the
    447     client should trigger the payment interaction when
    448     the user presses the "select" button.
    449   * a special button to "disable synchronization and backup"
    450 
    451 One usability issue here is that we are asking users to deal with a
    452 private key.  It is likely better to map private keys to trustwords
    453 (PEP-style).  Also, when putting private keys into a QR code, there is
    454 the danger of the QR code being scanned and interpreted as a "public"
    455 URL.  Thus, the QR code should use the schema
    456 ``taler://sync/$SYNC-DOMAIN/$SYNC-PATH#private-key`` where
    457 ``$SYNC-DOMAIN`` is the domainname of the synchronization service and
    458 ``$SYNC-PATH`` the (usually empty) path.  By putting the private key after
    459 ``#``, we may succeed in disclosing the value even to eager Web-ish
    460 interpreters of URLs.  Note that the actual synchronization service
    461 must use the HTTPS protocol, which means we can leave out this prefix.
    462 
    463 
    464 ---------------------------
    465 Web Security Considerations
    466 ---------------------------
    467 
    468 To ensure that the Taler Web extension (and others) can access the
    469 service despite Web "security", all service endpoints must set the
    470 header::
    471 
    472   Access-Control-Allow-Origin: *