Generated by Sphinx 3.4.3.

Anastasis Manual
****************

     Anastasis 0.0.0pre0, Jul 18, 2021

     Anastasis SARL

     Copyright © 2020-2021 Anastasis SARL (AGPLv3+ or GFDL 1.3+)

The system will be based on free software and open protocols.

Documentation Overview
**********************

Introduction
============

Anastasis is a service that allows the user to securely deposit a core secret with an open set of escrow providers and recover it if the secret is lost.  The core secret itself is protected from the escrow providers by encrypting it with a master key.  The main objective of Anastasis is to ensure that the user can reliably recover the core secret, while making this difficult for everyone else.  Furthermore, it is assumed that the user is unable to reliably remember any secret with sufficiently high entropy, so we cannot simply encrypt using some other key material in possession of the user.

To uniquely identify users, an “unforgettable” identifier is used.  This identifier should be difficult to guess for anybody but the user. However, the identifier is not expected to have sufficient entropy or secrecy to be cryptographically secure. Examples for such identifier would be a concatenation of the full name of the user and their social security or passport number(s).  For Swiss citizens, the AHV number could also be used.

The adversary model of Anastasis has two types of adversaries: weak adversaries which do not know the user’s identifier, and strong adversaries which somehow do know a user’s identifier.  For weak adversaries the system guarantees full confidentiality.  For strong adversaries, breaking confidentiality additionally requires that Anastasis escrow providers must have colluded.  The user is able to specify a set of policies which determine which Anastasis escrow providers would need to collude to break confidentiality. These policies also set the bar for the user to recover their core secret.

A recovery document includes all of the information a user needs to recover access to their core secret.  It specifies a set of escrow methods, which specify how the user should convince the Anastasis server that they are “real”.  Escrow methods can for example include SMS-based verification, video identification or a security question.  For each escrow method, the Anastasis server is provided with truth, that is data the Anastasis operator may learn during the recovery process to authenticate the user.  Examples for truth would be a phone number (for SMS), a picture of the user (for video identification), or the (hash of) a security answer.  A strong adversary is assumed to be able to learn the truth, while weak adversaries must not.  In addition to a set of escrow methods and associated Anastasis server operators, the recovery document also specifies policies, which describe the combination(s) of the escrow methods that suffice to obtain access to the core secret.  For example, a policy could say that the escrow methods (A and B) suffice, and a second policy may permit (A and C).  A different user may choose to use the policy that (A and B and C) are all required.  Anastasis imposes no limit on the number of policies in a recovery document, or the set of providers or escrow methods involved in guarding a user’s secret.  Weak adversaries must not be able to deduce information about a user’s recovery document (except for its length, which may be exposed to an adversary which monitors the user’s network traffic).

Installation
============

Please install the following packages before proceeding with the exchange compilation.

  - libsqlite3 >= 3.16.2

  - GNU libunistring >= 0.9.3

  - libcurl >= 7.26 (or libgnurl >= 7.26)

  - libqrencode >= 4.0.0

  - GNU libgcrypt >= 1.6

  - libsodium >= 1.0

  - libargon2 >= 20171227

  - libjansson >= 2.7

  - Postgres >= 9.6, including libpq

  - GNU libmicrohttpd >= 0.9.71

  - GNUnet >= 0.14.0 (from source tarball (http://ftpmirror.gnu.org/gnunet/))

  - GNU Taler exchange

  - GNU Taler merchant backend

Except for the last two, these are available in most GNU/Linux distributions and should just be installed using the respective package manager.

Installing from source
----------------------

The following instructions will show how to install libgnunetutil and the GNU Taler exchange from source.

Installing GNUnet
.................

Before you install GNUnet, you must download and install the dependencies mentioned in the previous section, otherwise the build may succeed, but could fail to export some of the tooling required by GNU Taler.

To install GNUnet, unpack the tarball and change into the resulting directory, then proceed as follows:

     $ ./configure [--prefix=GNUNETPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install
     # ldconfig

If you did not specify a prefix, GNUnet will install to /usr/local, which requires you to run the last step as root. The ldconfig command (also run as root) makes the shared object libraries (.so files) visible to the various installed programs.

Installing the Taler Exchange
.............................

After installing GNUnet, unpack the GNU Taler exchange tarball, change into the resulting directory, and proceed as follows:

     $ ./configure [--prefix=EXCHANGEPFX] \
                   [--with-gnunet=GNUNETPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, the exchange will install to /usr/local, which requires you to run the last step as root.  You have to specify --with-gnunet=/usr/local if you installed GNUnet to /usr/local in the previous step.

Installing the Taler Merchant
.............................

GNU Taler merchant has these additional dependencies:

  - libqrencode >= 4.0.0

The following steps assume all dependencies are installed.

First, unpack the GNU Taler merchant tarball and change into the resulting directory. Then, use the following commands to build and install the merchant backend:

     $ ./configure [--prefix=PFX] \
                   [--with-gnunet=GNUNETPFX] \
                   [--with-exchange=EXCHANGEPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, the exchange will install to /usr/local, which requires you to run the last step as root.

You have to specify --with-exchange=/usr/local and/or --with-gnunet=/usr/local if you installed the exchange and/or GNUnet to /usr/local in the previous steps.

Depending on the prefixes you specified for the installation and the distribution you are using, you may have to edit /etc/ld.so.conf, adding lines for GNUNETPFX/lib/ and EXCHANGEPFX/lib/ and PFX/lib/ (replace the prefixes with the actual paths you used). Afterwards, you should run ldconfig. Without this step, it is possible that the linker may not find the installed libraries and launching the Taler merchant backend would then fail.

Installing Anastasis
....................

The following steps assume all dependencies are installed.

First, unpack the Anastasis tarball and change into the resulting directory. Then, use the following commands to build and install Anastasis:

     $ ./configure [--prefix=PFX] \
                   [--with-gnunet=GNUNETPFX] \
                   [--with-exchange=EXCHANGEPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, Anastasis will be installed to /usr/local, which requires you to run the last step as root.

You have to specify --with-exchange=/usr/local and/or --with-gnunet=/usr/local if you installed the exchange and/or GNUnet to /usr/local in the previous steps.

Depending on the prefixes you specified for the installation and the distribution you are using, you may have to edit /etc/ld.so.conf, adding lines for GNUNETPFX/lib/ and EXCHANGEPFX/lib/ and PFX/lib/ (replace the prefixes with the actual paths you used). Afterwards, you should run ldconfig. Without this step, it is possible that the linker may not find the installed libraries and launching the Anastasis backend would then fail.

Installing GNUnet-gtk
.....................

The following steps assume at least the GNUnet and Gtk+ dependencies are installed.

First, unpack the gnunet-gtk tarball and change into the resulting directory. Then, use the following commands to build and install gnunet-gtk:

     $ ./configure [--prefix=$PFX] \
                   [--with-gnunet=$GNUNETPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

It is highly recommended to use the same prefix ($PFX) for gnunet-gtk that was used for GNUnet ($GNUNETPFX).  If you did not specify a prefix, gnunet-gtk will be installed to /usr/local, which requires you to run the last step as root.

You have to specify --with-gnunet=/usr/local if you installed GNUnet to /usr/local in the previous steps.

Depending on the prefixes you specified for the installation and the distribution you are using, you may have to edit /etc/ld.so.conf, adding lines for $GNUNETPFX/lib/ and $PFX/lib/ (replace the prefixes with the actual paths you used). Afterwards, you should run ldconfig. Without this step, it is possible that the linker may not find the installed libraries and launching gnunet-gtk would then fail.

Installing Anastasis-gtk
........................

The following steps assume at least the GNUnet, gnunet-gtk and Anastasis dependencies are installed.

First, unpack the anastasis-gtk tarball and change into the resulting directory.  Then, use the following commands to build and install anastasis-gtk:

     $ ./configure [--prefix=PFX] \
                   [--with-gnunet=GNUNETPFX] \
                   [--with-exchange=EXCHANGEPFX] \
                   [--with-anastasis=ANASTASISPFX]
     $ # Each dependency can be fetched from non standard locations via
     $ # the '--with-<LIBNAME>' option. See './configure --help'.
     $ make
     # make install

If you did not specify a prefix, anastasis-gtk will be installed to /usr/local, which requires you to run the last step as root.

You have to specify -with-anastasis=/usr/local, --with-exchange=/usr/local and/or --with-gnunet=/usr/local if you installed the exchange and/or GNUnet to /usr/local in the previous steps.

Depending on the prefixes you specified for the installation and the distribution you are using, you may have to edit /etc/ld.so.conf, adding lines for GNUNETPFX/lib/ and EXCHANGEPFX/lib/ and PFX/lib/ (replace the prefixes with the actual paths you used). Afterwards, you should run ldconfig. Without this step, it is possible that the linker may not find the installed libraries and launching anastasis-gtk would then fail.

Installing Anastasis binary packages on Debian
----------------------------------------------

To install the GNU Taler Debian packages, first ensure that you have the right Debian distribution. At this time, the packages are built for Sid, which means you should use a system which at least includes unstable packages in its source list.  We recommend using APT pinning to limit unstable packages to those explicitly requested. To do this, set your /etc/apt/preferences as follows:

     Package: *
     Pin: release a=stable
     Pin-Priority: 700

     Package: *
     Pin: release a=testing
     Pin-Priority: 650

     Package: *
     Pin: release a=unstable
     Pin-Priority: 600

     Package: *
     Pin: release l=Debian-Security
     Pin-Priority: 1000

A typical /etc/apt/sources.list file for this setup which combines Debian stable with more recent packages from testing and unstable would look like this:

     deb http://ftp.ch.debian.org/debian/ buster main
     deb http://security.debian.org/debian-security buster/updates main
     deb http://ftp.ch.debian.org/debian/ testing main
     deb http://ftp.ch.debian.org/debian/ unstable main

Naturally, you may want to use different mirrors depending on your region. Additionally, you must add a file to import the GNU Taler packages. Typically, this is done by adding a file /etc/apt/sources.list.d/taler.list that looks like this:

     deb https://deb.taler.net/apt/debian sid main

Next, you must import the Taler Systems SA public package signing key into your keyring and update the package lists:

     # wget -O - https://taler.net/taler-systems.gpg.key | apt-key add -
     # apt update

     You may want to verify the correctness of the Taler Systems key out-of-band.

Now your system is ready to install the official GNU Taler binary packages using apt.

Installing the graphical front-end
..................................

To install the Anastasis Gtk+ frontend, you can simply run:

     # apt install anastasis-gtk

To use anastasis-gtk, you can simply run:

     $ anastasis-gtk

Installing the backend
......................

If you want to install the Anastasis backend-end (which normal users do not need), you should run:

     # apt install -t sid anastasis-httpd

Note that the latter package does not perform all of the configuration work. It does setup the user users and the systemd service scripts, but you still must configure the database backup, HTTP reverse proxy (typically with TLS certificates), Taler merchant backend for payments, authentication services, prices and the terms of service.

Sample configuration files for the HTTP reverse proxy can be found in /etc/anastasis.conf.

Note that the package does not complete the integration of the backend with the HTTP reverse proxy (typically with TLS certificates).  A configuration fragment for Nginx or Apache will be placed in /etc/{apache,nginx}/conf-available/anastasis.conf.

To operate an Anastasis backend with payments, you additionally need to install a Taler merchant backend via:

     # apt install -t sid taler-merchant-httpd

Installing Anastasis binary packages on Ubuntu
----------------------------------------------

To install the GNU Taler Ubuntu packages, first ensure that you have the right Ubuntu distribution. At this time, the packages are built for Ubuntu 20.04 LTS (Focal Fossa).

A typical /etc/apt/sources.list.d/taler.list file for this setup would look like this:

     deb https://deb.taler.net/apt/ubuntu/ focal-fossa main

The last line is crucial, as it adds the GNU Taler packages.

Next, you must import the Taler Systems SA public package signing key into your keyring and update the package lists:

     # wget -O - https://taler.net/taler-systems.gpg.key | apt-key add -
     # apt update

     You may want to verify the correctness of the Taler Systems key out-of-band.

Now your system is ready to install the official GNU Taler binary packages using apt.

Installing the graphical front-end
..................................

To install the Anastasis front-end, you can now simply run:

     # apt install -t focal-fossa anastasis-gtk

To use anastasis-gtk, you can simply run:

     $ anastasis-gtk

Installing the backend
......................

If you want to install the Anastasis backend-end (which normal users do not need), you should run:

     # apt install -t focal-fossa anastasis-httpd

Note that the latter package does not perform all of the configuration work. It does setup the user users and the systemd service scripts, but you still must configure the database backup, HTTP reverse proxy (typically with TLS certificates), Taler merchant backend for payments, authentication services, prices and the terms of service.

Sample configuration files for the HTTP reverse proxy can be found in /etc/anastasis.conf.

To operate an Anastasis backend with payments, you additionally need to install a Taler merchant backend via:

     # apt install -t sid taler-merchant-httpd

Configuration
=============

Details about the contents of the configuration file are describe in the anastasis.conf(5) chapter.  This chapter only describes the configuration format.

Configuration format
--------------------

In Taler realm, any component obeys to the same pattern to get configuration values. According to this pattern, once the component has been installed, the installation deploys default values in ${prefix}/share/taler/config.d/, in .conf files. In order to override these defaults, the user can write a custom .conf file and either pass it to the component at execution time, or name it taler.conf and place it under $HOME/.config/.

A config file is a text file containing sections, and each section contains its values. The right format follows:

     [section1]
     value1 = string
     value2 = 23

     [section2]
     value21 = string
     value22 = /path22

Throughout any configuration file, it is possible to use $-prefixed variables, like $VAR, especially when they represent filesystem paths. It is also possible to provide defaults values for those variables that are unset, by using the following syntax: ${VAR:-default}. However, there are two ways a user can set $-prefixable variables:

by defining them under a [paths] section, see example below,

     [paths]
     TALER_DEPLOYMENT_SHARED = ${HOME}/shared-data
     ..
     [section-x]
     path-x = ${TALER_DEPLOYMENT_SHARED}/x

or by setting them in the environment:

     $ export VAR=/x

The configuration loader will give precedence to variables set under [path], though.

The utility taler-config, which gets installed along with the exchange, serves to get and set configuration values without directly editing the .conf. The option -f is particularly useful to resolve pathnames, when they use several levels of $-expanded variables. See taler-config --help.

Note that, in this stage of development, the file $HOME/.config/taler.conf can contain sections for all the component. For example, both an exchange and a bank can read values from it.

The repository git://taler.net/deployment contains examples of configuration file used in our demos. See under deployment/config.

     Note

     Expectably, some components will not work just by using default values, as their work is often interdependent. For example, a merchant needs to know an exchange URL, or a database name.

Using anastasis-config
----------------------

The tool anastasis-config can be used to extract or manipulate configuration values; however, the configuration use the well-known INI file format and can also be edited by hand.

Run

     $ anastasis-config -s $SECTION

to list all of the configuration values in section $SECTION.

Run

     $ anastasis-config -s $section -o $option

to extract the respective configuration value for option $option in section $section.

Finally, to change a setting, run

     $ anastasis-config -s $section -o $option -V $value

to set the respective configuration value to $value. Note that you have to manually restart the Taler backend after you change the configuration to make the new configuration go into effect.

Some default options will use $-variables, such as $DATADIR within their value. To expand the $DATADIR or other $-variables in the configuration, pass the -f option to anastasis-config. For example, compare:

     $ anastasis-config -s ACCOUNT-bank \
                    -o WIRE_RESPONSE
     $ anastasis-config -f -s ACCOUNT-bank \
                    -o WIRE_RESPONSE

While the configuration file is typically located at $HOME/.config/taler.conf, an alternative location can be specified to taler-merchant-httpd and anastasis-config using the -c option.

Cryptography
============

When a user needs to interact with Anastasis, the system first derives some key material, but not the master secret, from the user’s identifier using different HKDFs.  These HKDFs are salted using the respective escrow provider’s server salt, which ensures that the accounts for the same user cannot be easily correlated across the various Anastasis servers.

Each Anastasis server uses an EdDSA account key to identify the account of the user.  The account private key is derived from the user’s identifier using a computationally expensive cryptographic hash function.  Using an expensive hash algorithm is assumed to make it infeasible for a weak adversary to determine account keys by brute force (without knowing the user’s identifier). However, it is assumed that a strong adversary performing a targeted attack can compute the account key pair.

The public account key is Crockford base32-encoded in the URI to identify the account, and used to sign requests.  These signatures are also provided in base32-encoding and transmitted using the HTTP header Anastasis-Account-Signature.

When confidential data is uploaded to an Anastasis server, the respective payload is encrypted using AES-GCM with a symmetric key and initialization vector derived from the identifier and a high-entropy nonce.  The nonce and the GCM tag are prepended to the ciphertext before being uploaded to the Anastasis server.  This is done whenever confidential data is stored with the server.

The core secret of the user is (AES) encrypted using a symmetric master key.  Recovering this master key requires the user to satisfy a particular policy.  Policies specify a set of escrow methods, each of which leads the user to a key share. Combining those key shares (by hashing) allows the user to obtain a policy key, which can be used to decrypt the master key.  There can be many policies, satisfying any of these will allow the user to recover the master key.  A recovery document contains the encrypted core secret, a set of escrow methods and a set of policies.

Key derivations
---------------

EdDSA and ECDHE public keys are always points on Curve25519 and represented using the standard 256 bit Ed25519 compact format.  The binary representation is converted to Crockford Base32 when transmitted inside JSON or as part of URLs.

To start, a user provides their private, unique and unforgettable identifier as a seed to identify their account.  For example, this could be a social security number together with their full name.  Specifics may depend on the cultural context, in this document we will simply refer to this information as the identifier.

This identifier will be first hashed with Argon2, to provide a kdf_id which will be used to derive other keys later. The Hash must also include the respective server_salt. This also ensures that the kdf_id is different on each server. The use of Argon2 and the respective server_salt is intended to make it difficult to brute-force kdf_id values and help protect the user’s privacy. Also this ensures that the kdf_ids on every server differs. However, we do not assume that the identifier or the kdf_id cannot be determined by an adversary performing a targeted attack, as a user’s identifier is likely to always be known to state actors and may likely also be available to other actors.

     kdf_id := Argon2( identifier, server_salt, keysize )

identifier: The secret defined from the user beforehand.

server_salt: The salt from the Server.

keysize: The desired output size of the KDF, here 32 bytes.

Verification
............

For users to authorize “policy” operations we need an EdDSA key pair.  As we cannot assure that the corresponding private key is truly secret, such policy operations must never be destructive: Should an adversary learn the private key, they could access (and with the kdf_id, decrypt) the user’s policy (but not the core secret), or upload a new version of the encrypted recovery document (but not delete an existing version).

For the generation of the private key we use the kdf_id as the entropy source, hash it to derive a base secret which will then be processed to fit the requirements for EdDSA private keys.  From the private key we can then generate the corresponding public key.  Here, “ver” is used as a salt for the HKDF to ensure that the result differs from other cases where we hash kdf_id.

     ver_secret := HKDF(kdf_id, "ver", keysize)
     eddsa_priv := eddsa_d_to_a(ver_secret)
     eddsa_pub := get_EdDSA_Pub(eddsa_priv)

HKDF(): The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.

kdf_id: Hashed identifier.

key_size: Size of the output, here 32 bytes.

ver_secret: Derived key from the kdf_id, serves as intermediate step for the generation of the private key.

eddsa_d_to_a(): Function which converts the ver_key to a valid EdDSA private key. Specifically, assuming the value eddsa_priv is in a 32-byte array “digest”, the function clears and sets certain bits as follows:

     digest[0] = (digest[0] & 0x7f) | 0x40;
     digest[31] &= 0xf8;

eddsa_priv: The generated EdDSA private key.

eddsa_pub: The generated EdDSA public key.

Encryption
..........

For symmetric encryption of data we use AES256-GCM. For this we need a symmetric key and an initialization vector (IV).  To ensure that the symmetric key changes for each encryption operation, we compute the key material using an HKDF over a nonce and the kdf_id.

     (iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)

HKDF(): The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.

kdf_id: Hashed identifier.

keysize: Size of the AES symmetric key, here 32 bytes.

ivsize: Size of the AES GCM IV, here 12 bytes.

prekey: Original key material.

nonce: 32-byte nonce, must never match “ver” (which it cannot as the length is different). Of course, we must avoid key reuse. So, we have to use different nonces to get different keys and IVs (see below).

key: Symmetric key which is later used to encrypt the documents with AES256-GCM.

iv: IV which will be used for AES-GCM.

Key Usage
---------

The keys we have generated are then used to encrypt the recovery document and the key_share of the user.

Encryption
..........

Before every encryption a 32-byte nonce is generated. From this the symmetric key is computed as described above. We use AES256-GCM for the encryption of the recovery document and the key_share.  To ensure that the key derivation for the encryption of the recovery document differs fundamentally from that of an individual key share, we use different salts (“erd” and “eks”, respectively).

     (iv0, key0) := HKDF(key_id, nonce0, "erd", keysize + ivsize)
     (encrypted_recovery_document, aes_gcm_tag) := AES256_GCM(recovery_document, key0, iv0)
     (iv_i, key_i) := HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize)
     (encrypted_key_share_i, aes_gcm_tag_i) := AES256_GCM(key_share_i, key_i, iv_i)

encrypted_recovery_document: The encrypted recovery document which contains the escrow methods, policies and the encrypted core secret.

nonce0: Nonce which is used to generate key0 and iv0 which are used for the encryption of the recovery document. Nonce must contain the string “ERD”.

optional data: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider.

encrypted_key_share_i: The encrypted key_share which the escrow provider must release upon successful authentication. Here, i must be a positive number used to iterate over the various key shares used for the various escrow methods at the various providers.

nonce_i: Nonce which is used to generate key_i and iv_i which are used for the encryption of the key share. i must be the same number as specified above for encrypted_key_share_i. Nonce must contain the string “EKS” plus the according i.

As a special rule, when a security question is used to authorize access to an encrypted_key_share_i, then the salt “eks” is replaced with an (expensive) hash of the answer to the security question as an additional way to make the key share inaccessible to those who do not have the answer:

     powh := POW_HASH (qsalt, answer)
     ekss := HKDF("Anastasis-secure-question-uuid-salting",
                  powh,
                  uuid);
     (iv_i, key_i) := HKDF(key_id, nonce_i, ekss, [optional data], keysize + ivsize)

qsalt: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing.

answer: Answer to the security question, in UTF-8, as entered by the user.

powh: Result of the (expensive, proof-of-work) hash algorithm.

uuid: UUID of the challenge associated with the security question and the encrypted key share.

ekss: Replacement salt to be used instead of “eks” when deriving the key to encrypt/decrypt the key share.

Signatures
..........

The EdDSA keys are used to sign the data sent from the client to the server. Everything the client sends to server is signed. The following algorithm is equivalent for Anastasis-Policy-Signature.

     (anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv)
     ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)

anastasis-account-signature: Signature over the SHA-512 hash of the body using the purpose code TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD (1400) (see GNUnet EdDSA signature API for the use of purpose).

h_body: The hashed body.

ver_res: A boolean value. True: Signature verification passed, False: Signature verification failed.

When requesting policy downloads, the client must also provide a signature:

     (anastasis-account-signature) := eddsa_sign(version, eddsa_priv)
     ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)

anastasis-account-signature: Signature over the SHA-512 hash of the body using the purpose code TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD (1401) (see GNUnet EdDSA signature API for the use of purpose).

version: The version requested as a 64-bit integer, 2^64-1 for the “latest version”.

ver_res: A boolean value. True: Signature verification passed, False: Signature verification failed.

Availability Considerations
---------------------------

Anastasis considers two main threats against availability. First, the Anastasis server operators must be protected against denial-of-service attacks where an adversary attempts to exhaust the operator’s resources.  The API protects against these attacks by allowing operators to set fees for all operations. Furthermore, all data stored comes with an expiration logic, so an attacker cannot force servers to store data indefinitely.

A second availability issue arises from strong adversaries that may be able to compute the account keys of some user.  While we assume that such an adversary cannot successfully authenticate against the truth, the account key does inherently enable these adversaries to upload a new policy for the account. This cannot be prevented, as the legitimate user must be able to set or change a policy using only the account key.  To ensure that an adversary cannot exploit this, policy uploads first of all never delete existing policies, but merely create another version.  This way, even if an adversary uploads a malicious policy, a user can still retrieve an older version of the policy to recover access to their data.  This append-only storage for policies still leaves a strong adversary with the option of uploading many policies to exhaust the Anastasis server’s capacity.  We limit this attack by requiring a policy upload to include a reference to a payment identifier from a payment made by the user.  Thus, a policy upload requires both knowledge of the identity and making a payment.  This effectively prevents an adversary from using the append-only policy storage from exhausting Anastasis server capacity.

REST API
========

HTTP Request and Response
-------------------------

Certain response formats are common for all requests. They are documented here instead of with each individual request.  Furthermore, we note that clients may theoretically fail to receive any response.  In this case, the client should verify that the Internet connection is working properly, and then proceed to handle the error as if an internal error (500) had been returned.

 -- HTTP Any: ANY /*

     Request:

     Unless specified otherwise, HTTP requests that carry a message body must have the content type application/json.

     Request Headers:

       * Content-Type (https://tools.ietf.org/html/rfc7231#section-3.1.1.5) – application/json

     Response:

     Response Headers:

       * Content-Type (https://tools.ietf.org/html/rfc7231#section-3.1.1.5) – application/json

     200 Ok (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1):

          The request was successful.

     400 Bad request (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1):

          One of the arguments to the request is missing or malformed.

     500 Internal server error (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1):

          This always indicates some serious internal operational error of the Anastasis provider, such as a program bug, database problems, etc., and must not be used for client-side problems.  When facing an internal server error, clients should retry their request after some delay.  We recommended initially trying after 1s, twice more at randomized times within 1 minute, then the user should be informed and another three retries should be scheduled within the next 24h. If the error persists, a report should ultimately be made to the auditor, although the auditor API for this is not yet specified.  However, as internal server errors are always reported to the exchange operator, a good operator should naturally be able to address them in a timely fashion, especially within 24h.

     Unless specified otherwise, all error status codes (4xx and 5xx) have a message body with an ErrorDetail JSON object.

     Details:

          interface ErrorDetail {

            // Numeric error code unique to the condition, see ``gnu-taler-error-codes`` in GANA.
            // The other arguments are specific to the error value reported here.
            code: number;

            // Human-readable description of the error, i.e. "missing parameter", "commitment violation", ...
            // Should give a human-readable hint about the error's nature. Optional, may change without notice!
            hint?: string;

          }

Protocol Version Ranges
-----------------------

Anastasis services expose the range of API versions they support.  Clients in turn have an API version range they support.  These version ranges are written down in the libtool version format (https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html).

A protocol version is a positive, non-zero integer.  A protocol version range consists of three components:

 1. The current version.  This is the latest version of the protocol supported by the client or service.

 2. The revision number.  This value should usually not be interpreted by the client/server, but serves purely as a comment.  Each time a service/client for a protocol is updated while supporting the same set of protocol versions, the revision should be increased. In rare cases, the revision number can be used to work around unintended breakage in deployed versions of a service.  This is discouraged and should only be used in exceptional situations.

 3. The age number.  This non-zero integer identifies with how many previous protocol versions this implementation is compatible.  An age of 0 implies that the implementation only supports the current protocol version.  The age must be less or equal than the current protocol version.

To avoid confusion with semantic versions, the protocol version range is written down in the following format:

     current[:revision[:age]]

The angle brackets mark optional components. If either revision or age are omitted, they default to 0.

Examples:

  * “1” and “1” are compatible

  * “1” and “2” are incompatible

  * “2:0:1” and “1:0:0” are compatible

  * “2:5:1” and “1:10:0” are compatible

  * “4:0:1” and “2:0:0” are incompatible

  * “4:0:1” and “3:0:0” are compatible

     Semantic versions (https://semver.org/) are not a good tool for this job, as we concisely want to express that the client/server supports the last n versions of the protocol. Semantic versions don’t support this, and semantic version ranges are too complex for this.

     A client doesn’t have one single protocol version range.  Instead, it has a protocol version range for each type of service it talks to.

     For privacy reasons, the protocol version range of a client should not be sent to the service.  Instead, the client should just use the two version ranges to decide whether it will talk to the service.

Common encodings
----------------

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

Binary Data
...........

     type Base32 = string;

Binary data is generally encoded using Crockford’s variant of Base32 (http://www.crockford.com/wrmg/base32.html), except that “U” is not excluded but also decodes to “V” to make OCR easy.  We will still simply use the JSON type “base32” and the term “Crockford Base32” in the text to refer to the resulting encoding.

Hash codes
..........

Hash codes are strings representing base32 encoding of the respective hashed data. See base32.

     // 64-byte hash code.
     type HashCode = string;

     // 32-byte hash code.
     type ShortHashCode = string;

Large numbers
.............

Large numbers such as 256 bit keys, are transmitted as other binary data in Crockford Base32 encoding.

Timestamps
..........

Timestamps are represented by the following structure:

     interface Timestamp {
       // Milliseconds since epoch, or the special
       // value "never" to represent an event that will
       // never happen.
       t_ms: number | "never";
     }

     interface Duration {
       // Duration in milliseconds or "forever"
       // to represent an infinite duration.
       d_ms: number | "forever";
     }

Integers
........

     // JavaScript numbers restricted to integers.
     type Integer = number;

Objects
.......

     // JavaScript objects, no further restrictions.
     type Object = object;

Keys
....

     // EdDSA and ECDHE public keys always point on Curve25519
     // and represented  using the standard 256 bits Ed25519 compact format,
     // converted to Crockford `Base32`.
     type EddsaPublicKey = string;

     // EdDSA and ECDHE public keys always point on Curve25519
     // and represented  using the standard 256 bits Ed25519 compact format,
     // converted to Crockford `Base32`.
     type EddsaPrivateKey = string;

Signatures
..........

     // EdDSA signatures are transmitted as 64-bytes `base32`
     // binary-encoded objects with just the R and S values (base32_ binary-only).
     type EddsaSignature = string;

Amounts
.......

     type Amount = string;

Amounts of currency are serialized as a string of the format <Currency>:<DecimalAmount>.  Taler treats monetary amounts as fixed-precision numbers, with 8 decimal places.  Unlike floating point numbers, this allows accurate representation of monetary amounts.

The following constrains apply for a valid amount:

 1. The <Currency> part must be at most 11 characters long and may only consist of ASCII letters (a-zA-Z).

 2. The integer part of <DecimalAmount> may be at most 2^52.

 3. The fractional part of <DecimalAmount> may contain at most 8 decimal digits.

     “EUR:1.50” and “EUR:10” are valid amounts.  These are all invalid amounts: “A:B:1.5”, “EUR:4503599627370501.0”, “EUR:1.”, “EUR:.1”.

An amount that is prefixed with a + or - character is also used in certain contexts. When no sign is present, the amount is assumed to be positive.

Time
....

In signed messages, time is represented using 64-bit big-endian values, denoting microseconds since the UNIX Epoch.  UINT64_MAX represents “never”.

     struct GNUNET_TIME_Absolute {
       uint64_t timestamp_us;
     };
     struct GNUNET_TIME_AbsoluteNBO {
       uint64_t abs_value_us__;       // in network byte order
     };

Cryptographic primitives
........................

All elliptic curve operations are on Curve25519.  Public and private keys are thus 32 bytes, and signatures 64 bytes.  For hashing, including HKDFs, Taler uses 512-bit hash codes (64 bytes).

     struct GNUNET_HashCode {
       uint8_t hash[64];      // usually SHA-512
     };

     struct TALER_EcdhEphemeralPublicKeyP {
       uint8_t ecdh_pub[32];
     };

     struct UUID {
       uint32_t value[4];
     };

Signatures
..........

Any piece of signed data, complies to the abstract data structure given below.

     struct Data {
       struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
       type1_t payload1;
       type2_t payload2;
       ...
     };

     /*From gnunet_crypto_lib.h*/
     struct GNUNET_CRYPTO_EccSignaturePurpose {
       /**

       The following constraints apply for a valid amount:

        * This field is used to express the context in
        * which the signature is made, ensuring that a
        * signature cannot be lifted from one part of the protocol
        * to another. See `src/include/taler_signatures.h` within the
        * exchange's codebase (git://taler.net/exchange).
        */
       uint32_t purpose;
       /**
        * This field equals the number of bytes being signed,
        * namely 'sizeof (struct Data)'.
        */
       uint32_t size;
     };

Receiving Configuration
.......................

 -- HTTP Get: GET /config

     Obtain the configuration details of the escrow provider.

     Response:

     Returns an EscrowConfigurationResponse.

          interface EscrowConfigurationResponse {

            // Protocol identifier, clarifies that this is an Anastasis provider.
            name: "anastasis";

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

            // Currency in which this provider processes payments.
            currency: string;

            // Supported authorization methods.
            methods: AuthorizationMethodConfig[];

            // Maximum policy upload size supported.
            storage_limit_in_megabytes: number;

            // Payment required to maintain an account to store policy documents for a year.
            // Users can pay more, in which case the storage time will go up proportionally.
            annual_fee: Amount;

            // Payment required to upload truth.  To be paid per upload.
            truth_upload_fee: Amount;

            // Limit on the liability that the provider is offering with
            // respect to the services provided.
            liability_limit: Amount;

            // Salt value with 128 bits of entropy.
            // Different providers
            // will use different high-entropy salt values. The resulting
            // **provider salt** is then used in various operations to ensure
            // cryptographic operations differ by provider.  A provider must
            // never change its salt value.
            server_salt: string;

          }

          interface AuthorizationMethodConfig {
            // Name of the authorization method.
            type: string;

            // Fee for accessing key share using this method.
            cost: Amount;

          }

Receiving Terms of Service
..........................

 -- HTTP Get: GET /terms

     Obtain the terms of service provided by the escrow provider.

     Response:

     Returns the terms of service of the provider, in the best language and format available based on the client’s request.

 -- HTTP Get: GET /privacy

     Obtain the privacy policy of the service provided by the escrow provider.

     Response:

     Returns the privacy policy of the provider, in the best language and format available based on the client’s request.

Manage policy
.............

This API is used by the Anastasis client to deposit or request encrypted recovery documents with the escrow provider.  Generally, a client will deposit the same encrypted recovery document with each escrow provider, but provide a different truth to each escrow provider.

Operations by the client are identified and authorized by $ACCOUNT_PUB, which should be kept secret from third parties. $ACCOUNT_PUB should be an account public key using the Crockford base32-encoding.

In the following, UUID is always defined and used according to RFC 4122 (https://tools.ietf.org/html/rfc4122).

 -- HTTP Get: GET /policy/$ACCOUNT_PUB[?version=$NUMBER]

     Get the customer’s encrypted recovery document.  If version is not specified, the server returns the latest available version.  If version is specified, returns the policy with the respective version.  The response must begin with the nonce and an AES-GCM tag and continue with the ciphertext.  Once decrypted, the plaintext is expected to contain:

       * the escrow policy

       * the separately encrypted master public key

     Note that the key shares required to decrypt the master public key are not included, as for this the client needs to obtain authorization. The policy does provide sufficient information for the client to determine how to authorize requests for truth.

     The client MAY provide an If-None-Match header with an Etag. In that case, the server MUST additionally respond with an 304 status code in case the resource matches the provided Etag.

     Response:

     200 OK (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1):

          The escrow provider responds with an EncryptedRecoveryDocument object.

     304 Not modified (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5):

          The client requested the same resource it already knows.

     400 Bad request (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1):

          The $ACCOUNT_PUB is not an EdDSA public key.

     402 Payment Required (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3):

          The account’s balance is too low for the specified operation. See the Taler payment protocol specification for how to pay.

     403 Forbidden (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4):

          The required account signature was invalid.

     404 Not found (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5):

          The requested resource was not found.

     Anastasis-Version: $NUMBER — The server must return actual version of the encrypted recovery document via this header. If the client specified a version number in the header of the request, the server must return that version. If the client did not specify a version in the request, the server returns latest version of the EncryptedRecoveryDocument.

     Etag: Set by the server to the Base32-encoded SHA512 hash of the body. Used for caching and to prevent redundancies. The server MUST send the Etag if the status code is 200 OK.

     If-None-Match: If this is not the very first request of the client, this contains the Etag-value which the client has received before from the server. The client SHOULD send this header with every request (except for the first request) to avoid unnecessary downloads.

     Anastasis-Account-Signature: The client must provide Base-32 encoded EdDSA signature over hash of body with $ACCOUNT_PRIV, affirming desire to download the requested encrypted recovery document.  The purpose used MUST be TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD (1401).

 -- HTTP Post: POST /policy/$ACCOUNT_PUB

     Upload a new version of the customer’s encrypted recovery document. While the document’s structure is described in JSON below, the upload should just be the bytestream of the raw data (i.e. 32-byte nonce followed by 16-byte tag followed by the encrypted document). If the request has been seen before, the server should do nothing, and otherwise store the new version. The body must begin with a nonce, an AES-GCM tag and continue with the ciphertext.  The format is the same as specified for the response of the GET method. The Anastasis server cannot fully validate the format, but MAY impose minimum and maximum size limits.

     Request:

     Query Parameters:

       * storage_duration=YEARS – For how many years from now would the client like us to store the recovery document? Defaults to 0 (that is, do not extend / prolong existing storage contract). The server will respond with a 402 Payment required, but only if the rest of the request is well-formed (account signature must match).  Clients that do not actually intend to make a new upload but that only want to pay may attempt to upload the latest backup again, as this option will be checked before the 304 Not modified case.

       * timeout_ms=NUMBER – Optional.  If specified, the Anastasis server will wait up to timeout_ms milliseconds for completion of the payment before sending the HTTP response.  A client must never rely on this behavior, as the backend may return a response immediately.

     If-None-Match: This header MUST be present and set to the SHA512 hash (Etag) of the body by the client. The client SHOULD also set the Expect: 100-Continue header and wait for 100 continue before uploading the body.  The server MUST use the Etag to check whether it already knows the encrypted recovery document that is about to be uploaded. The server MUST refuse the upload with a 304 status code if the Etag matches the latest version already known to the server.

     Anastasis-Policy-Signature: The client must provide Base-32 encoded EdDSA signature over hash of body with $ACCOUNT_PRIV, affirming desire to upload an encrypted recovery document.

     Payment-Identifier: Base-32 encoded 32-byte payment identifier that was included in a previous payment (see 402 status code). Used to allow the server to check that the client paid for the upload (to protect the server against DoS attacks) and that the client knows a real secret of financial value (as the kdf_id might be known to an attacker). If this header is missing in the client’s request (or the associated payment has exceeded the upload limit), the server must return a 402 response.  When making payments, the server must include a fresh, randomly-generated payment-identifier in the payment request.

     Response:

     204 No content (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5):

          The encrypted recovery document was accepted and stored.  Anastasis-Version and Anastasis-UUID headers indicate what version and UUID was assigned to this encrypted recovery document upload by the server.

     304 Not modified (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5):

          The same encrypted recovery document was previously accepted and stored.  Anastasis-Version header indicates what version was previously assigned to this encrypted recovery document.

     400 Bad request (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1):

          The $ACCOUNT_PUB is not an EdDSA public key or mandatory headers are missing. The response body MUST elaborate on the error using a Taler error code in the typical JSON encoding.

     402 Payment required (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3):

          The account’s balance is too low for the specified operation. See the Taler payment protocol specification for how to pay. The response body MAY provide alternative means for payment.

     403 Forbidden (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4):

          The required account signature was invalid.  The response body may elaborate on the error.

     413 Request entity too large (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14):

          The upload is too large or too small. The response body may elaborate on the error.

     Details:

          interface EncryptedRecoveryDocument {
            // Nonce used to compute the (iv,key) pair for encryption of the
            // encrypted_compressed_recovery_document.
            nonce: [32]; //bytearray

            // Authentication tag.
            aes_gcm_tag: [16]; //bytearray

            // Variable-size encrypted recovery document. After decryption,
            // this contains a gzip compressed JSON-encoded `RecoveryDocument`.
            // The nonce of the HKDF for this encryption must include the
            // string "ERD".
            encrypted_compressed_recovery_document: []; //bytearray of undefined length

          }

          interface RecoveryDocument {
            // Account identifier at backup provider, AES-encrypted with
            // the (symmetric) master_key, i.e. an URL
            // https://sync.taler.net/$BACKUP_ID and
            // a private key to decrypt the backup.  Anastasis is oblivious
            // to the details of how this is ultimately encoded.
            backup_account: []; //bytearray of undefined length

            // List of escrow providers and selected authentication method.
            methods: EscrowMethod[];

            // List of possible decryption policies.
            policy: DecryptionPolicy[];

          }

          interface EscrowMethod {
            // URL of the escrow provider (including possibly this Anastasis server).
            provider_url : string;

            // Type of the escrow method (e.g. security question, SMS etc.).
            escrow_type: string;

            // UUID of the escrow method (see /truth/ API below).
            uuid: string;

            // Key used to encrypt the `Truth` this `EscrowMethod` is related to.
            // Client has to provide this key to the server when using ``/truth/``.
            truth_encryption_key: [32]; //bytearray

            // Salt used to encrypt the truth on the Anastasis server.
            truth_salt: [32]; //bytearray

            // The challenge to give to the user (i.e. the security question
            // if this is challenge-response).
            // (Q: as string in base32 encoding?)
            // (Q: what is the mime-type of this value?)
            //
            // For some methods, this value may be absent.
            //
            // The plaintext challenge is not revealed to the
            // Anastasis server.
            challenge: []; //bytearray of undefined length

          }

          interface DecryptionPolicy {
            // Salt included to encrypt master key share when
            // using this decryption policy.
            policy_salt: [32]; //bytearray

            // Master key, AES-encrypted with key derived from
            // salt and keyshares revealed by the following list of
            // escrow methods identified by UUID.
            encrypted_master_key: [32]; //bytearray

            // List of escrow methods identified by their UUID.
            uuid: string[];

          }

Managing truth
..............

This API is used by the Anastasis client to deposit truth or request a (encrypted) key share with the escrow provider.

An escrow method specifies an Anastasis provider and how the user should authorize themself.  The truth API allows the user to provide the (encrypted) key share to the respective escrow provider, as well as auxiliary data required for such a respective escrow method.

An Anastasis-server may store truth for free for a certain time period, or charge per truth operation using GNU Taler.

 -- HTTP Post: POST /truth/$UUID

     Upload a TruthUploadRequest-Object according to the policy the client created before (see RecoveryDocument). If request has been seen before, the server should do nothing, and otherwise store the new object.

     Request:

     Query Parameters:

       * timeout_ms=NUMBER – Optional.  If specified, the Anastasis server will wait up to timeout_ms milliseconds for completion of the payment before sending the HTTP response.  A client must never rely on this behavior, as the backend may return a response immediately.

     Response:

     204 No content (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5):

          Truth stored successfully.

     304 Not modified (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5):

          The same truth was previously accepted and stored under this UUID.  The Anastasis server must still update the expiration time for the truth when returning this response code.

     402 Payment required (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3):

          This server requires payment to store truth per item. See the Taler payment protocol specification for how to pay. The response body MAY provide alternative means for payment.

     409 Conflict (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10):

          The server already has some truth stored under this UUID. The client should check that it is generating UUIDs with enough entropy.

     412 Precondition failed (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13):

          The selected authentication method is not supported on this provider.

     Details:

          interface TruthUploadRequest {
            // Contains the information of an interface `EncryptedKeyShare`, but simply
            // as one binary block (in Crockford Base32 encoding for JSON).
            key_share_data: []; //bytearray

            // Key share method, i.e. "security question", "SMS", "e-mail", ...
            type: string;

            // Nonce used to compute the (iv,key) pair for encryption of the
            // encrypted_truth.
            nonce: [32]; //bytearray

            // Authentication tag of ``encrypted_truth``.
            aes_gcm_tag: [16]; //bytearray

            // Variable-size truth. After decryption,
            // this contains the ground truth, i.e. H(challenge answer),
            // phone number, e-mail address, picture, fingerprint, ...
            // **base32 encoded**.
            //
            // The nonce of the HKDF for this encryption must include the
            // string "ECT".
            encrypted_truth: [80]; //bytearray

            // MIME type of truth, i.e. text/ascii, image/jpeg, etc.
            truth_mime: string;

            // For how many years from now would the client like us to
            // store the truth?
            storage_duration_years: Integer;

          }

 -- HTTP Get: GET /truth/$UUID[?response=$H_RESPONSE]

     Get the stored encrypted key share. If $H_RESPONSE is specified by the client, the server checks if $H_RESPONSE matches the expected response specified before within the TruthUploadRequest (see encrypted_truth). Also, the user has to provide the correct truth_encryption_key with every get request (see below). When $H_RESPONSE is correct, the server responds with the encrypted key share. The encrypted key share is returned simply as a byte array and not in JSON format.

     Response:

     200 OK (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1):

          EncryptedKeyShare is returned in body (in binary).

     202 Accepted (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3):

          The escrow provider will respond out-of-band (i.e. SMS). The body may contain human-readable instructions on next steps.

     >>208 Already Reported<<:

          An authentication challenge was recently send, client should simply respond to the pending challenge.

     303 See other (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4):

          The provider redirects for authentication (i.e. video identification/WebRTC). If the client is not a browser, it should launch a browser at the URL given in the Location header and allow the user to re-try the operation after successful authorization.

     402 Payment required (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3):

          The service requires payment for access to truth. See the Taler payment protocol specification for how to pay. The response body MAY provide alternative means for payment.

     403 Forbidden (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4):

          The server requires a valid “response” to the challenge associated with the UUID.

     404 Not found (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5):

          The server does not know any truth under the given UUID.

     410 Gone (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11):

          The server has not (recently) issued a challenge under the given UUID, but a reply was provided. (This does not apply for secure question.)

     417 Expectation Failed (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18):

          The decrypted truth does not match the expectations of the authentication backend, i.e. a phone number for sending an SMS is not a number, or an e-mail address for sending an E-mail is not a valid e-mail address.

     503 Service Unavailable (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4):

          Server is out of Service.

     Truth-Decryption-Key: Key used to encrypt the truth (see encrypted_truth within TruthUploadRequest) and which has to provided by the user. The key is stored with the according EscrowMethod. The server needs this key to get the info out of TruthUploadRequest needed to verify the $RESPONSE.

     Details:

          interface EncryptedKeyShare {
            // Nonce used to compute the decryption (iv,key) pair.
            nonce_i: [32]; //bytearray

            // Authentication tag.
            aes_gcm_tag_i: [16]; //bytearray

            // Encrypted key-share in base32 encoding.
            // After decryption, this yields a `KeyShare`.  Note that
            // the `KeyShare` MUST be encoded as a fixed-size binary
            // block (instead of in JSON encoding).
            //
            // HKDF for the key generation must include the
            // string "eks" as salt.
            // Depending on the method,
            // the HKDF may additionally include
            // bits from the response (i.e. some hash over the
            // answer to the security question).
            encrypted_key_share_i: [32]; //bytearray

          }

          interface KeyShare {
            // Key material to concatenate with policy_salt and KDF to derive
            // the key to decrypt the master key.
            key_share: [32]; //bytearray

            // Signature over method, UUID, and ``key_share``.
            account_sig: EddsaSignature;

          }

Reducer API
===========

This section describes the Anastasis Reducer API which is used by client applications to store or load the different states the client application can have. The reducer takes a state in JSON syntax and returns the new state in JSON syntax.

For example a state may take the following structure:

     {
       "backup_state": "CONTINENT_SELECTING",
       "continents": [
         "Europe",
         "North_America"
       ]
     }

The new state depends on the previous one and on the transition action with its arguments given to the reducer. A transition argument also is a statement in JSON syntax:

     {
       "continent": "Europe"
     }

The new state returned by the reducer with the state and transition argument defined above would look like following for the transition action select_continent:

     {
       "backup_state": "COUNTRY_SELECTING",
       "continents": [
         "Europe",
         "North_America"
       ],
       "selected_continent": "Europe",
       "countries": [
         {
           "code": "ch",
           "name": "Switzerland",
           "continent": "Europe",
           "name_i18n": {
             "de_DE": "Schweiz",
             "de_CH": "Schwiiz",
             "fr": "Suisse",
             "en": "Swiss"
           },
           "currency": "CHF"
         },
         {
           "code": "de",
           "name": "Germany",
           "continent": "Europe",
           "continent_i18n": {
             "de": "Europa"
           },
           "name_i18n": {
             "de_DE": "Deutschland",
             "de_CH": "Deutschland",
             "fr": "Allemagne",
             "en": "Germany"
           },
           "currency": "EUR"
         }
       ]
     }

States
------

Overall, the reducer knows the following states:

          ERROR: The transition led to an error. No further transitions are possible from

               this state, but the client may want to continue from a previous state.

          CONTINENT_SELECTING: The user should specify the continent where they are living,

               so that we can show a list of countries to choose from.

          COUNTRY_SELECTING: The user should specify the country where they are living,

               so that we can determine appropriate attributes, currencies and Anastasis providers.

          USER_ATTRIBUTES_COLLECTING: The user should provide the country-specific personal

               attributes.

          AUTHENTICATIONS_EDITING: The user should add authentication methods to be used

               during recovery.

       - POLICIES_REVIEWING: The user should review the recovery policies.

       - SECRET_EDITING: The user should edit the secret to be backed up.

          TRUTHS_PAYING: The user needs to pay for one or more uploads of data associated

               with an authentication method.

       - POLICIES_PAYING: The user needs to pay for storing the recovery policy document.

       - BACKUP_FINISHED: A backup has been successfully generated.

          SECRET_SELECTING: The user needs to select a recovery policy document with

               the secret that is to be recovered.

          CHALLENGE_SELECTING: The user needs to select an authorization challenge to

               proceed with recovery.

       - CHALLENGE_PAYING: The user needs to pay to proceed with the authorization challenge.

       - CHALLENGE_SOLVING: The user needs to solve the authorization challenge.

       - RECOVERY_FINISHED: The secret of the user has been recovered.

State names:

       - In SELECTING-states, the user has to choose one value out of a predefined set of values (for example a continent out of a set of continents).

       - In COLLECTING-states, the user has to give certain values.

       - In EDITING-states, the user is free to choose which values he wants to give.

       - In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something.

       - in PAYING-states, the user must make a payment.

       - in FINISHED-states, the operation has definitively concluded.

Backup Reducer
--------------

fig-anastasis_reducer_backup

Figure: Backup states and their transitions.

The illustration above shows the different states the reducer can have during a backup process.

Recovery Reducer
----------------

fig-anastasis_reducer_recovery

Figure: Recovery states and their transitions.

The illustration above shows the different states the reducer can have during a recovery process.

Reducer transitions
-------------------

In the following, the individual transitions will be specified in more detail. Note that we only show fields added by the reducer, typically the previous state is preserved to enable “back” transitions to function smoothly.

Initial state
.............

The initial states for backup and recovery processes are:

Initial backup state:

     {
       "backup_state": "CONTINENT_SELECTING",
       "continents": [
         "Europe",
         "North America"
       ]
     }

Initial recovery state:

     {
       "recovery_state": "CONTINENT_SELECTING",
       "continents": [
         "Europe",
         "North America"
       ]
     }

Here, “continents” is an array of English strings with the names of the continents which contain countries for which Anastasis could function (based on having providers that are known to operate and rules being provided for user attributes from those countries).

For internationalization, another field continents_i18n may be present. This field would be a map of language names to arrays of translated continent names:

     {
       "recovery_state": "CONTINENT_SELECTING",
       "continents": [
         "Europe",
         "North America"
       ]
       "continents_i18n":
       {
         "de_DE" : [
           "Europa",
           "Nordamerika"
           ],
         "de_CH" : [
           "Europa",
           "Nordamerika"
           ]
       }
     }

Translations must be given in the same order as the main English array.

Common transitions
..................

select_continent:

Here the user specifies the continent they live on.  Arguments (example):

     {
       "continent": "Europe"
     }

The continent must be given using the English name from the continents array. Using a translated continent name is invalid and may result in failure.

The reducer returns an updated state with a list of countries to choose from, for example:

     {
       "backup_state": "COUNTRY_SELECTING",
       "selected_continent": "Europe",
       "countries": [
         {
           "code": "ch",
           "name": "Switzerland",
           "continent": "Europe",
           "name_i18n": {
             "de_DE": "Schweiz",
             "de_CH": "Schwiiz",
             "fr": "Suisse",
             "en": "Swiss"
           },
           "currency": "CHF"
         },
         {
           "code": "de",
           "name": "Germany",
           "continent": "Europe",
           "continent_i18n": {
             "de": "Europa"
           },
           "name_i18n": {
             "de_DE": "Deutschland",
             "de_CH": "Deutschland",
             "fr": "Allemagne",
             "en": "Germany"
           },
           "currency": "EUR"
         }
       ]
     }

Here countries is an array of countries on the selected_continent.  For each country, the code is the ISO 3166-1 alpha-2 country code.  The continent is only present because some countries span continents, the information is redundant and will always match selected_continent.  The name is the name of the country in English, internationalizations of the name may be provided in name_i18n.  The currency is an official currency of the country, if a country has multiple currencies, it may appear multiple times in the list.  In this case, the user should select the entry with the currency they intend to pay with.  It is also possible for users to select a currency that does not match their country, but user interfaces should by default try to use currencies that match the user’s residence.

select_country:

Selects the country (via the country code) and specifies the currency. The latter is needed as some countries have more than one currency, and some use-cases may also involve users insisting on paying with foreign currency.

Arguments (example):

     {
       "country_code": "de",
       "currency": "EUR"
     }

The country_code must be an ISO 3166-1 alpha-2 country code from the array of countries of the reducer’s state.  The currency field must be a valid currency accepted by the Taler payment system.

The reducer returns a new state with the list of attributes the user is expected to provide, as well as possible authentication providers that accept payments in the selected currency:

     {
       "backup_state": "USER_ATTRIBUTES_COLLECTING",
       "selected_country": "de",
       "currency": "EUR",
       "required_attributes": [
         {
           "type": "string",
           "name": "full_name",
           "label": "Full name",
           "label_i18n": {
             "de_DE": "Vollstaendiger Name",
             "de_CH": "Vollstaendiger. Name",
             "fr": "Nom complet",
             "en": "Full name"
           },
           "widget": "anastasis_gtk_ia_full_name",
           "uuid" : "9e8f463f-575f-42cb-85f3-759559997331"
         },
         {
           "type": "date",
           "name": "birthdate",
           "label": "Birthdate",
           "label_i18n": {
             "de_DE": "Geburtsdatum",
             "de_CH": "Geburtsdatum",
             "fr": "Date de naissance",
             "en": "Birthdate"
           },
           "uuid" : "83d655c7-bdb6-484d-904e-80c1058c8854"
           "widget": "anastasis_gtk_ia_birthdate"
         },
             {
                "type": "string",
            "name": "tax_number",
                "label": "Taxpayer identification number",
                "label_i18n":{
                      "de_DE": "Steuerliche Identifikationsnummer",
                      "de_CH": "Steuerliche Identifikationsnummer",
                      "en": "German taxpayer identification number"
                },
                "widget": "anastasis_gtk_ia_tax_de",
            "uuid": "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
                "validation-regex": "^[0-9]{11}$",
                "validation-logic": "DE_TIN_check"
             },
         {
           "type": "string",
           "name": "social_security_number",
           "label": "Social security number",
           "label_i18n": {
             "de_DE": "Sozialversicherungsnummer",
             "de_CH": "Sozialversicherungsnummer",
             "fr": "Numéro de sécurité sociale",
             "en": "Social security number"
           },
           "widget": "anastasis_gtk_ia_ssn",
               "validation-regex": "^[0-9]{8}[[:upper:]][0-9]{3}$",
               "validation-logic": "DE_SVN_check"
           "optional" : true
       }
       ],
       "authentication_providers": {
         "http://localhost:8089/": {
           "http_status": 200,
           "methods": [
             { "type" : "question",
               "usage_fee" : "EUR:0.0" },
             { "type" : "sms",
               "usage_fee" : "EUR:0.5" }
           ],
           "annual_fee": "EUR:4.99",
           "truth_upload_fee": "EUR:4.99",
           "liability_limit": "EUR:1",
           "currency": "EUR",
           "truth_lifetime": { "d_ms" : 50000000 },
           "storage_limit_in_megabytes": 1,
           "provider_name": "Anastasis 4",
           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
         },
         "http://localhost:8088/": {
           "http_status": 200,
           "methods": [
             { "type" : "question",
               "usage_fee" : "EUR:0.01" },
             { "type" : "sms",
               "usage_fee" : "EUR:0.55" }
           ],
           "annual_fee": "EUR:0.99",
           "truth_upload_fee": "EUR:3.99",
           "liability_limit": "EUR:1",
           "currency": "EUR",
           "truth_lifetime": { "d_ms" : 50000000 },
           "storage_limit_in_megabytes": 1,
           "provider_name": "Anastasis 4",
           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
         }
       }
     }

The array of required_attributes contains attributes about the user that must be provided includes:

       - type: The type of the attribute, for now only string and date are supported.

       - name: The name of the attribute, this is the key under which the attribute value must be provided later. The name must be unique per response.

       - label: A human-readable description of the attribute in English. Translated descriptions may be provided under label_i18n.

       - uuid: A UUID that uniquely identifies identical attributes across different countries. Useful to preserve values should the user enter some attributes, and then switch to another country.  Note that attributes must not be preserved if they merely have the same name, only the uuid will be identical if the semantics is identical.

       - widget: An optional name of a widget that is known to nicely render the attribute entry in user interfaces where named widgets are supported.

       - validation-regex: An optional extended POSIX regular expression that is to be used to validate (string) inputs to ensure they are well-formed.

       - validation-logic: Optional name of a function that should be called to validate the input.  If the function is not known to the particular client, the respective validation can be skipped (at the expense of typos by users not being detected, possibly rendering secrets irrecoverable).

       - optional: Optional boolean field that, if true, indicates that this attribute is not actually required but optional and users MAY leave it blank in case they do not have the requested information. Used for common fields that apply to some large part of the population but are not sufficiently universal to be actually required.

The authentication providers are listed under a key that is the base URL of the service. For each provider, the following information is provided if the provider was successfully contacted:

       - http_status: HTTP status code, always 200 on success.

       - methods: Array of authentication methods supported by this provider. Includes the type of the authentication method and the usage_fee (how much the user must pay for authorization using this method during recovery).

       - annual_fee: Fee the provider charges to store the recovery policy for one year.

       - truth_upload_fee: Fee the provider charges to store a key share.

       - liability_limit: Amount the provider can be held liable for in case a key share or recovery document cannot be recovered due to provider failures.

       - currency: Currency in which the provider wants to be paid, will match all of the fees.

       - storage_limit_in_megabytes: Maximum size of an upload (for both recovery document and truth data) in megabytes.

       - provider_name: Human-readable name of the provider’s business.

       - salt: Salt value used by the provider, used to derive the user’s identity at this provider. Should be unique per provider, and must never change for a given provider.  The salt is base32 encoded.

If contacting the provider failed, the information returned is:

       - http_status: HTTP status code (if available, possibly 0 if we did not even obtain an HTTP response).

       - error_code: Taler error code, never 0.

add_provider:

This operation can be performed in state USER_ATTRIBUTES_COLLECTING.  It adds one or more Anastasis providers to the list of providers the reducer should henceforth consider.  Note that removing providers is not possible at this time.

Here, the client must provide an array with the base URLs of the providers to add, for example:

     {
       "urls": [
         "http://localhost:8888/",
         "http://localhost:8089/"
       ]
     }

Note that existing providers will remain in the state.  The following is an example for an expected new state where the service on port 8089 is unreachable, the service on port 8088 was previously known, and service on port 8888 was now added:

     {
       "backup_state": "USER_ATTRIBUTES_COLLECTING",
       "authentication_providers": {
         "http://localhost:8089/": {
           "error_code": 11,
           "http_status": 0
         },
         "http://localhost:8088/": {
           "http_status": 200,
           "methods": [
             { "type" : "question",
               "usage_fee" : "EUR:0.01" },
             { "type" : "sms",
               "usage_fee" : "EUR:0.55" }
           ],
           "annual_fee": "EUR:0.99",
           "truth_upload_fee": "EUR:3.99",
           "liability_limit": "EUR:1",
           "currency": "EUR",
           "truth_lifetime": { "d_ms" : 50000000 },
           "storage_limit_in_megabytes": 1,
           "provider_name": "Anastasis 4",
           "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
         }
         "http://localhost:8888/": {
           "methods": [
             { "type" : "question",
               "usage_fee" : "EUR:0.01" },
             { "type" : "sms",
               "usage_fee" : "EUR:0.55" }
           ],
           "annual_fee": "EUR:0.99",
           "truth_upload_fee": "EUR:3.99",
           "liability_limit": "EUR:1",
           "currency": "EUR",
           "truth_lifetime": { "d_ms" : 50000000 },
           "storage_limit_in_megabytes": 1,
           "provider_name": "Anastasis 42",
           "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
         }
       }
     }

Backup transitions
..................

enter_user_attributes:

This transition provides the user’s personal attributes. The specific set of attributes required depends on the country of residence of the user.  Some attributes may be optional, in which case they should be omitted entirely (that is, not simply be set to null or an empty string).  Example arguments would be:

     {
       "identity_attributes": {
         "full_name": "Max Musterman",
         "social_security_number": "123456789",
         "birthdate": "2000-01-01",
         "birthplace": "Earth"
      }
     }

Note that at this stage, the state machines between backup and recovery diverge and the recovery_state will begin to look very different from the backup_state.

For backups, if all required attributes are present, the reducer will transition to an AUTHENTICATIONS_EDITING state with the attributes added to it:

     {
       "backup_state": "AUTHENTICATIONS_EDITING",
       "identity_attributes": {
         "full_name": "Max Musterman",
         "social_security_number": "123456789",
         "birthdate": "2000-01-01",
         "birthplace": "Earth"
       }
     }

If required attributes are missing, do not match the required regular expression, or fail the custom validation logic, the reducer SHOULD transition to an error state indicating what was wrong about the input.  A reducer that does not support some specific validation logic MAY accept the invalid input and proceed anyway.  The error state will include a Taler error code that is specific to the failure, and optional details.  Example:

     {
       "backup_state": "ERROR",
       "code": 8404,
       "hint": "An input did not match the regular expression.",
       "detail": "social_security_number"
     }

Clients may safely repeat this transition to validate the user’s inputs until they satisfy all of the constraints.  This way, the user interface does not have to perform the input validation directly.

add_authentication:

This transition adds an authentication method.  The method must be supported by one or more providers that are included in the current state.  Adding an authentication method requires specifying the type and instructions to be given to the user.  The challenge is encrypted and stored at the Anastasis provider. The specific semantics of the value depend on the type.  Typical challenges values are a phone number (to send an SMS to), an e-mail address (to send a PIN code to) or the answer to a security question.  Note that these challenge values will still be encrypted (and possibly hashed) before being given to the Anastasis providers.

Note that the challenge must be given in Crockford Base32 encoding, as it MAY include binary data (such as a photograph of the user).  In the latter case, the optional mime_type field must be provided to give the MIME type of the value encoded in challenge.

     {
       "authentication_method":
       {
         "type": "question",
         "mime_type" : "text/plain",
         "instructions" : "What is your favorite GNU package?",
         "challenge" : "E1QPPS8A",
       }
     }

If the information provided is valid, the reducer will add the new authentication method to the array of authentication methods:

     {
       "backup_state": "AUTHENTICATIONS_EDITING",
       "authentication_methods": [
         {
           "type": "question",
           "mime_type" : "text/plain",
           "instructions" : "What is your favorite GNU package?",
           "challenge" : "E1QPPS8A",
         },
         {
           "type": "email",
           "instructions" : "E-mail to user@*le.com",
           "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
         }
       ]
     }

delete_authentication:

This transition can be used to remove an authentication method from the array of authentication methods. It simply requires the index of the authentication method to remove. Note that the array is 0-indexed:

     {
       "authentication_method": 1
     }

Assuming we begin with the state from the example above, this would remove the email authentication method, resulting in the following response:

     {
       "backup_state": "AUTHENTICATIONS_EDITING",
       "authentication_methods": [
         {
           "type": "question",
           "mime_type" : "text/plain",
           "instructions" : "What is your favorite GNU package?",
           "challenge" : "gdb",
         }
       ]
     }

If the index is invalid, the reducer will instead transition into an ERROR state.

next (from AUTHENTICATIONS_EDITING):

This transition confirms that the user has finished adding (or removing) authentication methods, and that the system should now automatically compute a set of reasonable recovery policies.

This transition does not take any mandatory arguments.  Optional arguments can be provided to upload the recovery document only to a specific subset of the providers:

     {
       "providers": [
         "http://localhost:8088/",
         "http://localhost:8089/"
       ]
     }

The resulting state provides the suggested recovery policies in a way suitable for presentation to the user:

     {
       "backup_state": "POLICIES_REVIEWING",
       "policy_providers" : [
           { "provider_url" : "http://localhost:8088/" },
           { "provider_url" : "http://localhost:8089/" }
       ],
       "policies": [
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8088/"
             },
             {
               "authentication_method": 1,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8087/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8088/"
             },
             {
               "authentication_method": 1,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 3,
               "provider": "http://localhost:8089/"
             }
           ]
         }
       ]
     }

For each recovery policy, the state includes the specific details of which authentication methods must be solved to recovery the secret using this policy.  The methods array specifies the index of the authentication_method in the authentication_methods array, as well as the provider that was selected to supervise this authentication.

If no authentication method was provided, the reducer will transition into an ERROR state instead of suggesting policies.

add_policy:

Using this transition, the user can add an additional recovery policy to the state.  The argument format is the same that is used in the existing state. An example for a possible argument would thus be:

     {
       "policy": [
         {
           "authentication_method": 1,
           "provider": "http://localhost:8088/"
         },
         {
           "authentication_method": 3,
           "provider": "http://localhost:8089/"
         }
       ]
     }

Note that the specified providers must already be in the authentication_providers of the state. You cannot add new providers at this stage.  The reducer will simply attempt to append the suggested policy to the “policies” array, returning an updated state:

     {
       "backup_state": "POLICIES_REVIEWING",
       "policies": [
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 1,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 1,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 1,
               "provider": "http://localhost:8088/"
             },
             {
               "authentication_method": 3,
               "provider": "http://localhost:8089/"
             }
           ]
         }
       ]
     }

If the new policy is invalid, for example because it adds an unknown authentication method, or the selected provider does not support the type of authentication, the reducer will transition into an ERROR state instead of adding the new policy.

update_policy:

Using this transition, the user can modify an existing recovery policy in the state. The argument format is the same that is used in add_policy, except there is an additional key policy_index which identifies the policy to modify. An example for a possible argument would thus be:

     {
       "policy_index" : 1,
       "policy": [
         {
           "authentication_method": 1,
           "provider": "http://localhost:8088/"
         },
         {
           "authentication_method": 3,
           "provider": "http://localhost:8089/"
         }
       ]
     }

If the new policy is invalid, for example because it adds an unknown authentication method, or the selected provider does not support the type of authentication, the reducer will transition into an ERROR state instead of modifying the policy.

delete_policy:

This transition allows the deletion of a recovery policy. The argument simply specifies the index of the policy to delete, for example:

     {
       "policy_index": 3
     }

Given as input the state from the example above, the expected new state would be:

     {
       "backup_state": "POLICIES_REVIEWING",
       "policies": [
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 1,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 1,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8088/"
             }
           ]
         }
       ]
     }

If the index given is invalid, the reducer will transition into an ERROR state instead of deleting a policy.

delete_challenge:

This transition allows the deletion of an individual challenge from a recovery policy. The argument simply specifies the index of the policy and challenge to delete, for example:

     {
       "policy_index": 1,
       "challenge_index" : 1
     }

Given as input the state from the example above, the expected new state would be:

     {
       "backup_state": "POLICIES_REVIEWING",
       "policies": [
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 1,
               "provider": "http://localhost:8088/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 0,
               "provider": "http://localhost:8089/"
             }
           ]
         },
         {
           "methods": [
             {
               "authentication_method": 1,
               "provider": "http://localhost:8089/"
             },
             {
               "authentication_method": 2,
               "provider": "http://localhost:8088/"
             }
           ]
         }
       ]
     }

If the index given is invalid, the reducer will transition into an ERROR state instead of deleting a challenge.

next (from POLICIES_REVIEWING):

Using this transition, the user confirms that the policies in the current state are acceptable. The transition does not take any arguments.

The reducer will simply transition to the SECRET_EDITING state:

     {
       "backup_state": "SECRET_EDITING",
       "upload_fees" : [ "KUDOS:42" ],
       "expiration" : { "t_ms" : 1245362362 }
     }

Here, upload_fees is an array of applicable upload fees for the given policy expiration time. This is an array because fees could be in different currencies.  The final cost may be lower if the user already paid for some of the time.

If the array of policies is currently empty, the reducer will transition into an ERROR state instead of allowing the user to continue.

enter_secret:

This transition provides the reducer with the actual core secret of the user that Anastasis is supposed to backup (and possibly recover). The argument is simply the Crockford-Base32 encoded value together with its mime type, or a text field with a human-readable secret text. For example:

     {
       "secret": {
          "value": "EDJP6WK5EG50",
          "mime" : "text/plain"
       },
       "expiration" : { "t_ms" : 1245362362 }
     }

If the application is unaware of the format, it set the mime field to null. The expiration field is optional.

The reducer remains in the SECRET_EDITING state, but now the secret and updated expiration time are part of the state and the cost calculations will be updated.

     {
       "backup_state": "SECRET_EDITING",
       "core_secret" : {
          "value": "EDJP6WK5EG50",
          "mime" : "text/plain"
       },
       "expiration" : { "t_ms" : 1245362362 },
       "upload_fees" : [ "KUDOS:42" ]
     }

clear_secret:

This transition removes the core secret from the state.  It is simply a convenience function to undo enter_secret without providing a new value immediately. The transition takes no arguments.  The resuting state will no longer have the core_secret field, and be otherwise unchanged. Calling clear_secret on a state without a core_secret will result in an error.

enter_secret_name:

This transition provides the reducer with a name for the core secret of the user. This name will be given to the user as a hint when seleting a recovery policy document during recovery, prior to satisfying any of the challenges. The argument simply contains the name for the secret. Applications that have build-in support for Anastasis MUST prefix the secret name with an underscore and an application-specific identifier registered in GANA so that they can use recognize their own backups. An example argument would be:

     {
       "name": "_TALERWALLET_MyPinePhone",
     }

Here, MyPinePhone might be chosen by the user to identify the device that was being backed up.

The reducer remains in the SECRET_EDITING state, but now the secret name is updated:

     {
       "secret_name" : "_TALERWALLET_MyPinePhone"
     }

update_expiration:

This transition asks the reducer to change the desired expiration time and to update the associated cost. For example:

     {
       "expiration" : { "t_ms" : 1245362362 }
     }

The reducer remains in the SECRET_EDITING state, but the expiration time and cost calculation will be updated.

     {
       "backup_state": "SECRET_EDITING",
       "expiration" : { "t_ms" : 1245362362 },
       "upload_fees" : [ { "fee": "KUDOS:43" } ]
     }

next (from SECRET_EDITING):

Using this transition, the user confirms that the secret and expiration settings in the current state are acceptable. The transition does not take any arguments.

If the secret is currently empty, the reducer will transition into an ERROR state instead of allowing the user to continue.

After adding a secret, the reducer may transition into different states depending on whether payment(s) are necessary.  If payments are needed, the secret will be stored in the state under core_secret.  Applications should be careful when persisting the resulting state, as the core_secret is not protected in the PAYING states.  The PAYING states only differ in terms of what the payments are for (key shares or the recovery document), in all cases the state simply includes an array of Taler URIs that refer to payments that need to be made with the Taler wallet.

If all payments are complete, the reducer will transition into the BACKUP_FINISHED state and (if applicable) delete the core_secret as an additional safety measure.

Example results are thus:

     {
       "backup_state": "TRUTHS_PAYING",
       "secret_name" : "$NAME",
       "core_secret" : { "$anything":"$anything" },
       "payments": [
         "taler://pay/...",
         "taler://pay/..."
       ]
     }

     {
       "backup_state": "POLICIES_PAYING",
       "secret_name" : "$NAME",
       "core_secret" : { "$anything":"$anything" },
       "payments": [
         "taler://pay/...",
         "taler://pay/..."
       ]
     }

     {
       "backup_state": "BACKUP_FINISHED",
     }

pay:

This transition suggests to the reducer that a payment may have been made or is immanent, and that the reducer should check with the Anastasis service provider to see if the operation is now possible.  The operation takes one optional argument, which is a timeout value that specifies how long the reducer may wait (in long polling) for the payment to complete:

     {
       "timeout":  { "d_ms" : 5000 },
     }

The specified timeout is passed on to the Anastasis service provider(s), which will wait this long before giving up.  If no timeout is given, the check is done as quickly as possible without additional delays.  The reducer will continue to either an updated state with the remaining payment requests, to the BACKUP_FINISHED state (if all payments have been completed and the backup finished), or into an ERROR state in case there was an irrecoverable error, indicating the specific provider and how it failed.  An example for this final error state would be:

     {
       "backup_state": "ERROR",
       "http_status" : 500,
       "upload_status" : 52,
       "provider_url" : "https://bad.example.com/",
     }

Here, the fields have the following meaning:

       - http_status is the HTTP status returned by the Anastasis provider.

       - upload_status is the Taler error code return by the provider.

       - provider_url is the base URL of the failing provider.

In the above example, 52 would thus imply that the Anastasis provider failed to store information into its database.

Recovery transitions
....................

enter_user_attributes:

This transition provides the user’s personal attributes. The specific set of attributes required depends on the country of residence of the user.  Some attributes may be optional, in which case they should be omitted entirely (that is, not simply be set to null or an empty string).  The arguments are identical to the enter_user_attributes transition from the backup process.  Example arguments would thus be:

     {
       "identity_attributes": {
         "full_name": "Max Musterman",
         "social_security_number": "123456789",
         "birthdate": "2000-01-01",
         "birthplace": "Earth"
       }
     }

However, in contrast to the backup process, the reducer will attempt to retrieve the latest recovery document from all known providers for the selected currency given the above inputs.  If a recovery document was found by any provider, the reducer will attempt to load it and transition to a state where the user can choose which challenges to satisfy:

     {
       "recovery_state": "CHALLENGE_SELECTING",
       "recovery_information": {
         "challenges": [
           {
             "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
             "cost": "TESTKUDOS:0",
             "type": "question",
             "instructions": "q1"
           },
           {
             "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
             "cost": "TESTKUDOS:0",
             "type": "email",
             "instructions": "e-mail address m?il@f*.bar"
           },
         ],
         "policies": [
           [
             {
               "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
             },
             {
               "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
             },
           ],
         ],
         "provider_url": "http://localhost:8088/",
         "version": 1,
       },
       "recovery_document": {
         "...": "..."
       }
     }

The recovery_document is an internal representation of the recovery information and of no concern to the user interface. The pertinent information is in the recovery_information. Here, the challenges array is a list of possible challenges the user could attempt to solve next, while policies is an array of policies, with each policy being an array of challenges. Satisfying all of the challenges of one of the policies will enable the secret to be recovered.  The provider_url from where the recovery document was obtained and its version are also provided.  Each challenge comes with four mandatory fields:

       - uuid: A unique identifier of the challenge; this is what the UUIDs in the policies array refer to, but also this UUID may be included in messages sent to the user. They allow the user to distinguish different PIN/TANs should say the same phone number be used for SMS-authentication with different providers.

       - cost: This is the amount the Anastasis provider will charge to allow the user to pass the challenge.

       - type: This is the type of the challenge, as a string.

       - instructions: Contains additional important hints for the user to allow the user to satisfy the challenge.  It typically includes an abbreviated form of the contact information or the security question. Details depend on type.

If a recovery document was not found, either the user never performed a backup, entered incorrect attributes, or used a provider not yet in the list of Anastasis providers.  Hence, the user must now either select a different provider, or go back and update the identity attributes.  In the case a recovery document was not found, the transition fails, returning the error code and a human-readable error message together with a transition failure:

     {
       "recovery_state": "ERROR",
       "error_message": "account unknown to Anastasis server",
       "error_code": 9,
     }

Here, the error_code is from the enum ANASTASIS_RecoveryStatus and describes precisely what failed about the download, while the error_message is a human-readable (English) explanation of the code. Applications may want to translate the message using GNU gettext; translations should be available in the anastasis text domain. However, in general it should be sufficient to display the slightly more generic Taler error code that is returned with the new state.

change_version:

Even if a recovery document was found, it is possible that the user intended to recover a different version, or recover a backup where the recovery document is stored at a different provider. Thus, the reducer allows the user to explicitly switch to a different provider or recovery document version using the change_version transition, which takes a provider URL and policy version as arguments:

     {
       "provider_url": "https://localhost:8080/",
       "version": 2
     }

Note that using a version of 0 implies fetching “the latest version”.  The resulting states are the same as those of the enter_user_attributes transition, except that the recovery document version is not necessarily the latest available version at the provider.

select_challenge:

Selecting a challenge takes different, depending on the state of the payment. A comprehensive example for select_challenge would be:

     {
         "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
         "timeout" : { "d_ms" : 5000 },
         "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
     }

The uuid field is mandatory and specifies the selected challenge. The other fields are optional, and are needed in case the user has previously been requested to pay for the challenge.  In this case, the payment_secret identifies the previous payment request, and timeout says how long the Anastasis service should wait for the payment to be completed before giving up (long polling).

Depending on the type of the challenge and the need for payment, the reducer may transition into CHALLENGE_SOLVING or CHALLENGE_PAYING states.  In CHALLENGE_SOLVING, the new state will primarily specify the selected challenge:

     {
       "backup_state": "CHALLENGE_SOLVING",
       "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
     }

In CHALLENGE_PAYING, the new state will include instructions for payment in the challenge_feedback. In general, challenge_feedback includes information about attempted challenges, with the final state being solved:

     {
       "recovery_state": "CHALLENGE_SELECTING",
       "recovery_information": {
         "...": "..."
       }
       "challenge_feedback": {
         "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
           "state" : "solved"
         }
       }
     }

Challenges feedback for a challenge can have many different state values that applications must all handle. States other than solved are:

       - payment: Here, the user must pay for a challenge. An example would be:

               {
                 "backup_state": "CHALLENGE_PAYING",
                 "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
                 "challenge_feedback": {
                   "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : {
                    "state" : "payment",
                    "taler_pay_uri" : "taler://pay/...",
                    "provider" : "https://localhost:8080/",
                    "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
                   }
                 }
               }

            - body: Here, the server provided an HTTP reply for how to solve the challenge, but the reducer could not parse them into a known format. A mime-type may be provided and may help parse the details.

                    {
                      "recovery_state": "CHALLENGE_SOLVING",
                      "recovery_information": {
                          "...": "..."
                      }
                      "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                      "challenge_feedback": {
                        "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                          "state": "body",
                          "body": "CROCKFORDBASE32ENCODEDBODY",
                          "http_status": 403,
                          "mime_type" : "anything/possible"
                        }
                      }
                    }

            - hint: Here, the server provided human-readable hint for how to solve the challenge.  Note that the hint provided this time is from the Anastasis provider and may differ from the instructions for the challenge under recovery_information:

                    {
                      "recovery_state": "CHALLENGE_SOLVING",
                      "recovery_information": {
                          "...": "..."
                      }
                      "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                      "challenge_feedback": {
                        "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                          "state": "hint",
                          "hint": "Recovery TAN send to email mail@DOMAIN",
                          "http_status": 403
                        }
                      }
                    }

            - details: Here, the server provided a detailed JSON status response related to solving the challenge:

                    {
                      "recovery_state": "CHALLENGE_SOLVING",
                      "recovery_information": {
                          "...": "..."
                      }
                      "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                      "challenge_feedback": {
                        "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                          "state": "details",
                          "details": {
                            "code": 8111,
                            "hint": "The client's response to the challenge was invalid.",
                            "detail" : null
                          },
                          "http_status": 403
                        }
                      }
                    }

                 - redirect: To solve the challenge, the user must visit the indicated Web site at redirect_url, for example to perform video authentication:

                         {
                           "recovery_state": "CHALLENGE_SOLVING",
                           "recovery_information": {
                               "...": "..."
                           }
                           "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                           "challenge_feedback": {
                             "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                               "state": "redirect",
                               "redirect_url": "https://videoconf.example.com/",
                               "http_status": 303
                             }
                           }
                         }

                      - server-failure: This indicates that the Anastasis provider encountered a failure and recovery using this challenge cannot proceed at this time. Examples for failures might be that the provider is unable to send SMS messages at this time due to an outage.  The body includes details about the failure. The user may try again later or continue with other challenges.

                         {
                           "recovery_state": "CHALLENGE_SELECTING",
                           "recovery_information": {
                               "...": "..."
                           }
                           "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                           "challenge_feedback": {
                             "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                               "state": "server-failure",
                               "http_status": "500",
                               "error_code": 52
                             }
                           }
                         }

                      - truth-unknown: This indicates that the Anastasis provider is unaware of the specified challenge. This is typically a permanent failure, and user interfaces should not allow users to re-try this challenge.

                         {
                           "recovery_state": "CHALLENGE_SELECTING",
                           "recovery_information": {
                               "...": "..."
                           }
                           "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                           "challenge_feedback": {
                             "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                               "state": "truth-unknown",
                               "error_code": 8108
                             }
                           }
                         }

                      - rate-limit-exceeded:

                         {
                           "recovery_state": "CHALLENGE_SELECTING",
                           "recovery_information": {
                               "...": "..."
                           }
                           "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
                           "challenge_feedback": {
                             "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": {
                               "state": "rate-limit-exceeded",
                               "error_code": 8121
                             }
                           }
                         }

pay:

With a pay transition, the application indicates to the reducer that a payment may have been made. Here, it is again possible to specify an optional timeout argument for long-polling, for example:

     {
         "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS"
         "timeout" : { "d_ms" : 5000 },
     }

Depending on the type of the challenge and the result of the operation, the new state may be CHALLENGE_SOLVING (if say the SMS was now sent to the user), CHALLENGE_SELECTING (if the answer to the security question was correct), RECOVERY_FINISHED (if this was the last challenge that needed to be solved) or still CHALLENGE_PAYING (if the challenge was not actually paid for).  For sample messages, see the different types of challenge_feedback in the section about select_challenge.

solve_challenge:

Solving a challenge takes various formats, depending on the type of the challenge and what is known about the answer.  The different supported formats are:

     {
         "answer": "answer to security question"
     }

     {
         "pin": 1234
     }

     {
         "hash": "SOMEBASE32ENCODEDHASHVALUE"
     }

Authentication Methods
======================

This section describes the supported authentication methods in detail.  We note that the server implements rate limiting for all authentication methods to ensure that malicious strong attackers cannot guess the values by brute-force. Typically, a user is given three attempts per hour to enter the correct code from 2^63 possible values.  Transmitted codes also come with an expiration date. If the user re-requests a challenge to be sent, the same challenge may be transmitted (with the three attempts counter not increasing!) for a limited period of time (depending on the authentication method) before the service eventually rotates to a fresh random code with a fresh retry counter. Given the default value range and time intervals (which providers are at liberty to adjust), brute-force attacks against this are expected to succeed with a 50% probability after about 200000 years of attempts at the maximum permissible frequency.

SMS (sms)
---------

Sends an SMS with a code (prefixed with A-) to the user’s phone, including a UUID which identifies the challenge the code is for.  The user must send this code back with his request (see $RESPONSE under Managing truth). If the transmitted code is correct, the server responses with the requested encrypted key share.

Email verification (email)
--------------------------

Sends an email with a code (prefixed with A-) to the user’s mail address, including a UUID which identifies the challenge the code is for.  The user must send this code back with his request (see $RESPONSE under Managing truth). If the transmitted code is correct, the server responses with the requested encrypted key share.

Video identification (vid)
--------------------------

Requires the user to identify via video-call.  In the video-call, the user is told the code (prefixed with A-) needed to authenticate.

The user is expected to delete all metadata revealing personal information from the images before uploading them. Since the respective images must be passed on to the video identification service in the event of password recovery, it should be ensured that no further information about the user can be derived from them.

Video identification will typically result in the Anastasis provider requesting the user to be redirected to a Web site (or other URL) for the video-call.

Security question (qa)
----------------------

Asks the user a security question.  The user sends back a salted hash over the answer.  The question-salt is stored encrypted as part of the recovery document and never revealed to the providers. This ensures that providers cannot derive the answer from the hash value. Furthermore, the security question itself is also only in the recovery document and never given to the Anastasis provider.  A moderately expensive hash function is used to further limit strong attackers that have obtained the recovery document from brute-forcing the answer.

If the hash value matches with the one the server is expecting, the server answers with the requested encrypted key share.  However, unlike other encrypted key shares, the encrypted key share of a security question uses a special variation of the Anastasis encryption: Here, a different hash function over the security answer is used to provide an additional key-salt for the decryption of the (encrypted) key share.  This ensures that the key share remains irrecoverable without the answer even if the Anastasis provider storing the security question is malicious.

Snail mail verification (post)
------------------------------

Sends physical mail (snail mail) with a code (prefixed with A-) to the user’s mail address, including a UUID which identifies the challenge the code is for.  The user must send this code back with their request (see $RESPONSE under Managing truth).  If the transmitted code is correct, the server responds with the requested encrypted key share.

DB Schema
=========

Design Documents
================

This is a collection of design documents related to Anastasis. The goal of these documents is to discuss facilitate discussion around new features while keeping track of the evolution of the whole system and protocol.

Design Doc 001: Anastasis User Experience
-----------------------------------------

Summary
.......

This document describes the recommended way of implementing the user experience of setting up and making use of Introduction account recovery.

Motivation
..........

Wallet state consisting of digital cash, transaction history etc. should not be lost. Taler provides a backup mechanism to prevent that. As an additional protection measure Anastasis can be used to provide access to the backup, even if all devices and offline secrets have been lost.

Access to the backup key is shared with escrow providers that can be chosen by the user.

Setup Steps
...........

[graphviz]

Entry point: Settings
.....................

The app settings should have a section for Anastasis using a different more universally understood name like Wallet Recovery.

The section should have an option to setup Anastasis initially.  This option should be disabled as long as no backup has been set up.  The section could maybe be integrated into the backup settings.

Providing Identification
........................

Instead of a forgettable freely chosen user name, Anastasis collects various static information from the user to generate a unique user identifier from that.  Examples for such identifier would be a concatenation of the full name of the user and their social security or passport number(s).

The information that can reasonably used here various from cultural context and jurisdiction.  Therefore, one idea is to start by asking for continent and then the country of primary legal residence, and then continue from there with country-specific attributes (and also offer a stateless person option).

Special care should be taken to avoid that information can later be provided ambiguously thus changing the user identifier and not being able to restore the user’s data.  This can be typographic issues like someone providing “Seestr.”  and later “Seestrasse” or “Seestraße” or “seestrasse”.  But it can also be simple typos that we can only prevent in some instances like when checking checksums in passport numbers.

The user should be made aware that this data will not leave the app and that it is only used to compute a unique identifier that can not be forgotten.

If possible, we should guide the user in the country selection by accessing permission-less information such as the currently set language/locale and the country of the SIM card.  But nothing invasive like the actual GPS location.

Add Authentication Methods
..........................

After creating a unique identifier, the user can chose one or more Authentication Methods supported by Anastasis.

When selecting a method, the user is already asked to provide the information required for the recovery with that method.  For example, a photo of themselves, their phone number or mailing address.

The user interface validates that the inputs are well-formed, and refuses inputs that are clearly invalid. Where possible, it pre-fills the fields with sane values (phone number, e-mail addresses, country of residence).

Confirm/Change Service Providers
................................

From the dialog where the user is adding authentication methods, the user can optionally jump to a side-action with list of available providers (and their status) and possibly add additional providers that are not included in the default list provided by the wallet.

Defining Recovery Options
.........................

After mapping authentication methods to providers, the user needs select which combinations are sufficient to recover the secret.  Here, the system pre-computes a reasonably sane allocation, for small n the default could be n-1 out of n.

We should propose a mapping of authentication methods to providers by minimizing cost (tricky: sign-up vs. recovery costs, different currencies) and distributing the selected authentication methods across as many providers as possible.

The user should be able to change the proposed default selection and add more than one provider to each chosen method.

Using Anastatis providers usually is not free.  From here on, the UI should show estimated recurring costs (yearly) and the cost of recovery.  These costs should get updated with each user action affecting those costs such as when the user reconfigures the policies.

Pay for Setup
.............

As the last step when all information has been properly provided, the user is asked to pay for the service with the regular wallet payment confirmation screen.

Show Service Status After Setup
...............................

TODO

Recovery Steps
..............

[graphviz]

Entry point: Settings
.....................

Like the backup, the recovery option should be available via the App settings.

The section should have an option to recover from backup.  If a previous recovery was not completed, the interaction should resume from that previous checkpoint instead of from the beginning.

Providing Identification
........................

The first dialog(s) during recovery should be identical to the first dialog during backup: the user is asked to select a continent, country of residence and then to provide country-specific inputs for identification.

Select Authentication Challenge
...............................

If Anastasis could recover the recovery document via any provider, it should show a dialog allowing the user to select one of the open challenges, and highlight which challenges still need to be satisfied for the various policies.

Additionally, the specific provider and recovery document version should be shown. The user should be able to change the provider or recovery document version, resulting in a switch of the recovery document and policies. If the user has already satisfied some challenges of the current recovery document, switching to a different recovery document should only be done after a confirmation pop-up dialog warning the user that the existing progress will be lost.

When selecting a challenge, the user may be asked to confirm making a payment for this challenge if the provider requires payment.

Payment
.......

Typcially, this would be the canonical wallet payment confirmation dialog.

However, in the case of a security question, the payment confirmation should be combined with the dialog where the user enters the security answer (so instead of an Ok button, text showing the amount due and Pay should be used – except of course if the security question challenge is free of charge).

Enter Challenge Response
........................

If the challenge was not a security question, the dialog to enter the security code (PIN/TAN) should open after payment.  The security code field should have a prefix A-. However, the user should be able to enter both only the numeric code, or the full code with the A- prefix (or ideally, the user cannot delete the pre-filled A- text).

Success
.......

The user is informed about the successful recovery.  We may want to do this as part of a separate screen, or simply with a notification bar in the main wallet screen.

Template
--------

Summary
.......

Motivation
..........

Requirements
............

Proposed Solution
.................

Alternatives
............

Drawbacks
.........

Discussion / Q&A
................

(This should be filled in with results from discussions on mailing lists / personal communication.)

Anastasis licensing information
===============================

This file gives an overview of all Anastasis component’s licensing and of runtime dependencies thereof. For “component” here is meant a set of source files which can be retrieved from a single repository.  If components consist of sources under different licensing regimes, i.e. because we want to enable third party developments to easily integrate with Taler, those are described as well.

All Anastasis components are generally released under the Affero GPL.

Anastasis (git://git.taler.net/anastasis)
-----------------------------------------

Anastasis core logic is under AGPL.

Runtime dependencies
....................

The following list encompasses all the runtime dependencies for this project, and gives the copyright holder for each of them:

  * libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals

  * libgcrypt: LGPL, owned by Free Software Foundation

  * postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL Global Development Group

  * libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V.

  * libgnunetjson: GPLv3+, GNUnet e.V.

  * GNU Taler: LGPLv3+ / GPLv3+ / AGPLv3+: owned by Taler Systems SA

Anastasis-gtk (git://git.taler.net/anastasis-gtk)
-------------------------------------------------

Anastasis-gtk is under AGPL.

Runtime dependencies
....................

The following list encompasses all the runtime dependencies for this project, and gives the copyright holder for each of them:

  * libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals

  * libgcrypt: LGPL, owned by Free Software Foundation

  * postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL Global Development Group

  * libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V.

  * libgnunetjson: GPLv3+, GNUnet e.V.

  * libgnunetgtk: GPLv3+, GNUnet e.V.

  * GNU Taler: LGPLv3+ / GPLv3+ / AGPLv3+: owned by Taler Systems SA

Documentation
-------------

The documentation is licensed under the GNU Free Documentation License Version 1.3 or later.

Man Pages
=========

anastasis-config(1)
-------------------

Synopsis
........

anastasis-config [-b backend | ––supported-backend=backend] [-c filename | ––config=filename] [-f | ––filename] [-F | ––full] [-h | ––help] [-L loglevel | ––loglevel=loglevel] [-l filename | ––logfile=‌filename] [-o option | ––option=option] [-r | ––rewrite] [-S | ––list-sections] [-s section | ––section=section] [-V value | ––value=value] [-v | ––version]

Description
...........

anastasis-config can be used to read or modify Anastasis configuration files.

-b BACKEND | ––supported-backend=BACKEND

     Tests whether the specified BACKEND is supported by the current installation. The backend must match the name of a plugin, i.e. “namestore_postgres” for the Postgres database backend of the “NAMESTORE” service.  If BACKEND is supported, anastasis-config will return a status code of 0 (success), otherwise 77 (unsupported).  When this option is specified, no other options may be specified. Specifying this option together with other options will cause anastasis-config to return a status code of 1 (error).

-c FILENAME | ––config=FILENAME

     Use the configuration file FILENAME.

-f | ––filename

     Try to perform expansions as if the option values represent filenames (will also be applied even if the option is not really a filename).

-F | ––full

     Write the full configuration file, not just the differences to the defaults.

-h | ––help

     Print short help on options.

-L LOGLEVEL | ––loglevel=LOGLEVEL

     Use LOGLEVEL for logging. Valid values are DEBUG, INFO, WARNING, and ERROR.

-l FILENAME | ––logfile=‌FILENAME

     Send logging output to FILENAME.

-o OPTION | ––option=OPTION

     Which configuration option should be accessed or edited.  Required to set a value.  If not given, all values of a given section will be printed in the format “OPTION = VALUE”.

-r | ––rewrite

     Write the configuration file even if nothing changed. Will remove all comments!

-S | ––list-sections

     List available configuration sections for use with --section.

-s SECTION | ––section=SECTION

     Which configuration section should be accessed or edited. Required option.

-V VALUE | ––value=VALUE

     Configuration value to store in the given section under the given option. Must only be given together with -s and -o options.

     Note:

          Changing the configuration file with -V will remove comments and may reorder sections and remove @INLINE@ directives.

-v | ––version

     Print Anastasis version number.

See Also
........

anastasis.conf(5)

Bugs
....

Report bugs by using https://bugs.anastasis.lu or by sending electronic mail to <contact@anastasis.lu>.

anastasis-gtk(1)
----------------

Synopsis
........

anastasis-gtk [-c FILENAME | ––config=‌FILENAME] [-h | ––help] [-L LOGLEVEL | ––loglevel=‌LOGLEVEL] [-l FILENAME | ––logfile=‌FILENAME] [-v | ––version]

Description
...........

anastasis-gtk is a graphical tool to run Anastasis key recover and backup operations.

-c FILENAME | ––config=‌FILENAME

     Use the configuration from FILENAME.

-h | ––help

     Print short help on options.

-L LOGLEVEL | ––loglevel=‌LOGLEVEL

     Specifies the log level to use. Accepted values are: DEBUG, INFO, WARNING, ERROR.

-l FILENAME | ––logfile=‌FILENAME

     Send logging output to FILENAME.

-v | ––version

     Print version information.

See Also
........

anastasis-reducer(1), anastasis-httpd(1), anastasis.conf(5).

Bugs
....

Report bugs by using https://bugs.anastasis.lu/ or by sending electronic mail to <contact@anastasis.lu>.

anastasis-httpd(1)
------------------

Synopsis
........

anastasis-httpd

Description
...........

Banastasis-httpd is a command line tool to run the Anastasis (HTTP backend).  The required configuration and database must exist before running this command.

Its options are as follows:

-C | –connection-close

     Force each HTTP connection to be closed after each request.

-c FILENAME | ––config=‌FILENAME

     Use the configuration and other resources for the merchant to operate from FILENAME.

-h | ––help

     Print short help on options.

-v | ––version

     Print version information.

Signals
.......

anastasis-httpd responds to the following signals:

SIGTERM

     Sending a SIGTERM to the process will cause it to shutdown cleanly.

See also
........

anastasis-dbinit(1), anastasis-config(1), anastasis-gtk(1), anastasis-reducer(1)

Bugs
....

Report bugs by using https://bugs.anastasis.lu or by sending electronic mail to <contact@anastasis.lu>.

anastasis-reducer(1)
--------------------

Synopsis
........

anastasis-reducer [-a**_*JSON*_|_–arguments=JSON] [-b**_|_–backup] [-c FILENAME | ––config=‌FILENAME] [-h | ––help] [-L LOGLEVEL | ––loglevel=‌LOGLEVEL] [-l FILENAME | ––logfile=‌FILENAME] [-r**_|_–restore] [-v | ––version] COMMAND

Description
...........

anastasis-reducer is a command-line tool to run Anastasis key recover and backup operations using a reducer-style interface. The reducer will read the current state from standard input and write the resulting state to standard output.  A COMMAND must be given on the command line.  The arguments (if any) are to be given in JSON format to the -a option.  A list of commands can be found in the Reducer API chapter.

-a JSON | ––arguments=JSON

     Provide JSON inputs for the given command.

-b | –backup

     Begin fresh reducer operation for a back up operation.

-c FILENAME | ––config=‌FILENAME

     Use the configuration from FILENAME.

-h | ––help

     Print short help on options.

-L LOGLEVEL | ––loglevel=‌LOGLEVEL

     Specifies the log level to use. Accepted values are: DEBUG, INFO, WARNING, ERROR.

-l FILENAME | ––logfile=‌FILENAME

     Send logging output to FILENAME.

-r | –restore

     Begin fresh reducer operation for a restore operation.

-v | ––version

     Print version information.

See Also
........

anastasis-gtk(1), anastasis-httpd(1), anastasis.conf(5).

Bugs
....

Report bugs by using https://bugs.anastasis.lu/ or by sending electronic mail to <contact@anastasis.lu>.

anastasis.conf(5)
-----------------

Description
...........

The configuration file is line-oriented. Blank lines and whitespace at the beginning and end of a line are ignored. Comments start with # or % in the first column (after any beginning-of-line whitespace) and go to the end of the line.

The file is split into sections. Every section begins with “[SECTIONNAME]” and contains a number of options of the form “OPTION=VALUE”. There may be whitespace around the = (equal sign). Section names and options are case-insensitive.

The values, however, are case-sensitive. In particular, boolean values are one of YES or NO. Values can include whitespace by surrounding the entire value with " (double quote). Note, however, that there are no escape characters in such strings; all characters between the double quotes (including other double quotes) are taken verbatim.

Values that represent filenames can begin with a /bin/sh-like variable reference. This can be simple, such as $TMPDIR/foo, or complex, such as ${TMPDIR:-${TMP:-/tmp}}/foo. See [PATHS] (below).

Values that represent a time duration are represented as a series of one or more NUMBER UNIT pairs, e.g. 60 s, 4 weeks 1 day, 5 years 2 minutes.

Values that represent an amount are in the usual amount syntax: CURRENCY:VALUE.FRACTION, e.g. EUR:1.50. The FRACTION portion may extend up to 8 places.

Files containing default values for many of the options described below are installed under $ANASTASIS_PREFIX/share/taler/config.d/. The configuration file given with -c to Anastasis binaries overrides these defaults.

A configuration file may include another, by using the @INLINE@ directive, for example, in main.conf, you could write @INLINE@ sub.conf to include the entirety of sub.conf at that point in main.conf. .. TODO: Document ‘anastasis-config -V’ in light of ‘@INLINE@’ in taler-config(1).

GLOBAL OPTIONS
..............

The following options are from the [anastasis] section and used by the anastasis-httpd service.

PAYMENT_BACKEND_URL

     Base-URL of the Taler merchant backend instance to use for payments. FIXME: How do we pass the access token?

ANNUAL_FEE

     Annual fee to be paid for policy uploads, i.e. “EUR:1.5”.

TRUTH_UPLOAD_FEE

     Annual fee to be paid for truth uploads, i.e. “EUR:1.5”.

DB

     Database backend to use, only postgres is supported right now.

UPLOAD_LIMIT_MB

     Maximum upload size for policy uploads in megabytes. Default is 1.

ANNUAL_POLICY_UPLOAD_LIMIT

     Maximum number of policies uploaded per year of service. Default is 42.

BUSINESS_NAME

     Name of the business.

SERVER_SALT

     Must be set to a high-entropy random server salt that the provider must never change after the initial configuration.

PORT

     TCP port on which the HTTP service should listen on.

Authorization options
.....................

For each active authorization plugin, options must be configured in a section called [authorization-$PLUGIN] where $PLUGIN is the name of the authorization plugin.

COST

     Fee the user has to pay to obtain a challenge from this authorization plugin during recovery.

ENABLED

     yes to enable this plugin, no to disable.

COMMAND

     Helper command to run (only relevant for some plugins).

Postgres database configuration
...............................

The following options must be in the section [statis-postgres] if postgress was used for the database under DB in the [anastasis] section.

CONFIG

     Path under which the Postgres database is that the service should use, i.e. postgres://anastasis.

SEE ALSO
........

anastasis-httpd(1), anastasis-config(1)

BUGS
....

Report bugs by using https://bugs.anastasis.lu/ or by sending electronic mail to <contact@anastasis.lu>.

Complete Index
==============

GNU Free Documentation License
==============================

Version 1.3, 3 November 2008

Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. https://fsf.org/

Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed.

0. PREAMBLE
-----------

The purpose of this License is to make a manual, textbook, or other functional and useful document “free” in the sense of freedom: to assure everyone the effective freedom to copy and redistribute it, with or without modifying it, either commercially or noncommercially. Secondarily, this License preserves for the author and publisher a way to get credit for their work, while not being considered responsible for modifications made by others.

This License is a kind of “copyleft”, which means that derivative works of the document must themselves be free in the same sense. It complements the GNU General Public License, which is a copyleft license designed for free software.

We have designed this License in order to use it for manuals for free software, because free software needs free documentation: a free program should come with manuals providing the same freedoms that the software does. But this License is not limited to software manuals; it can be used for any textual work, regardless of subject matter or whether it is published as a printed book. We recommend this License principally for works whose purpose is instruction or reference.

1. APPLICABILITY AND DEFINITIONS
--------------------------------

This License applies to any manual or other work, in any medium, that contains a notice placed by the copyright holder saying it can be distributed under the terms of this License. Such a notice grants a world-wide, royalty-free license, unlimited in duration, to use that work under the conditions stated herein. The “Document”, below, refers to any such manual or work. Any member of the public is a licensee, and is addressed as “you”. You accept the license if you copy, modify or distribute the work in a way requiring permission under copyright law.

A “Modified Version” of the Document means any work containing the Document or a portion of it, either copied verbatim, or with modifications and/or translated into another language.

A “Secondary Section” is a named appendix or a front-matter section of the Document that deals exclusively with the relationship of the publishers or authors of the Document to the Document’s overall subject (or to related matters) and contains nothing that could fall directly within that overall subject. (Thus, if the Document is in part a textbook of mathematics, a Secondary Section may not explain any mathematics.) The relationship could be a matter of historical connection with the subject or with related matters, or of legal, commercial, philosophical, ethical or political position regarding them.

The “Invariant Sections” are certain Secondary Sections whose titles are designated, as being those of Invariant Sections, in the notice that says that the Document is released under this License. If a section does not fit the above definition of Secondary then it is not allowed to be designated as Invariant. The Document may contain zero Invariant Sections. If the Document does not identify any Invariant Sections then there are none.

The “Cover Texts” are certain short passages of text that are listed, as Front-Cover Texts or Back-Cover Texts, in the notice that says that the Document is released under this License. A Front-Cover Text may be at most 5 words, and a Back-Cover Text may be at most 25 words.

A “Transparent” copy of the Document means a machine-readable copy, represented in a format whose specification is available to the general public, that is suitable for revising the document straightforwardly with generic text editors or (for images composed of pixels) generic paint programs or (for drawings) some widely available drawing editor, and that is suitable for input to text formatters or for automatic translation to a variety of formats suitable for input to text formatters. A copy made in an otherwise Transparent file format whose markup, or absence of markup, has been arranged to thwart or discourage subsequent modification by readers is not Transparent. An image format is not Transparent if used for any substantial amount of text. A copy that is not “Transparent” is called “Opaque”.

Examples of suitable formats for Transparent copies include plain ASCII without markup, Texinfo input format, LaTeX input format, SGML or XML using a publicly available DTD, and standard-conforming simple HTML, PostScript or PDF designed for human modification. Examples of transparent image formats include PNG, XCF and JPG. Opaque formats include proprietary formats that can be read and edited only by proprietary word processors, SGML or XML for which the DTD and/or processing tools are not generally available, and the machine-generated HTML, PostScript or PDF produced by some word processors for output purposes only.

The “Title Page” means, for a printed book, the title page itself, plus such following pages as are needed to hold, legibly, the material this License requires to appear in the title page. For works in formats which do not have any title page as such, “Title Page” means the text near the most prominent appearance of the work’s title, preceding the beginning of the body of the text.

The “publisher” means any person or entity that distributes copies of the Document to the public.

A section “Entitled XYZ” means a named subunit of the Document whose title either is precisely XYZ or contains XYZ in parentheses following text that translates XYZ in another language. (Here XYZ stands for a specific section name mentioned below, such as “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.) To “Preserve the Title” of such a section when you modify the Document means that it remains a section “Entitled XYZ” according to this definition.

The Document may include Warranty Disclaimers next to the notice which states that this License applies to the Document. These Warranty Disclaimers are considered to be included by reference in this License, but only as regards disclaiming warranties: any other implication that these Warranty Disclaimers may have is void and has no effect on the meaning of this License.

2. VERBATIM COPYING
-------------------

You may copy and distribute the Document in any medium, either commercially or noncommercially, provided that this License, the copyright notices, and the license notice saying this License applies to the Document are reproduced in all copies, and that you add no other conditions whatsoever to those of this License. You may not use technical measures to obstruct or control the reading or further copying of the copies you make or distribute. However, you may accept compensation in exchange for copies. If you distribute a large enough number of copies you must also follow the conditions in section 3.

You may also lend copies, under the same conditions stated above, and you may publicly display copies.

3. COPYING IN QUANTITY
----------------------

If you publish printed copies (or copies in media that commonly have printed covers) of the Document, numbering more than 100, and the Document’s license notice requires Cover Texts, you must enclose the copies in covers that carry, clearly and legibly, all these Cover Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on the back cover. Both covers must also clearly and legibly identify you as the publisher of these copies. The front cover must present the full title with all words of the title equally prominent and visible. You may add other material on the covers in addition. Copying with changes limited to the covers, as long as they preserve the title of the Document and satisfy these conditions, can be treated as verbatim copying in other respects.

If the required texts for either cover are too voluminous to fit legibly, you should put the first ones listed (as many as fit reasonably) on the actual cover, and continue the rest onto adjacent pages.

If you publish or distribute Opaque copies of the Document numbering more than 100, you must either include a machine-readable Transparent copy along with each Opaque copy, or state in or with each Opaque copy a computer-network location from which the general network-using public has access to download using public-standard network protocols a complete Transparent copy of the Document, free of added material. If you use the latter option, you must take reasonably prudent steps, when you begin distribution of Opaque copies in quantity, to ensure that this Transparent copy will remain thus accessible at the stated location until at least one year after the last time you distribute an Opaque copy (directly or through your agents or retailers) of that edition to the public.

It is requested, but not required, that you contact the authors of the Document well before redistributing any large number of copies, to give them a chance to provide you with an updated version of the Document.

4. MODIFICATIONS
----------------

You may copy and distribute a Modified Version of the Document under the conditions of sections 2 and 3 above, provided that you release the Modified Version under precisely this License, with the Modified Version filling the role of the Document, thus licensing distribution and modification of the Modified Version to whoever possesses a copy of it. In addition, you must do these things in the Modified Version:

  - A. Use in the Title Page (and on the covers, if any) a title distinct from that of the Document, and from those of previous versions (which should, if there were any, be listed in the History section of the Document). You may use the same title as a previous version if the original publisher of that version gives permission.

  - B. List on the Title Page, as authors, one or more persons or entities responsible for authorship of the modifications in the Modified Version, together with at least five of the principal authors of the Document (all of its principal authors, if it has fewer than five), unless they release you from this requirement.

  - C. State on the Title page the name of the publisher of the Modified Version, as the publisher.

      4. Preserve all the copyright notices of the Document.

  - E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices.

  - F. Include, immediately after the copyright notices, a license notice giving the public permission to use the Modified Version under the terms of this License, in the form shown in the Addendum below.

  - G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice.

      8. Include an unaltered copy of this License.

  - I. Preserve the section Entitled “History”, Preserve its Title, and add to it an item stating at least the title, year, new authors, and publisher of the Modified Version as given on the Title Page. If there is no section Entitled “History” in the Document, create one stating the title, year, authors, and publisher of the Document as given on its Title Page, then add an item describing the Modified Version as stated in the previous sentence.

  - J. Preserve the network location, if any, given in the Document for public access to a Transparent copy of the Document, and likewise the network locations given in the Document for previous versions it was based on. These may be placed in the “History” section. You may omit a network location for a work that was published at least four years before the Document itself, or if the original publisher of the version it refers to gives permission.

  - K. For any section Entitled “Acknowledgements” or “Dedications”, Preserve the Title of the section, and preserve in the section all the substance and tone of each of the contributor acknowledgements and/or dedications given therein.

  - L. Preserve all the Invariant Sections of the Document, unaltered in their text and in their titles. Section numbers or the equivalent are not considered part of the section titles.

  - M. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version.

  - N. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section.

      15. Preserve any Warranty Disclaimers.

If the Modified Version includes new front-matter sections or appendices that qualify as Secondary Sections and contain no material copied from the Document, you may at your option designate some or all of these sections as invariant. To do this, add their titles to the list of Invariant Sections in the Modified Version’s license notice. These titles must be distinct from any other section titles.

You may add a section Entitled “Endorsements”, provided it contains nothing but endorsements of your Modified Version by various partiesâ€”for example, statements of peer review or that the text has been approved by an organization as the authoritative definition of a standard.

You may add a passage of up to five words as a Front-Cover Text, and a passage of up to 25 words as a Back-Cover Text, to the end of the list of Cover Texts in the Modified Version. Only one passage of Front-Cover Text and one of Back-Cover Text may be added by (or through arrangements made by) any one entity. If the Document already includes a cover text for the same cover, previously added by you or by arrangement made by the same entity you are acting on behalf of, you may not add another; but you may replace the old one, on explicit permission from the previous publisher that added the old one.

The author(s) and publisher(s) of the Document do not by this License give permission to use their names for publicity for or to assert or imply endorsement of any Modified Version.

5. COMBINING DOCUMENTS
----------------------

You may combine the Document with other documents released under this License, under the terms defined in section 4 above for modified versions, provided that you include in the combination all of the Invariant Sections of all of the original documents, unmodified, and list them all as Invariant Sections of your combined work in its license notice, and that you preserve all their Warranty Disclaimers.

The combined work need only contain one copy of this License, and multiple identical Invariant Sections may be replaced with a single copy. If there are multiple Invariant Sections with the same name but different contents, make the title of each such section unique by adding at the end of it, in parentheses, the name of the original author or publisher of that section if known, or else a unique number. Make the same adjustment to the section titles in the list of Invariant Sections in the license notice of the combined work.

In the combination, you must combine any sections Entitled “History” in the various original documents, forming one section Entitled “History”; likewise combine any sections Entitled “Acknowledgements”, and any sections Entitled “Dedications”. You must delete all sections Entitled “Endorsements”.

6. COLLECTIONS OF DOCUMENTS
---------------------------

You may make a collection consisting of the Document and other documents released under this License, and replace the individual copies of this License in the various documents with a single copy that is included in the collection, provided that you follow the rules of this License for verbatim copying of each of the documents in all other respects.

You may extract a single document from such a collection, and distribute it individually under this License, provided you insert a copy of this License into the extracted document, and follow this License in all other respects regarding verbatim copying of that document.

7. AGGREGATION WITH INDEPENDENT WORKS
-------------------------------------

A compilation of the Document or its derivatives with other separate and independent documents or works, in or on a volume of a storage or distribution medium, is called an “aggregate” if the copyright resulting from the compilation is not used to limit the legal rights of the compilation’s users beyond what the individual works permit. When the Document is included in an aggregate, this License does not apply to the other works in the aggregate which are not themselves derivative works of the Document.

If the Cover Text requirement of section 3 is applicable to these copies of the Document, then if the Document is less than one half of the entire aggregate, the Document’s Cover Texts may be placed on covers that bracket the Document within the aggregate, or the electronic equivalent of covers if the Document is in electronic form. Otherwise they must appear on printed covers that bracket the whole aggregate.

8. TRANSLATION
--------------

Translation is considered a kind of modification, so you may distribute translations of the Document under the terms of section 4. Replacing Invariant Sections with translations requires special permission from their copyright holders, but you may include translations of some or all Invariant Sections in addition to the original versions of these Invariant Sections. You may include a translation of this License, and all the license notices in the Document, and any Warranty Disclaimers, provided that you also include the original English version of this License and the original versions of those notices and disclaimers. In case of a disagreement between the translation and the original version of this License or a notice or disclaimer, the original version will prevail.

If a section in the Document is Entitled “Acknowledgements”, “Dedications”, or “History”, the requirement (section 4) to Preserve its Title (section 1) will typically require changing the actual title.

9. TERMINATION
--------------

You may not copy, modify, sublicense, or distribute the Document except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, or distribute it is void, and will automatically terminate your rights under this License.

However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation.

Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice.

Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, receipt of a copy of some or all of the same material does not give you any rights to use it.

10. FUTURE REVISIONS OF THIS LICENSE
------------------------------------

The Free Software Foundation may publish new, revised versions of the GNU Free Documentation License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. See https://www.gnu.org/licenses/.

Each version of the License is given a distinguishing version number. If the Document specifies that a particular numbered version of this License “or any later version” applies to it, you have the option of following the terms and conditions either of that specified version or of any later version that has been published (not as a draft) by the Free Software Foundation. If the Document does not specify a version number of this License, you may choose any version ever published (not as a draft) by the Free Software Foundation. If the Document specifies that a proxy can decide which future versions of this License can be used, that proxy’s public statement of acceptance of a version permanently authorizes you to choose that version for the Document.

11. RELICENSING
---------------

“Massive Multiauthor Collaboration Site” (or “MMC Site”) means any World Wide Web server that publishes copyrightable works and also provides prominent facilities for anybody to edit those works. A public wiki that anybody can edit is an example of such a server. A “Massive Multiauthor Collaboration” (or “MMC”) contained in the site means any set of copyrightable works thus published on the MMC site.

“CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0 license published by Creative Commons Corporation, a not-for-profit corporation with a principal place of business in San Francisco, California, as well as future copyleft versions of that license published by that same organization.

“Incorporate” means to publish or republish a Document, in whole or in part, as part of another Document.

An MMC is “eligible for relicensing” if it is licensed under this License, and if all works that were first published under this License somewhere other than this MMC, and subsequently incorporated in whole or in part into the MMC, (1) had no cover texts or invariant sections, and (2) were thus incorporated prior to November 1, 2008.

The operator of an MMC Site may republish an MMC contained in the site under CC-BY-SA on the same site at any time before August 1, 2009, provided the MMC is eligible for relicensing.

ADDENDUM: How to use this License for your documents
----------------------------------------------------

To use this License in a document you have written, include a copy of the License in the document and put the following copyright and license notices just after the title page:

     Copyright (C)  YEAR  YOUR NAME.
     Permission is granted to copy, distribute and/or modify this document
     under the terms of the GNU Free Documentation License, Version 1.3
     or any later version published by the Free Software Foundation;
     with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
     A copy of the license is included in the section entitled "GNU
     Free Documentation License".

If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with â€¦ Texts.” line with this:

     with the Invariant Sections being LIST THEIR TITLES, with the
     Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST.

If you have Invariant Sections without Cover Texts, or some other combination of the three, merge those two alternatives to suit the situation.

If your document contains nontrivial examples of program code, we recommend releasing these examples in parallel under your choice of free software license, such as the GNU General Public License, to permit their use in free software.