\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename anastasis.info @documentencoding UTF-8 @ifinfo @*Generated by Sphinx 3.4.3.@* @end ifinfo @settitle Anastasis Manual @defindex ge @paragraphindent 0 @exampleindent 4 @finalout @dircategory CATEGORY @direntry * MENU ENTRY: (anastasis.info). DESCRIPTION @end direntry @definfoenclose strong,`,' @definfoenclose emph,`,' @c %**end of header @copying @quotation Anastasis 0.0.0pre0, Aug 14, 2021 Anastasis SARL Copyright @copyright{} 2020-2021 Anastasis SARL (AGPLv3+ or GFDL 1.3+) @end quotation @end copying @titlepage @title Anastasis Manual @insertcopying @end titlepage @contents @c %** start of user preamble @c %** end of user preamble @ifnottex @node Top @top Anastasis Manual @insertcopying @end ifnottex @c %**start of body @anchor{index doc}@anchor{0} @c This file is part of GNU Anastasis. @c Copyright (C) 2020-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff Anastasis is Free Software protocol and implementation that allows users to securely deposit @strong{core secrets} with an open set of escrow providers and to recover these secrets if their original copies are lost. Anastasis is intended for users that want to make backups of key material, such as OpenPGP encryption keys, hard disk encryption keys or master keys of electronic wallets. Anastasis is NOT intended to store large amounts of secret data, it is only designed to safeguard key material. Anastasis solves the issue of keeping key material both available to the authorized user(s), and confidential from anyone else. With Anastasis, the @strong{core secrets} are protected from the Anastasis escrow providers by encrypting each with a @strong{master key}. The @strong{master key} can be split and distributed across the escrow providers to ensure that no single escrow provider can recover the @strong{master key} on its own. Which subset(s) of Anastasis providers must be contacted to recover a @strong{master key} is freely configurable. With Anastasis, users can reliably recover their @strong{core secret}, while Anastasis makes this difficult for everyone else. This is even true if the user is unable to reliably remember any secret with sufficiently high entropy: Anastasis does not simply reduce the problem to encrypting the @strong{core secret} using some other key material in possession of the user. @menu * Documentation Overview:: @detailmenu --- The Detailed Node Listing --- Documentation Overview * Introduction:: * Installation:: * Configuration:: * Cryptography:: * REST API:: * Reducer API:: * Authentication Methods:: * DB Schema:: * Anastasis licensing information:: * Man Pages:: * Complete Index:: * GNU Free Documentation License:: Introduction * User Identifiers:: * Adversary models:: * The recovery document:: Installation * Installing from source:: * Installing Anastasis binary packages on Debian:: * Installing Anastasis binary packages on Ubuntu:: Installing from source * Installing GNUnet:: * Installing the Taler Exchange:: * Installing the Taler Merchant:: * Installing Anastasis:: * Installing GNUnet-gtk:: * Installing Anastasis-gtk:: Installing Anastasis binary packages on Debian * Installing the graphical front-end:: * Installing the backend:: Installing Anastasis binary packages on Ubuntu * Installing the graphical front-end: Installing the graphical front-end<2>. * Installing the backend: Installing the backend<2>. Configuration * Configuration format:: * Using anastasis-config:: Cryptography * Key derivations:: * Key Usage:: * Availability Considerations:: Key derivations * Verification:: * Encryption:: Key Usage * Encryption: Encryption<2>. * Signatures:: REST API * HTTP Request and Response:: * Protocol Version Ranges:: * Common encodings:: Common encodings * Binary Data:: * Hash codes:: * Large numbers:: * Timestamps:: * Integers:: * Objects:: * Keys:: * Signatures: Signatures<2>. * Amounts:: * Time:: * Cryptographic primitives:: * Signatures: Signatures<3>. * Receiving Configuration:: * Receiving Terms of Service:: * Manage policy:: * Managing truth:: Reducer API * States:: * Backup Reducer:: * Recovery Reducer:: * Reducer transitions:: Reducer transitions * Initial state:: * Common transitions:: * Backup transitions:: * Recovery transitions:: Authentication Methods * SMS (sms): SMS sms. * Email verification (email): Email verification email. * Video identification (vid): Video identification vid. * Security question (qa): Security question qa. * Snail mail verification (post): Snail mail verification post. Anastasis licensing information * Anastasis (git;//git.taler.net/anastasis): Anastasis git //git taler net/anastasis. * Anastasis-gtk (git;//git.taler.net/anastasis-gtk): Anastasis-gtk git //git taler net/anastasis-gtk. * Documentation:: Anastasis (git://git.taler.net/anastasis) * Runtime dependencies:: Anastasis-gtk (git://git.taler.net/anastasis-gtk) * Runtime dependencies: Runtime dependencies<2>. Man Pages * anastasis-config(1): anastasis-config 1. * anastasis-gtk(1): anastasis-gtk 1. * anastasis-httpd(1): anastasis-httpd 1. * anastasis-reducer(1): anastasis-reducer 1. * anastasis.conf(5): anastasis conf 5. anastasis-config(1) * Synopsis:: * Description:: * See Also:: * Bugs:: anastasis-gtk(1) * Synopsis: Synopsis<2>. * Description: Description<2>. * See Also: See Also<2>. * Bugs: Bugs<2>. anastasis-httpd(1) * Synopsis: Synopsis<3>. * Description: Description<3>. * Signals:: * See also:: * Bugs: Bugs<3>. anastasis-reducer(1) * Synopsis: Synopsis<4>. * Description: Description<4>. * See Also: See Also<3>. * Bugs: Bugs<4>. anastasis.conf(5) * Description: Description<5>. * SEE ALSO:: * BUGS:: Description * GLOBAL OPTIONS:: * Authorization options:: * Postgres database configuration:: GNU Free Documentation License * 0. PREAMBLE: 0 PREAMBLE. * 1. APPLICABILITY AND DEFINITIONS: 1 APPLICABILITY AND DEFINITIONS. * 2. VERBATIM COPYING: 2 VERBATIM COPYING. * 3. COPYING IN QUANTITY: 3 COPYING IN QUANTITY. * 4. MODIFICATIONS: 4 MODIFICATIONS. * 5. COMBINING DOCUMENTS: 5 COMBINING DOCUMENTS. * 6. COLLECTIONS OF DOCUMENTS: 6 COLLECTIONS OF DOCUMENTS. * 7. AGGREGATION WITH INDEPENDENT WORKS: 7 AGGREGATION WITH INDEPENDENT WORKS. * 8. TRANSLATION: 8 TRANSLATION. * 9. TERMINATION: 9 TERMINATION. * 10. FUTURE REVISIONS OF THIS LICENSE: 10 FUTURE REVISIONS OF THIS LICENSE. * 11. RELICENSING: 11 RELICENSING. * ADDENDUM; How to use this License for your documents: ADDENDUM How to use this License for your documents. @end detailmenu @end menu @node Documentation Overview,,Top,Top @anchor{index anastasis-documentation}@anchor{1}@anchor{index documentation-overview}@anchor{2} @chapter Documentation Overview @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @menu * Introduction:: * Installation:: * Configuration:: * Cryptography:: * REST API:: * Reducer API:: * Authentication Methods:: * DB Schema:: * Anastasis licensing information:: * Man Pages:: * Complete Index:: * GNU Free Documentation License:: @end menu @node Introduction,Installation,,Documentation Overview @anchor{introduction doc}@anchor{3}@anchor{introduction introduction}@anchor{4} @section Introduction To understand how Anastasis works, you need to understand three key concepts: user identifiers, our adversary model and the role of the recovery document. @menu * User Identifiers:: * Adversary models:: * The recovery document:: @end menu @node User Identifiers,Adversary models,,Introduction @anchor{introduction user-identifiers}@anchor{5} @subsection User Identifiers To uniquely identify users, an “unforgettable” @strong{identifier} is used. This identifier should be difficult to guess for anybody but the user. However, the @strong{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. @node Adversary models,The recovery document,User Identifiers,Introduction @anchor{introduction adversary-models}@anchor{6} @subsection Adversary models The adversary model of Anastasis has two types of adversaries: weak adversaries which do not know the user’s @strong{identifier}, and strong adversaries which somehow do know a user’s @strong{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 @strong{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. @node The recovery document,,Adversary models,Introduction @anchor{introduction the-recovery-document}@anchor{7} @subsection The recovery document A @strong{recovery document} includes all of the information a user needs to recover access to their core secret. It specifies a set of @strong{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 @strong{truth}, that is data the Anastasis operator may learn during the recovery process. Truth always consists of an encrypted key share and associated data 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 @strong{recovery document} also specifies @strong{policies}, which describe the combination(s) of the escrow methods that suffice to obtain access to the core secret. For example, a @strong{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 @strong{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 @strong{recovery document} (except for its length, which may be exposed to an adversary which monitors the user’s network traffic). @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node Installation,Configuration,Introduction,Documentation Overview @anchor{installation doc}@anchor{8}@anchor{installation installation}@anchor{9} @section Installation Please install the following packages before proceeding with the exchange compilation. @itemize - @item libsqlite3 >= 3.16.2 @item GNU libunistring >= 0.9.3 @item libcurl >= 7.26 (or libgnurl >= 7.26) @item libqrencode >= 4.0.0 @item GNU libgcrypt >= 1.6 @item libsodium >= 1.0 @item libargon2 >= 20171227 @item libjansson >= 2.7 @item Postgres >= 9.6, including libpq @item GNU libmicrohttpd >= 0.9.71 @item GNUnet >= 0.14.0 (from source tarball@footnote{http://ftpmirror.gnu.org/gnunet/}) @item GNU Taler exchange @item GNU Taler merchant backend @end itemize Except for the last two, these are available in most GNU/Linux distributions and should just be installed using the respective package manager. @menu * Installing from source:: * Installing Anastasis binary packages on Debian:: * Installing Anastasis binary packages on Ubuntu:: @end menu @node Installing from source,Installing Anastasis binary packages on Debian,,Installation @anchor{installation installing-from-source}@anchor{a} @subsection Installing from source The following instructions will show how to install libgnunetutil and the GNU Taler exchange from source. @menu * Installing GNUnet:: * Installing the Taler Exchange:: * Installing the Taler Merchant:: * Installing Anastasis:: * Installing GNUnet-gtk:: * Installing Anastasis-gtk:: @end menu @node Installing GNUnet,Installing the Taler Exchange,,Installing from source @anchor{installation installing-gnunet}@anchor{b} @subsubsection 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: @example $ ./configure [--prefix=GNUNETPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install # ldconfig @end example If you did not specify a prefix, GNUnet will install to @code{/usr/local}, which requires you to run the last step as @code{root}. The @code{ldconfig} command (also run as @code{root}) makes the shared object libraries (@code{.so} files) visible to the various installed programs. @node Installing the Taler Exchange,Installing the Taler Merchant,Installing GNUnet,Installing from source @anchor{installation installing-the-taler-exchange}@anchor{c} @subsubsection Installing the Taler Exchange After installing GNUnet, unpack the GNU Taler exchange tarball, change into the resulting directory, and proceed as follows: @example $ ./configure [--prefix=EXCHANGEPFX] \ [--with-gnunet=GNUNETPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install @end example If you did not specify a prefix, the exchange will install to @code{/usr/local}, which requires you to run the last step as @code{root}. You have to specify @code{--with-gnunet=/usr/local} if you installed GNUnet to @code{/usr/local} in the previous step. @node Installing the Taler Merchant,Installing Anastasis,Installing the Taler Exchange,Installing from source @anchor{installation installing-the-taler-merchant}@anchor{d} @subsubsection Installing the Taler Merchant GNU Taler merchant has these additional dependencies: @itemize - @item libqrencode >= 4.0.0 @end itemize 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: @example $ ./configure [--prefix=PFX] \ [--with-gnunet=GNUNETPFX] \ [--with-exchange=EXCHANGEPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install @end example If you did not specify a prefix, the exchange will install to @code{/usr/local}, which requires you to run the last step as @code{root}. You have to specify @code{--with-exchange=/usr/local} and/or @code{--with-gnunet=/usr/local} if you installed the exchange and/or GNUnet to @code{/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 @code{/etc/ld.so.conf}, adding lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/} (replace the prefixes with the actual paths you used). Afterwards, you should run @code{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. @node Installing Anastasis,Installing GNUnet-gtk,Installing the Taler Merchant,Installing from source @anchor{installation installing-anastasis}@anchor{e} @subsubsection 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: @example $ ./configure [--prefix=PFX] \ [--with-gnunet=GNUNETPFX] \ [--with-exchange=EXCHANGEPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install @end example If you did not specify a prefix, Anastasis will be installed to @code{/usr/local}, which requires you to run the last step as @code{root}. You have to specify @code{--with-exchange=/usr/local} and/or @code{--with-gnunet=/usr/local} if you installed the exchange and/or GNUnet to @code{/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 @code{/etc/ld.so.conf}, adding lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/} (replace the prefixes with the actual paths you used). Afterwards, you should run @code{ldconfig}. Without this step, it is possible that the linker may not find the installed libraries and launching the Anastasis backend would then fail. @node Installing GNUnet-gtk,Installing Anastasis-gtk,Installing Anastasis,Installing from source @anchor{installation installing-gnunet-gtk}@anchor{f} @subsubsection 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: @example $ ./configure [--prefix=$PFX] \ [--with-gnunet=$GNUNETPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install @end example 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 @code{/usr/local}, which requires you to run the last step as @code{root}. You have to specify @code{--with-gnunet=/usr/local} if you installed GNUnet to @code{/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 @code{/etc/ld.so.conf}, adding lines for @code{$GNUNETPFX/lib/} and @code{$PFX/lib/} (replace the prefixes with the actual paths you used). Afterwards, you should run @code{ldconfig}. Without this step, it is possible that the linker may not find the installed libraries and launching gnunet-gtk would then fail. @node Installing Anastasis-gtk,,Installing GNUnet-gtk,Installing from source @anchor{installation installing-anastasis-gtk}@anchor{10} @subsubsection 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: @example $ ./configure [--prefix=PFX] \ [--with-gnunet=GNUNETPFX] \ [--with-exchange=EXCHANGEPFX] \ [--with-anastasis=ANASTASISPFX] $ # Each dependency can be fetched from non standard locations via $ # the '--with-' option. See './configure --help'. $ make # make install @end example If you did not specify a prefix, anastasis-gtk will be installed to @code{/usr/local}, which requires you to run the last step as @code{root}. You have to specify @code{-with-anastasis=/usr/local}, @code{--with-exchange=/usr/local} and/or @code{--with-gnunet=/usr/local} if you installed the exchange and/or GNUnet to @code{/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 @code{/etc/ld.so.conf}, adding lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/} (replace the prefixes with the actual paths you used). Afterwards, you should run @code{ldconfig}. Without this step, it is possible that the linker may not find the installed libraries and launching anastasis-gtk would then fail. @node Installing Anastasis binary packages on Debian,Installing Anastasis binary packages on Ubuntu,Installing from source,Installation @anchor{installation installing-anastasis-binary-packages-on-debian}@anchor{11} @subsection 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 @code{/etc/apt/preferences} as follows: @example 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 @end example A typical @code{/etc/apt/sources.list} file for this setup which combines Debian stable with more recent packages from testing and unstable would look like this: @example 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 @end example 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 @code{/etc/apt/sources.list.d/taler.list} that looks like this: @example deb https://deb.taler.net/apt/debian sid main @end example Next, you must import the Taler Systems SA public package signing key into your keyring and update the package lists: @example # wget -O - https://taler.net/taler-systems.gpg.key | apt-key add - # apt update @end example @cartouche @quotation Note You may want to verify the correctness of the Taler Systems key out-of-band. @end quotation @end cartouche Now your system is ready to install the official GNU Taler binary packages using apt. @menu * Installing the graphical front-end:: * Installing the backend:: @end menu @node Installing the graphical front-end,Installing the backend,,Installing Anastasis binary packages on Debian @anchor{installation installing-the-graphical-front-end}@anchor{12} @subsubsection Installing the graphical front-end To install the Anastasis Gtk+ frontend, you can simply run: @example # apt install anastasis-gtk @end example To use @code{anastasis-gtk}, you can simply run: @example $ anastasis-gtk @end example @node Installing the backend,,Installing the graphical front-end,Installing Anastasis binary packages on Debian @anchor{installation installing-the-backend}@anchor{13} @subsubsection Installing the backend If you want to install the Anastasis backend-end (which normal users do not need), you should run: @example # apt install -t sid anastasis-httpd @end example 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 @code{/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 @code{/etc/@{apache,nginx@}/conf-available/anastasis.conf}. To operate an Anastasis backend with payments, you additionally need to install a Taler merchant backend via: @example # apt install -t sid taler-merchant-httpd @end example @node Installing Anastasis binary packages on Ubuntu,,Installing Anastasis binary packages on Debian,Installation @anchor{installation installing-anastasis-binary-packages-on-ubuntu}@anchor{14} @subsection 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 @code{/etc/apt/sources.list.d/taler.list} file for this setup would look like this: @example deb https://deb.taler.net/apt/ubuntu/ focal-fossa main @end example 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: @example # wget -O - https://taler.net/taler-systems.gpg.key | apt-key add - # apt update @end example @cartouche @quotation Note You may want to verify the correctness of the Taler Systems key out-of-band. @end quotation @end cartouche Now your system is ready to install the official GNU Taler binary packages using apt. @menu * Installing the graphical front-end: Installing the graphical front-end<2>. * Installing the backend: Installing the backend<2>. @end menu @node Installing the graphical front-end<2>,Installing the backend<2>,,Installing Anastasis binary packages on Ubuntu @anchor{installation id1}@anchor{15} @subsubsection Installing the graphical front-end To install the Anastasis front-end, you can now simply run: @example # apt install -t focal-fossa anastasis-gtk @end example To use @code{anastasis-gtk}, you can simply run: @example $ anastasis-gtk @end example @node Installing the backend<2>,,Installing the graphical front-end<2>,Installing Anastasis binary packages on Ubuntu @anchor{installation id2}@anchor{16} @subsubsection Installing the backend If you want to install the Anastasis backend-end (which normal users do not need), you should run: @example # apt install -t focal-fossa anastasis-httpd @end example 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 @code{/etc/anastasis.conf}. To operate an Anastasis backend with payments, you additionally need to install a Taler merchant backend via: @example # apt install -t sid taler-merchant-httpd @end example @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node Configuration,Cryptography,Installation,Documentation Overview @anchor{configuration doc}@anchor{17}@anchor{configuration configuration}@anchor{18} @section Configuration Details about the contents of the configuration file are describe in the @code{anastasis.conf(5)} chapter. This chapter only describes the configuration format. @menu * Configuration format:: * Using anastasis-config:: @end menu @node Configuration format,Using anastasis-config,,Configuration @anchor{configuration configuration-format}@anchor{19} @subsection 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: @example [section1] value1 = string value2 = 23 [section2] value21 = string value22 = /path22 @end example Throughout any configuration file, it is possible to use @code{$}-prefixed variables, like @code{$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: @code{$@{VAR:-default@}}. However, there are two ways a user can set @code{$}-prefixable variables: by defining them under a @code{[paths]} section, see example below, @example [paths] TALER_DEPLOYMENT_SHARED = $@{HOME@}/shared-data .. [section-x] path-x = $@{TALER_DEPLOYMENT_SHARED@}/x @end example or by setting them in the environment: @example $ export VAR=/x @end example The configuration loader will give precedence to variables set under @code{[path]}, though. The utility @code{taler-config}, which gets installed along with the exchange, serves to get and set configuration values without directly editing the .conf. The option @code{-f} is particularly useful to resolve pathnames, when they use several levels of @code{$}-expanded variables. See @code{taler-config --help}. Note that, in this stage of development, the file @code{$HOME/.config/taler.conf} can contain sections for @emph{all} the component. For example, both an exchange and a bank can read values from it. The repository @code{git://taler.net/deployment} contains examples of configuration file used in our demos. See under @code{deployment/config}. @quotation @strong{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. @end quotation @node Using anastasis-config,,Configuration format,Configuration @anchor{configuration using-anastasis-config}@anchor{1a} @subsection Using anastasis-config The tool @code{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 @example $ anastasis-config -s $SECTION @end example to list all of the configuration values in section @code{$SECTION}. Run @example $ anastasis-config -s $section -o $option @end example to extract the respective configuration value for option @code{$option} in section @code{$section}. Finally, to change a setting, run @example $ anastasis-config -s $section -o $option -V $value @end example to set the respective configuration value to @code{$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 @code{$DATADIR} within their value. To expand the @code{$DATADIR} or other $-variables in the configuration, pass the @code{-f} option to @code{anastasis-config}. For example, compare: @example $ anastasis-config -s ACCOUNT-bank \ -o WIRE_RESPONSE $ anastasis-config -f -s ACCOUNT-bank \ -o WIRE_RESPONSE @end example While the configuration file is typically located at @code{$HOME/.config/taler.conf}, an alternative location can be specified to @code{taler-merchant-httpd} and @code{anastasis-config} using the @code{-c} option. @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node Cryptography,REST API,Configuration,Documentation Overview @anchor{cryptography doc}@anchor{1b}@anchor{cryptography cryptography}@anchor{1c} @section 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 @strong{identifier} using different HKDFs. These HKDFs are salted using the respective escrow provider’s @strong{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 @strong{account key} to identify the account of the user. The account private key is derived from the user’s @strong{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 @code{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 @strong{identifier} and a high-entropy @strong{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 @strong{core secret} of the user is (AES) encrypted using a symmetric @strong{master key}. Recovering this master key requires the user to satisfy a particular @strong{policy}. Policies specify a set of @strong{escrow methods}, each of which leads the user to a @strong{key share}. Combining those key shares (by hashing) allows the user to obtain a @strong{policy key}, which can be used to decrypt the @strong{master key}. There can be many policies, satisfying any of these will allow the user to recover the master key. A @strong{recovery document} contains the encrypted @strong{core secret}, a set of escrow methods and a set of policies. @menu * Key derivations:: * Key Usage:: * Availability Considerations:: @end menu @node Key derivations,Key Usage,,Cryptography @anchor{cryptography key-derivations}@anchor{1d} @subsection 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 @strong{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 @strong{identifier}. This identifier will be first hashed with Argon2, to provide a @strong{kdf_id} which will be used to derive other keys later. The Hash must also include the respective @strong{server_salt}. This also ensures that the @strong{kdf_id} is different on each server. The use of Argon2 and the respective @strong{server_salt} is intended to make it difficult to brute-force @strong{kdf_id} values and help protect the user’s privacy. Also this ensures that the @strong{kdf_id}s on every server differs. However, we do not assume that the @strong{identifier} or the @strong{kdf_id} cannot be determined by an adversary performing a targeted attack, as a user’s @strong{identifier} is likely to always be known to state actors and may likely also be available to other actors. @example kdf_id := Argon2( identifier, server_salt, keysize ) @end example @strong{identifier}: The secret defined from the user beforehand. @strong{server_salt}: The salt from the Server. @strong{keysize}: The desired output size of the KDF, here 32 bytes. @menu * Verification:: * Encryption:: @end menu @node Verification,Encryption,,Key derivations @anchor{cryptography verification}@anchor{1e} @subsubsection 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 @strong{kdf_id}, decrypt) the user’s policy (but not the core secret), or upload a new version of the @strong{encrypted recovery document} (but not delete an existing version). For the generation of the private key we use the @strong{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 @strong{kdf_id}. @example ver_secret := HKDF(kdf_id, "ver", keysize) eddsa_priv := eddsa_d_to_a(ver_secret) eddsa_pub := get_EdDSA_Pub(eddsa_priv) @end example @strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase. @strong{kdf_id}: Hashed identifier. @strong{key_size}: Size of the output, here 32 bytes. @strong{ver_secret}: Derived key from the @code{kdf_id}, serves as intermediate step for the generation of the private key. @strong{eddsa_d_to_a()}: Function which converts the ver_key to a valid EdDSA private key. Specifically, assuming the value @code{eddsa_priv} is in a 32-byte array “digest”, the function clears and sets certain bits as follows: @example digest[0] = (digest[0] & 0x7f) | 0x40; digest[31] &= 0xf8; @end example @strong{eddsa_priv}: The generated EdDSA private key. @strong{eddsa_pub}: The generated EdDSA public key. @node Encryption,,Verification,Key derivations @anchor{cryptography encryption}@anchor{1f} @subsubsection 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 @code{nonce} and the @code{kdf_id}. @example (iv,key) := HKDF(kdf_id, nonce, keysize + ivsize) @end example @strong{HKDF()}: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase. @strong{kdf_id}: Hashed identifier. @strong{keysize}: Size of the AES symmetric key, here 32 bytes. @strong{ivsize}: Size of the AES GCM IV, here 12 bytes. @strong{prekey}: Original key material. @strong{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). @strong{key}: Symmetric key which is later used to encrypt the documents with AES256-GCM. @strong{iv}: IV which will be used for AES-GCM. @node Key Usage,Availability Considerations,Key derivations,Cryptography @anchor{cryptography key-usage}@anchor{20} @subsection Key Usage The keys we have generated are then used to encrypt the @strong{recovery document} and the @strong{key_share} of the user. @menu * Encryption: Encryption<2>. * Signatures:: @end menu @node Encryption<2>,Signatures,,Key Usage @anchor{cryptography id1}@anchor{21} @subsubsection 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 @strong{recovery document} and the @strong{key_share}. To ensure that the key derivation for the encryption of the @strong{recovery document} differs fundamentally from that of an individual @strong{key share}, we use different salts (“erd” and “eks”, respectively). @example (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) @end example @strong{encrypted_recovery_document}: The encrypted @strong{recovery document} which contains the escrow methods, policies and the encrypted @strong{core secret}. @strong{nonce0}: Nonce which is used to generate @emph{key0} and @emph{iv0} which are used for the encryption of the @emph{recovery document}. Nonce must contain the string “ERD”. @strong{optional data}: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider. @strong{encrypted_key_share_i}: The encrypted @strong{key_share} which the escrow provider must release upon successful authentication. Here, @strong{i} must be a positive number used to iterate over the various @strong{key shares} used for the various @strong{escrow methods} at the various providers. @strong{nonce_i}: Nonce which is used to generate @emph{key_i} and @emph{iv_i} which are used for the encryption of the @strong{key share}. @strong{i} must be the same number as specified above for @emph{encrypted_key_share_i}. Nonce must contain the string “EKS” plus the according @emph{i}. As a special rule, when a @strong{security question} is used to authorize access to an @strong{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: @example 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) @end example @strong{qsalt}: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing. @strong{answer}: Answer to the security question, in UTF-8, as entered by the user. @strong{powh}: Result of the (expensive, proof-of-work) hash algorithm. @strong{uuid}: UUID of the challenge associated with the security question and the encrypted key share. @strong{ekss}: Replacement salt to be used instead of “eks” when deriving the key to encrypt/decrypt the key share. @node Signatures,,Encryption<2>,Key Usage @anchor{cryptography signatures}@anchor{22} @subsubsection 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 @strong{Anastasis-Policy-Signature}. @example (anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv) ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub) @end example @strong{anastasis-account-signature}: Signature over the SHA-512 hash of the body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD} (1400) (see GNUnet EdDSA signature API for the use of purpose). @strong{h_body}: The hashed body. @strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed. When requesting policy downloads, the client must also provide a signature: @example (anastasis-account-signature) := eddsa_sign(version, eddsa_priv) ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub) @end example @strong{anastasis-account-signature}: Signature over the SHA-512 hash of the body using the purpose code @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} (1401) (see GNUnet EdDSA signature API for the use of purpose). @strong{version}: The version requested as a 64-bit integer, 2^64-1 for the “latest version”. @strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed. @node Availability Considerations,,Key Usage,Cryptography @anchor{cryptography availability-considerations}@anchor{23} @subsection 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 @strong{payment identifier} from a payment made by the user. Thus, a policy upload requires both knowledge of the @strong{identity} and making a payment. This effectively prevents an adversary from using the append-only policy storage from exhausting Anastasis server capacity. @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node REST API,Reducer API,Cryptography,Documentation Overview @anchor{rest doc}@anchor{24}@anchor{rest rest-api}@anchor{25} @section REST API @c This file is part of Anastasis @c @c Copyright (C) 2014-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @menu * HTTP Request and Response:: * Protocol Version Ranges:: * Common encodings:: @end menu @node HTTP Request and Response,Protocol Version Ranges,,REST API @anchor{rest http-common}@anchor{26}@anchor{rest http-request-and-response}@anchor{27} @subsection 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. @anchor{rest any--*}@anchor{28} @deffn {HTTP Any} ANY /* @strong{Request:} Unless specified otherwise, HTTP requests that carry a message body must have the content type @code{application/json}. @*Request Headers: @itemize * @item Content-Type@footnote{https://tools.ietf.org/html/rfc7231#section-3.1.1.5} – application/json @end itemize @strong{Response:} @*Response Headers: @itemize * @item Content-Type@footnote{https://tools.ietf.org/html/rfc7231#section-3.1.1.5} – application/json @end itemize @table @asis @item 200 Ok@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}: The request was successful. @item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}: One of the arguments to the request is missing or malformed. @item 500 Internal server error@footnote{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. @end table Unless specified otherwise, all error status codes (4xx and 5xx) have a message body with an @ref{29,,ErrorDetail} JSON object. @strong{Details:} @example interface ErrorDetail @{ // Numeric error code unique to the condition, see `@w{`}gnu-taler-error-codes`@w{`} 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; @} @end example @end deffn @node Protocol Version Ranges,Common encodings,HTTP Request and Response,REST API @anchor{rest protocol-version-ranges}@anchor{2a} @subsection 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@footnote{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: @enumerate @item The @code{current} version. This is the latest version of the protocol supported by the client or service. @item The @code{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. @item The @code{age} number. This non-zero integer identifies with how many previous protocol versions this implementation is compatible. An @code{age} of 0 implies that the implementation only supports the @code{current} protocol version. The @code{age} must be less or equal than the @code{current} protocol version. @end enumerate To avoid confusion with semantic versions, the protocol version range is written down in the following format: @example current[:revision[:age]] @end example The angle brackets mark optional components. If either @code{revision} or @code{age} are omitted, they default to 0. Examples: @itemize * @item “1” and “1” are compatible @item “1” and “2” are @strong{incompatible} @item “2:0:1” and “1:0:0” are compatible @item “2:5:1” and “1:10:0” are compatible @item “4:0:1” and “2:0:0” are @strong{incompatible} @item “4:0:1” and “3:0:0” are compatible @end itemize @cartouche @quotation Note Semantic versions@footnote{https://semver.org/} are not a good tool for this job, as we concisely want to express that the client/server supports the last @code{n} versions of the protocol. Semantic versions don’t support this, and semantic version ranges are too complex for this. @end quotation @end cartouche @cartouche @quotation Warning 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. @end quotation @end cartouche @cartouche @quotation Warning 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. @end quotation @end cartouche @node Common encodings,,Protocol Version Ranges,REST API @anchor{rest common-encodings}@anchor{2b}@anchor{rest encodings-ref}@anchor{2c} @subsection Common encodings This section describes how certain types of values are represented throughout the API. @menu * Binary Data:: * Hash codes:: * Large numbers:: * Timestamps:: * Integers:: * Objects:: * Keys:: * Signatures: Signatures<2>. * Amounts:: * Time:: * Cryptographic primitives:: * Signatures: Signatures<3>. * Receiving Configuration:: * Receiving Terms of Service:: * Manage policy:: * Managing truth:: @end menu @node Binary Data,Hash codes,,Common encodings @anchor{rest base32}@anchor{2d}@anchor{rest binary-data}@anchor{2e} @subsubsection Binary Data @example type Base32 = string; @end example Binary data is generally encoded using Crockford’s variant of Base32 (@indicateurl{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. @node Hash codes,Large numbers,Binary Data,Common encodings @anchor{rest hash-codes}@anchor{2f} @subsubsection Hash codes Hash codes are strings representing base32 encoding of the respective hashed data. See @ref{2d,,base32}. @example // 64-byte hash code. type HashCode = string; @end example @example // 32-byte hash code. type ShortHashCode = string; @end example @node Large numbers,Timestamps,Hash codes,Common encodings @anchor{rest large-numbers}@anchor{30} @subsubsection Large numbers Large numbers such as 256 bit keys, are transmitted as other binary data in Crockford Base32 encoding. @node Timestamps,Integers,Large numbers,Common encodings @anchor{rest timestamps}@anchor{31} @subsubsection Timestamps Timestamps are represented by the following structure: @example interface Timestamp @{ // Milliseconds since epoch, or the special // value "never" to represent an event that will // never happen. t_ms: number | "never"; @} @end example @example interface Duration @{ // Duration in milliseconds or "forever" // to represent an infinite duration. d_ms: number | "forever"; @} @end example @node Integers,Objects,Timestamps,Common encodings @anchor{rest integers}@anchor{32}@anchor{rest publickey}@anchor{33} @subsubsection Integers @example // JavaScript numbers restricted to integers. type Integer = number; @end example @node Objects,Keys,Integers,Common encodings @anchor{rest objects}@anchor{34} @subsubsection Objects @example // JavaScript objects, no further restrictions. type Object = object; @end example @node Keys,Signatures<2>,Objects,Common encodings @anchor{rest keys}@anchor{35} @subsubsection Keys @example // 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; @end example @example // 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; @end example @node Signatures<2>,Amounts,Keys,Common encodings @anchor{rest signature}@anchor{36}@anchor{rest signatures}@anchor{37} @subsubsection Signatures @example // EdDSA signatures are transmitted as 64-bytes `base32` // binary-encoded objects with just the R and S values (base32_ binary-only). type EddsaSignature = string; @end example @node Amounts,Time,Signatures<2>,Common encodings @anchor{rest amount}@anchor{38}@anchor{rest amounts}@anchor{39} @subsubsection Amounts @example type Amount = string; @end example Amounts of currency are serialized as a string of the format @code{:}. 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: @enumerate @item The @code{} part must be at most 11 characters long and may only consist of ASCII letters (@code{a-zA-Z}). @item The integer part of @code{} may be at most 2^52. @item The fractional part of @code{} may contain at most 8 decimal digits. @end enumerate @cartouche @quotation Note “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”. @end quotation @end cartouche An amount that is prefixed with a @code{+} or @code{-} character is also used in certain contexts. When no sign is present, the amount is assumed to be positive. @node Time,Cryptographic primitives,Amounts,Common encodings @anchor{rest time}@anchor{3a} @subsubsection Time In signed messages, time is represented using 64-bit big-endian values, denoting microseconds since the UNIX Epoch. @code{UINT64_MAX} represents “never”. @example struct GNUNET_TIME_Absolute @{ uint64_t timestamp_us; @}; struct GNUNET_TIME_AbsoluteNBO @{ uint64_t abs_value_us__; // in network byte order @}; @end example @node Cryptographic primitives,Signatures<3>,Time,Common encodings @anchor{rest cryptographic-primitives}@anchor{3b} @subsubsection 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). @example struct GNUNET_HashCode @{ uint8_t hash[64]; // usually SHA-512 @}; @end example @anchor{rest taler-ecdhephemeralpublickeyp}@anchor{3c} @example struct TALER_EcdhEphemeralPublicKeyP @{ uint8_t ecdh_pub[32]; @}; @end example @example struct UUID @{ uint32_t value[4]; @}; @end example @node Signatures<3>,Receiving Configuration,Cryptographic primitives,Common encodings @anchor{rest id1}@anchor{3d}@anchor{rest id2}@anchor{3e} @subsubsection Signatures Any piece of signed data, complies to the abstract data structure given below. @example 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; @}; @end example @anchor{rest salt}@anchor{3f} @node Receiving Configuration,Receiving Terms of Service,Signatures<3>,Common encodings @anchor{rest config}@anchor{40}@anchor{rest receiving-configuration}@anchor{41} @subsubsection Receiving Configuration @anchor{rest get--config}@anchor{42} @deffn {HTTP Get} GET /config Obtain the configuration details of the escrow provider. @strong{Response:} Returns an @ref{43,,EscrowConfigurationResponse}. @anchor{rest escrowconfigurationresponse}@anchor{43} @example 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; @} @end example @anchor{rest authorizationmethodconfig}@anchor{44} @example interface AuthorizationMethodConfig @{ // Name of the authorization method. type: string; // Fee for accessing key share using this method. cost: Amount; @} @end example @end deffn @node Receiving Terms of Service,Manage policy,Receiving Configuration,Common encodings @anchor{rest receiving-terms-of-service}@anchor{45}@anchor{rest terms}@anchor{46} @subsubsection Receiving Terms of Service @anchor{rest get--terms}@anchor{47} @deffn {HTTP Get} GET /terms Obtain the terms of service provided by the escrow provider. @strong{Response:} Returns the terms of service of the provider, in the best language and format available based on the client’s request. @end deffn @anchor{rest get--privacy}@anchor{48} @deffn {HTTP Get} GET /privacy Obtain the privacy policy of the service provided by the escrow provider. @strong{Response:} Returns the privacy policy of the provider, in the best language and format available based on the client’s request. @end deffn @node Manage policy,Managing truth,Receiving Terms of Service,Common encodings @anchor{rest id3}@anchor{49}@anchor{rest manage-policy}@anchor{4a} @subsubsection 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 @code{$ACCOUNT_PUB}, which should be kept secret from third parties. @code{$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@footnote{https://tools.ietf.org/html/rfc4122}. @anchor{rest get--policy-$ACCOUNT_PUB[?version=$NUMBER]}@anchor{4b} @deffn {HTTP Get} GET /policy/$ACCOUNT_PUB[?version=$NUMBER] Get the customer’s encrypted recovery document. If @code{version} is not specified, the server returns the latest available version. If @code{version} is specified, returns the policy with the respective @code{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: @itemize * @item the escrow policy @item the separately encrypted master public key @end itemize 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 @strong{truth}. The client MAY provide an @code{If-None-Match} header with an Etag. In that case, the server MUST additionally respond with an @code{304} status code in case the resource matches the provided Etag. @strong{Response}: @table @asis @item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}: The escrow provider responds with an @ref{4c,,EncryptedRecoveryDocument} object. @item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}: The client requested the same resource it already knows. @item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}: The @code{$ACCOUNT_PUB} is not an EdDSA public key. @item 402 Payment Required@footnote{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. @item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}: The required account signature was invalid. @item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}: The requested resource was not found. @end table @emph{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 @ref{4c,,EncryptedRecoveryDocument}. @emph{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 @code{200 OK}. @emph{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. @emph{Anastasis-Account-Signature}: The client must provide Base-32 encoded EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire to download the requested encrypted recovery document. The purpose used MUST be @code{TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD} (1401). @end deffn @anchor{rest post--policy-$ACCOUNT_PUB}@anchor{4d} @deffn {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. @strong{Request}: @*Query Parameters: @itemize * @item @code{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 @code{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 @code{304 Not modified} case. @item @code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will wait up to @code{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. @end itemize @emph{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 @code{Expect: 100-Continue} header and wait for @code{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 @code{304} status code if the Etag matches the latest version already known to the server. @emph{Anastasis-Policy-Signature}: The client must provide Base-32 encoded EdDSA signature over hash of body with @code{$ACCOUNT_PRIV}, affirming desire to upload an encrypted recovery document. @emph{Payment-Identifier}: Base-32 encoded 32-byte payment identifier that was included in a previous payment (see @code{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 @strong{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 @code{402} response. When making payments, the server must include a fresh, randomly-generated payment-identifier in the payment request. @strong{Response}: @table @asis @item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}: The encrypted recovery document was accepted and stored. @code{Anastasis-Version} and @code{Anastasis-UUID} headers indicate what version and UUID was assigned to this encrypted recovery document upload by the server. @item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}: The same encrypted recovery document was previously accepted and stored. @code{Anastasis-Version} header indicates what version was previously assigned to this encrypted recovery document. @item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}: The @code{$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. @item 402 Payment required@footnote{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. @item 403 Forbidden@footnote{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. @item 413 Request entity too large@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14}: The upload is too large @emph{or} too small. The response body may elaborate on the error. @end table @strong{Details:} @anchor{rest encryptedrecoverydocument}@anchor{4c} @example 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 @} @end example @anchor{rest recoverydocument}@anchor{4e} @example 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[]; @} @end example @anchor{rest escrowmethod}@anchor{4f} @example 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 `@w{`}/truth/`@w{`}. 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 @} @end example @anchor{rest decryptionpolicy}@anchor{50} @example 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[]; @} @end example @end deffn @node Managing truth,,Manage policy,Common encodings @anchor{rest managing-truth}@anchor{51}@anchor{rest truth}@anchor{52} @subsubsection Managing truth Truth always consists of an encrypted key share and encrypted authentication data. The key share and the authentication data are encrypted using different keys. Additionally, truth includes the name of the authentication method, the mime-type of the authentication data, and an expiration time in cleartext. This API is used by the Anastasis client to deposit @strong{truth} or request a (encrypted) @strong{key share} with the escrow provider. An @strong{escrow method} specifies an Anastasis provider and how the user should authorize themself. The @strong{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. @anchor{rest post--truth-$UUID}@anchor{53} @deffn {HTTP Post} POST /truth/$UUID Upload a @ref{54,,TruthUploadRequest}-Object according to the policy the client created before (see @ref{4e,,RecoveryDocument}). If request has been seen before, the server should do nothing, and otherwise store the new object. @strong{Request:} @*Query Parameters: @itemize * @item @code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will wait up to @code{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. @end itemize @strong{Response:} @table @asis @item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}: Truth stored successfully. @item 304 Not modified@footnote{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. @item 402 Payment required@footnote{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. @item 409 Conflict@footnote{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. @item 412 Precondition failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13}: The selected authentication method is not supported on this provider. @end table @strong{Details:} @anchor{rest truthuploadrequest}@anchor{54} @example 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; // 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: []; //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; @} @end example @end deffn @anchor{rest get--truth-$UUID}@anchor{55} @deffn {HTTP Get} GET /truth/$UUID Get the stored encrypted key share. Also, the user has to provide the correct @emph{truth_encryption_key} with every get request (see below). The encrypted key share is returned simply as a byte array and not in JSON format. @*Query Parameters: @itemize * @item @code{response=H_RESPONSE} – @emph{Optional.} If @code{$H_RESPONSE} is specified by the client, the server checks if @code{$H_RESPONSE} matches the expected response. This can be the hash of the security question (as specified before by the client within the @ref{54,,TruthUploadRequest} (see @code{encrypted_truth})), or the hash of the PIN code sent via SMS, E-mail or postal communication channels. When @code{$H_RESPONSE} is correct, the server responds with the encrypted key share. @item @code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will wait up to @code{timeout_ms} milliseconds for completion of the payment or the challenge before sending the HTTP response. A client must never rely on this behavior, as the backend may return a response immediately. @end itemize @strong{Response}: @table @asis @item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}: @ref{56,,EncryptedKeyShare} is returned in body (in binary). @item 202 Accepted@footnote{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. @item >>208 Already Reported<<: An authentication challenge was recently send, client should simply respond to the pending challenge. @item 303 See other@footnote{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 @code{Location} header and allow the user to re-try the operation after successful authorization. @item 402 Payment required@footnote{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. @item 403 Forbidden@footnote{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. @item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}: The server does not know any truth under the given UUID. @item 408 Request Timeout@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.9}: Accessing this truth requires satisfying an external authentication challenge (and not merely passing a response in the request) and this has not happened before the timeout was reached. @item 410 Gone@footnote{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.) @item 417 Expectation Failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18}: The decrypted @code{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. @item 503 Service Unavailable@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4}: Server is out of Service. @end table @emph{Truth-Decryption-Key}: Key used to encrypt the @strong{truth} (see encrypted_truth within @ref{54,,TruthUploadRequest}) and which has to provided by the user. The key is stored with the according @ref{4f,,EscrowMethod}. The server needs this key to get the info out of @ref{54,,TruthUploadRequest} needed to verify the @code{$RESPONSE}. @strong{Details:} @anchor{rest encryptedkeyshare}@anchor{56} @example 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 @} @end example @anchor{rest keyshare}@anchor{57} @example 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 `@w{`}key_share`@w{`}. account_sig: EddsaSignature; @} @end example @end deffn @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node Reducer API,Authentication Methods,REST API,Documentation Overview @anchor{reducer doc}@anchor{58}@anchor{reducer reducer-api}@anchor{59} @section 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 @ref{5a,,state} in JSON syntax and returns the new state in JSON syntax. For example a @strong{state} may take the following structure: @example @{ "backup_state": "CONTINENT_SELECTING", "continents": [ "Europe", "North_America" ] @} @end example The new state depends on the previous one and on the transition @ref{5b,,action} with its arguments given to the reducer. A @strong{transition argument} also is a statement in JSON syntax: @example @{ "continent": "Europe" @} @end example The new state returned by the reducer with the state and transition argument defined above would look like following for the transition @ref{5b,,action} @code{select_continent}: @example @{ "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" @} ] @} @end example @menu * States:: * Backup Reducer:: * Recovery Reducer:: * Reducer transitions:: @end menu @node States,Backup Reducer,,Reducer API @anchor{reducer states}@anchor{5c} @subsection States Overall, the reducer knows the following states: @quotation @itemize - @item @table @asis @item @strong{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. @end table @item @table @asis @item @strong{CONTINENT_SELECTING}: The user should specify the continent where they are living, so that we can show a list of countries to choose from. @end table @item @table @asis @item @strong{COUNTRY_SELECTING}: The user should specify the country where they are living, so that we can determine appropriate attributes, currencies and Anastasis providers. @end table @item @table @asis @item @strong{USER_ATTRIBUTES_COLLECTING}: The user should provide the country-specific personal attributes. @end table @item @table @asis @item @strong{AUTHENTICATIONS_EDITING}: The user should add authentication methods to be used during recovery. @end table @item @strong{POLICIES_REVIEWING}: The user should review the recovery policies. @item @strong{SECRET_EDITING}: The user should edit the secret to be backed up. @item @table @asis @item @strong{TRUTHS_PAYING}: The user needs to pay for one or more uploads of data associated with an authentication method. @end table @item @strong{POLICIES_PAYING}: The user needs to pay for storing the recovery policy document. @item @strong{BACKUP_FINISHED}: A backup has been successfully generated. @item @table @asis @item @strong{SECRET_SELECTING}: The user needs to select a recovery policy document with the secret that is to be recovered. @end table @item @table @asis @item @strong{CHALLENGE_SELECTING}: The user needs to select an authorization challenge to proceed with recovery. @end table @item @strong{CHALLENGE_PAYING}: The user needs to pay to proceed with the authorization challenge. @item @strong{CHALLENGE_SOLVING}: The user needs to solve the authorization challenge. @item @strong{RECOVERY_FINISHED}: The secret of the user has been recovered. @end itemize @end quotation State names: @quotation @itemize - @item 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). @item In COLLECTING-states, the user has to give certain values. @item In EDITING-states, the user is free to choose which values he wants to give. @item In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something. @item in PAYING-states, the user must make a payment. @item in FINISHED-states, the operation has definitively concluded. @end itemize @end quotation @node Backup Reducer,Recovery Reducer,States,Reducer API @anchor{reducer backup-reducer}@anchor{5d} @subsection Backup Reducer @anchor{reducer state}@anchor{5a}@anchor{reducer action}@anchor{5b} @float Figure @image{anastasis-figures/anastasis_reducer_backup,,,fig-anastasis_reducer_backup,png} @caption{Backup states and their transitions.} @end float The illustration above shows the different states the reducer can have during a backup process. @node Recovery Reducer,Reducer transitions,Backup Reducer,Reducer API @anchor{reducer recovery-reducer}@anchor{5e} @subsection Recovery Reducer @float Figure @image{anastasis-figures/anastasis_reducer_recovery,,,fig-anastasis_reducer_recovery,png} @caption{Recovery states and their transitions.} @end float The illustration above shows the different states the reducer can have during a recovery process. @node Reducer transitions,,Recovery Reducer,Reducer API @anchor{reducer reducer-transitions}@anchor{5f} @subsection 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. @menu * Initial state:: * Common transitions:: * Backup transitions:: * Recovery transitions:: @end menu @node Initial state,Common transitions,,Reducer transitions @anchor{reducer initial-state}@anchor{60} @subsubsection Initial state The initial states for backup and recovery processes are: @strong{Initial backup state:} @example @{ "backup_state": "CONTINENT_SELECTING", "continents": [ "Europe", "North America" ] @} @end example @strong{Initial recovery state:} @example @{ "recovery_state": "CONTINENT_SELECTING", "continents": [ "Europe", "North America" ] @} @end example 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 @code{continents_i18n} may be present. This field would be a map of language names to arrays of translated continent names: @example @{ "recovery_state": "CONTINENT_SELECTING", "continents": [ "Europe", "North America" ] "continents_i18n": @{ "de_DE" : [ "Europa", "Nordamerika" ], "de_CH" : [ "Europa", "Nordamerika" ] @} @} @end example Translations must be given in the same order as the main English array. @node Common transitions,Backup transitions,Initial state,Reducer transitions @anchor{reducer common-transitions}@anchor{61} @subsubsection Common transitions @strong{select_continent:} Here the user specifies the continent they live on. Arguments (example): @example @{ "continent": "Europe" @} @end example The continent must be given using the English name from the @code{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: @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" @} ] @} @end example Here @code{countries} is an array of countries on the @code{selected_continent}. For each country, the @code{code} is the ISO 3166-1 alpha-2 country code. The @code{continent} is only present because some countries span continents, the information is redundant and will always match @code{selected_continent}. The @code{name} is the name of the country in English, internationalizations of the name may be provided in @code{name_i18n}. The @code{currency} is @strong{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. @strong{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): @example @{ "country_code": "de", "currency": "EUR" @} @end example The @code{country_code} must be an ISO 3166-1 alpha-2 country code from the array of @code{countries} of the reducer’s state. The @code{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: @example @{ "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" @} @} @} @end example The array of @code{required_attributes} contains attributes about the user that must be provided includes: @quotation @itemize - @item @strong{type}: The type of the attribute, for now only @code{string} and @code{date} are supported. @item @strong{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. @item @strong{label}: A human-readable description of the attribute in English. Translated descriptions may be provided under @strong{label_i18n}. @item @strong{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 @strong{name}, only the @strong{uuid} will be identical if the semantics is identical. @item @strong{widget}: An optional name of a widget that is known to nicely render the attribute entry in user interfaces where named widgets are supported. @item @strong{validation-regex}: An optional extended POSIX regular expression that is to be used to validate (string) inputs to ensure they are well-formed. @item @strong{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). @item @strong{optional}: Optional boolean field that, if @code{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. @end itemize @end quotation 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: @quotation @itemize - @item @strong{http_status}: HTTP status code, always @code{200} on success. @item @strong{methods}: Array of authentication methods supported by this provider. Includes the @strong{type} of the authentication method and the @strong{usage_fee} (how much the user must pay for authorization using this method during recovery). @item @strong{annual_fee}: Fee the provider charges to store the recovery policy for one year. @item @strong{truth_upload_fee}: Fee the provider charges to store a key share. @item @strong{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. @item @strong{currency}: Currency in which the provider wants to be paid, will match all of the fees. @item @strong{storage_limit_in_megabytes}: Maximum size of an upload (for both recovery document and truth data) in megabytes. @item @strong{provider_name}: Human-readable name of the provider’s business. @item @strong{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. @end itemize @end quotation If contacting the provider failed, the information returned is: @quotation @itemize - @item @strong{http_status}: HTTP status code (if available, possibly 0 if we did not even obtain an HTTP response). @item @strong{error_code}: Taler error code, never 0. @end itemize @end quotation @strong{add_provider}: This operation can be performed in state @code{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: @example @{ "urls": [ "http://localhost:8888/", "http://localhost:8089/" ] @} @end example 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: @example @{ "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" @} @} @} @end example @node Backup transitions,Recovery transitions,Common transitions,Reducer transitions @anchor{reducer backup-transitions}@anchor{62} @subsubsection Backup transitions @strong{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 @code{null} or an empty string). Example arguments would be: @example @{ "identity_attributes": @{ "full_name": "Max Musterman", "social_security_number": "123456789", "birthdate": "2000-01-01", "birthplace": "Earth" @} @} @end example Note that at this stage, the state machines between backup and recovery diverge and the @code{recovery_state} will begin to look very different from the @code{backup_state}. For backups, if all required attributes are present, the reducer will transition to an @code{AUTHENTICATIONS_EDITING} state with the attributes added to it: @example @{ "backup_state": "AUTHENTICATIONS_EDITING", "identity_attributes": @{ "full_name": "Max Musterman", "social_security_number": "123456789", "birthdate": "2000-01-01", "birthplace": "Earth" @} @} @end example 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: @example @{ "backup_state": "ERROR", "code": 8404, "hint": "An input did not match the regular expression.", "detail": "social_security_number" @} @end example 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. @strong{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 @code{type} and @code{instructions} to be given to the user. The @code{challenge} is encrypted and stored at the Anastasis provider. The specific semantics of the value depend on the @code{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 @code{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 @code{mime_type} field must be provided to give the MIME type of the value encoded in @code{challenge}. @example @{ "authentication_method": @{ "type": "question", "mime_type" : "text/plain", "instructions" : "What is your favorite GNU package?", "challenge" : "E1QPPS8A", @} @} @end example If the information provided is valid, the reducer will add the new authentication method to the array of authentication methods: @example @{ "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" @} ] @} @end example @strong{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: @example @{ "authentication_method": 1 @} @end example Assuming we begin with the state from the example above, this would remove the @code{email} authentication method, resulting in the following response: @example @{ "backup_state": "AUTHENTICATIONS_EDITING", "authentication_methods": [ @{ "type": "question", "mime_type" : "text/plain", "instructions" : "What is your favorite GNU package?", "challenge" : "gdb", @} ] @} @end example If the index is invalid, the reducer will instead transition into an @code{ERROR} state. @strong{next} (from @code{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: @example @{ "providers": [ "http://localhost:8088/", "http://localhost:8089/" ] @} @end example The resulting state provides the suggested recovery policies in a way suitable for presentation to the user: @example @{ "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/" @} ] @} ] @} @end example For each recovery policy, the state includes the specific details of which authentication @code{methods} must be solved to recovery the secret using this policy. The @code{methods} array specifies the index of the @code{authentication_method} in the @code{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 @code{ERROR} state instead of suggesting policies. @strong{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: @example @{ "policy": [ @{ "authentication_method": 1, "provider": "http://localhost:8088/" @}, @{ "authentication_method": 3, "provider": "http://localhost:8089/" @} ] @} @end example Note that the specified providers must already be in the @code{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: @example @{ "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/" @} ] @} ] @} @end example 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 @code{ERROR} state instead of adding the new policy. @strong{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 @strong{add_policy}, except there is an additional key @code{policy_index} which identifies the policy to modify. An example for a possible argument would thus be: @example @{ "policy_index" : 1, "policy": [ @{ "authentication_method": 1, "provider": "http://localhost:8088/" @}, @{ "authentication_method": 3, "provider": "http://localhost:8089/" @} ] @} @end example 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 @code{ERROR} state instead of modifying the policy. @strong{delete_policy:} This transition allows the deletion of a recovery policy. The argument simply specifies the index of the policy to delete, for example: @example @{ "policy_index": 3 @} @end example Given as input the state from the example above, the expected new state would be: @example @{ "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/" @} ] @} ] @} @end example If the index given is invalid, the reducer will transition into an @code{ERROR} state instead of deleting a policy. @strong{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: @example @{ "policy_index": 1, "challenge_index" : 1 @} @end example Given as input the state from the example above, the expected new state would be: @example @{ "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/" @} ] @} ] @} @end example If the index given is invalid, the reducer will transition into an @code{ERROR} state instead of deleting a challenge. @strong{next} (from @code{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 @code{SECRET_EDITING} state: @example @{ "backup_state": "SECRET_EDITING", "upload_fees" : [ "KUDOS:42" ], "expiration" : @{ "t_ms" : 1245362362 @} @} @end example Here, @code{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 @code{policies} is currently empty, the reducer will transition into an @code{ERROR} state instead of allowing the user to continue. @strong{enter_secret:} This transition provides the reducer with the actual core @code{secret} of the user that Anastasis is supposed to backup (and possibly recover). The argument is simply the Crockford-Base32 encoded @code{value} together with its @code{mime} type, or a @code{text} field with a human-readable secret text. For example: @example @{ "secret": @{ "value": "EDJP6WK5EG50", "mime" : "text/plain" @}, "expiration" : @{ "t_ms" : 1245362362 @} @} @end example If the application is unaware of the format, it set the @code{mime} field to @code{null}. The @code{expiration} field is optional. The reducer remains in the @code{SECRET_EDITING} state, but now the secret and updated expiration time are part of the state and the cost calculations will be updated. @example @{ "backup_state": "SECRET_EDITING", "core_secret" : @{ "value": "EDJP6WK5EG50", "mime" : "text/plain" @}, "expiration" : @{ "t_ms" : 1245362362 @}, "upload_fees" : [ "KUDOS:42" ] @} @end example @strong{clear_secret:} This transition removes the core secret from the state. It is simply a convenience function to undo @code{enter_secret} without providing a new value immediately. The transition takes no arguments. The resuting state will no longer have the @code{core_secret} field, and be otherwise unchanged. Calling @strong{clear_secret} on a state without a @code{core_secret} will result in an error. @strong{enter_secret_name:} This transition provides the reducer with a name for the core @code{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 built-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: @example @{ "name": "_TALERWALLET_MyPinePhone", @} @end example Here, @code{MyPinePhone} might be chosen by the user to identify the device that was being backed up. The reducer remains in the @code{SECRET_EDITING} state, but now the secret name is updated: @example @{ "secret_name" : "_TALERWALLET_MyPinePhone" @} @end example @strong{update_expiration:} This transition asks the reducer to change the desired expiration time and to update the associated cost. For example: @example @{ "expiration" : @{ "t_ms" : 1245362362 @} @} @end example The reducer remains in the @code{SECRET_EDITING} state, but the expiration time and cost calculation will be updated. @example @{ "backup_state": "SECRET_EDITING", "expiration" : @{ "t_ms" : 1245362362 @}, "upload_fees" : [ @{ "fee": "KUDOS:43" @} ] @} @end example @strong{next} (from @code{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 @code{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 @code{secret} will be stored in the state under @code{core_secret}. Applications should be careful when persisting the resulting state, as the @code{core_secret} is not protected in the @code{PAYING} states. The @code{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 @code{BACKUP_FINISHED} state and (if applicable) delete the @code{core_secret} as an additional safety measure. Example results are thus: @example @{ "backup_state": "TRUTHS_PAYING", "secret_name" : "$NAME", "core_secret" : @{ "$anything":"$anything" @}, "payments": [ "taler://pay/...", "taler://pay/..." ] @} @end example @example @{ "backup_state": "POLICIES_PAYING", "secret_name" : "$NAME", "core_secret" : @{ "$anything":"$anything" @}, "payments": [ "taler://pay/...", "taler://pay/..." ] @} @end example @example @{ "backup_state": "BACKUP_FINISHED", "success_details": @{ "http://localhost:8080/" : @{ "policy_version" : 1, "policy_expiration" : @{ "t_ms" : 1245362362000 @} @}, "http://localhost:8081/" : @{ "policy_version" : 3, "policy_expiration" : @{ "t_ms" : 1245362362000 @} @} @} @} @end example @strong{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 @code{timeout} value that specifies how long the reducer may wait (in long polling) for the payment to complete: @example @{ "timeout": @{ "d_ms" : 5000 @}, @} @end example 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 @code{BACKUP_FINISHED} state (if all payments have been completed and the backup finished), or into an @code{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: @example @{ "backup_state": "ERROR", "http_status" : 500, "upload_status" : 52, "provider_url" : "https://bad.example.com/", @} @end example Here, the fields have the following meaning: @quotation @itemize - @item @strong{http_status} is the HTTP status returned by the Anastasis provider. @item @strong{upload_status} is the Taler error code return by the provider. @item @strong{provider_url} is the base URL of the failing provider. @end itemize @end quotation In the above example, 52 would thus imply that the Anastasis provider failed to store information into its database. @node Recovery transitions,,Backup transitions,Reducer transitions @anchor{reducer recovery-transitions}@anchor{63} @subsubsection Recovery transitions @strong{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 @code{null} or an empty string). The arguments are identical to the @strong{enter_user_attributes} transition from the backup process. Example arguments would thus be: @example @{ "identity_attributes": @{ "full_name": "Max Musterman", "social_security_number": "123456789", "birthdate": "2000-01-01", "birthplace": "Earth" @} @} @end example 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: @example @{ "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": @{ "...": "..." @} @} @end example The @code{recovery_document} is an internal representation of the recovery information and of no concern to the user interface. The pertinent information is in the @code{recovery_information}. Here, the @code{challenges} array is a list of possible challenges the user could attempt to solve next, while @code{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 @code{provider_url} from where the recovery document was obtained and its @code{version} are also provided. Each challenge comes with four mandatory fields: @quotation @itemize - @item @strong{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. @item @strong{cost}: This is the amount the Anastasis provider will charge to allow the user to pass the challenge. @item @strong{type}: This is the type of the challenge, as a string. @item @strong{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 @code{type}. @end itemize @end quotation 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 @code{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: @example @{ "recovery_state": "ERROR", "error_message": "account unknown to Anastasis server", "error_code": 9, @} @end example Here, the @code{error_code} is from the @code{enum ANASTASIS_RecoveryStatus} and describes precisely what failed about the download, while the @code{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 @code{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. @strong{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 @code{change_version} transition, which takes a provider URL and policy version as arguments: @example @{ "provider_url": "https://localhost:8080/", "version": 2 @} @end example Note that using a version of 0 implies fetching “the latest version”. The resulting states are the same as those of the @code{enter_user_attributes} transition, except that the recovery document version is not necessarily the latest available version at the provider. @strong{select_challenge:} Selecting a challenge takes different, depending on the state of the payment. A comprehensive example for @code{select_challenge} would be: @example @{ "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" "timeout" : @{ "d_ms" : 5000 @}, "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG" @} @end example The @code{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 @code{payment_secret} identifies the previous payment request, and @code{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 @code{CHALLENGE_SOLVING} or @code{CHALLENGE_PAYING} states. In @code{CHALLENGE_SOLVING}, the new state will primarily specify the selected challenge: @example @{ "backup_state": "CHALLENGE_SOLVING", "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" @} @end example In @code{CHALLENGE_PAYING}, the new state will include instructions for payment in the @code{challenge_feedback}. In general, @code{challenge_feedback} includes information about attempted challenges, with the final state being @code{solved}: @example @{ "recovery_state": "CHALLENGE_SELECTING", "recovery_information": @{ "...": "..." @} "challenge_feedback": @{ "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{ "state" : "solved" @} @} @} @end example Challenges feedback for a challenge can have many different @code{state} values that applications must all handle. States other than @code{solved} are: @quotation @itemize - @item @strong{payment}: Here, the user must pay for a challenge. An example would be: @example @{ "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" @} @} @} @end example @end itemize @quotation @itemize - @item @strong{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. @example @{ "recovery_state": "CHALLENGE_SOLVING", "recovery_information": @{ "...": "..." @} "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0", "challenge_feedback": @{ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{ "state": "body", "body": "CROCKFORDBASE32ENCODEDBODY", "http_status": 403, "mime_type" : "anything/possible" @} @} @} @end example @item @strong{hint}: Here, the server provided human-readable hint for how to solve the challenge. Note that the @code{hint} provided this time is from the Anastasis provider and may differ from the @code{instructions} for the challenge under @code{recovery_information}: @example @{ "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 @} @} @} @end example @item @strong{details}: Here, the server provided a detailed JSON status response related to solving the challenge: @example @{ "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 @} @} @} @end example @end itemize @quotation @itemize - @item @strong{redirect}: To solve the challenge, the user must visit the indicated Web site at @code{redirect_url}, for example to perform video authentication: @end itemize @quotation @example @{ "recovery_state": "CHALLENGE_SOLVING", "recovery_information": @{ "...": "..." @} "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0", "challenge_feedback": @{ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{ "state": "redirect", "redirect_url": "https://videoconf.example.com/", "http_status": 303 @} @} @} @end example @itemize - @item @strong{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. @end itemize @example @{ "recovery_state": "CHALLENGE_SELECTING", "recovery_information": @{ "...": "..." @} "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0", "challenge_feedback": @{ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{ "state": "server-failure", "http_status": "500", "error_code": 52 @} @} @} @end example @itemize - @item @strong{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. @end itemize @example @{ "recovery_state": "CHALLENGE_SELECTING", "recovery_information": @{ "...": "..." @} "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0", "challenge_feedback": @{ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{ "state": "truth-unknown", "error_code": 8108 @} @} @} @end example @itemize - @item @strong{rate-limit-exceeded}: @end itemize @example @{ "recovery_state": "CHALLENGE_SELECTING", "recovery_information": @{ "...": "..." @} "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0", "challenge_feedback": @{ "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{ "state": "rate-limit-exceeded", "error_code": 8121 @} @} @} @end example @end quotation @end quotation @end quotation @end quotation @strong{pay:} With a @code{pay} transition, the application indicates to the reducer that a payment may have been made. Here, it is again possible to specify an optional @code{timeout} argument for long-polling, for example: @example @{ "payment_secret": "ABCDADF242525AABASD52525235ABABFDABABANALASDAAKASDAS" "timeout" : @{ "d_ms" : 5000 @}, @} @end example Depending on the type of the challenge and the result of the operation, the new state may be @code{CHALLENGE_SOLVING} (if say the SMS was now sent to the user), @code{CHALLENGE_SELECTING} (if the answer to the security question was correct), @code{RECOVERY_FINISHED} (if this was the last challenge that needed to be solved) or still @code{CHALLENGE_PAYING} (if the challenge was not actually paid for). For sample messages, see the different types of @code{challenge_feedback} in the section about @code{select_challenge}. @strong{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: @example @{ "answer": "answer to security question" @} @end example @example @{ "pin": 1234 @} @end example @example @{ "hash": "SOMEBASE32ENCODEDHASHVALUE" @} @end example @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node Authentication Methods,DB Schema,Reducer API,Documentation Overview @anchor{authentication doc}@anchor{64}@anchor{authentication anastasis-auth-methods}@anchor{65}@anchor{authentication authentication-methods}@anchor{66} @section 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. @menu * SMS (sms): SMS sms. * Email verification (email): Email verification email. * Video identification (vid): Video identification vid. * Security question (qa): Security question qa. * Snail mail verification (post): Snail mail verification post. @end menu @node SMS sms,Email verification email,,Authentication Methods @anchor{authentication sms-sms}@anchor{67} @subsection SMS (sms) Sends an SMS with a code (prefixed with @code{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 @code{$RESPONSE} under @ref{52,,Managing truth}). If the transmitted code is correct, the server responses with the requested encrypted key share. @node Email verification email,Video identification vid,SMS sms,Authentication Methods @anchor{authentication email-verification-email}@anchor{68} @subsection Email verification (email) Sends an email with a code (prefixed with @code{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 @code{$RESPONSE} under @ref{52,,Managing truth}). If the transmitted code is correct, the server responses with the requested encrypted key share. @node Video identification vid,Security question qa,Email verification email,Authentication Methods @anchor{authentication video-identification-vid}@anchor{69} @subsection Video identification (vid) Requires the user to identify via video-call. In the video-call, the user is told the code (prefixed with @code{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. @node Security question qa,Snail mail verification post,Video identification vid,Authentication Methods @anchor{authentication security-question-qa}@anchor{6a} @subsection Security question (qa) Asks the user a security question. The user sends back a @strong{salted} hash over the answer. The @strong{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 @strong{key-salt} for the decryption of the (encrypted) @strong{key share}. This ensures that the key share remains irrecoverable without the answer even if the Anastasis provider storing the security question is malicious. @node Snail mail verification post,,Security question qa,Authentication Methods @anchor{authentication snail-mail-verification-post}@anchor{6b} @subsection Snail mail verification (post) Sends physical mail (snail mail) with a code (prefixed with @code{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 @code{$RESPONSE} under @ref{52,,Managing truth}). If the transmitted code is correct, the server responds with the requested encrypted key share. @c This file is part of Anastasis @c Copyright (C) 2019-2021 Anastasis SARL @c @c Anastasis is free software; you can redistribute it and/or modify it under the @c terms of the GNU Affero General Public License as published by the Free Software @c Foundation; either version 2.1, or (at your option) any later version. @c @c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY @c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR @c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. @c @c You should have received a copy of the GNU Affero General Public License along with @c Anastasis; see the file COPYING. If not, see @c @c @author Christian Grothoff @c @author Dominik Meister @c @author Dennis Neufeld @node DB Schema,Anastasis licensing information,Authentication Methods,Documentation Overview @anchor{db doc}@anchor{6c}@anchor{db db-schema}@anchor{6d} @section DB Schema @image{anastasis-figures/anastasis-db,,,,png} @image{anastasis-figures/anastasis_challengecode,,,,png} @image{anastasis-figures/anastasis_challenge_payment,,,,png} @image{anastasis-figures/anastasis_truth,,,,png} @image{anastasis-figures/anastasis_truth_payment,,,,png} @node Anastasis licensing information,Man Pages,DB Schema,Documentation Overview @anchor{global-licensing doc}@anchor{6e}@anchor{global-licensing anastasis-licensing-information}@anchor{6f} @section 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. @menu * Anastasis (git;//git.taler.net/anastasis): Anastasis git //git taler net/anastasis. * Anastasis-gtk (git;//git.taler.net/anastasis-gtk): Anastasis-gtk git //git taler net/anastasis-gtk. * Documentation:: @end menu @node Anastasis git //git taler net/anastasis,Anastasis-gtk git //git taler net/anastasis-gtk,,Anastasis licensing information @anchor{global-licensing anastasis-git-git-taler-net-anastasis}@anchor{70}@anchor{global-licensing exchange-repo}@anchor{71} @subsection Anastasis (git://git.taler.net/anastasis) Anastasis core logic is under AGPL. @menu * Runtime dependencies:: @end menu @node Runtime dependencies,,,Anastasis git //git taler net/anastasis @anchor{global-licensing runtime-dependencies}@anchor{72} @subsubsection Runtime dependencies The following list encompasses all the runtime dependencies for this project, and gives the copyright holder for each of them: @itemize * @item libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals @item libgcrypt: LGPL, owned by Free Software Foundation @item postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL Global Development Group @item libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V. @item libgnunetjson: GPLv3+, GNUnet e.V. @item GNU Taler: LGPLv3+ / GPLv3+ / AGPLv3+: owned by Taler Systems SA @end itemize @node Anastasis-gtk git //git taler net/anastasis-gtk,Documentation,Anastasis git //git taler net/anastasis,Anastasis licensing information @anchor{global-licensing anastasis-gtk-git-git-taler-net-anastasis-gtk}@anchor{73} @subsection Anastasis-gtk (git://git.taler.net/anastasis-gtk) Anastasis-gtk is under AGPL. @menu * Runtime dependencies: Runtime dependencies<2>. @end menu @node Runtime dependencies<2>,,,Anastasis-gtk git //git taler net/anastasis-gtk @anchor{global-licensing id1}@anchor{74} @subsubsection Runtime dependencies The following list encompasses all the runtime dependencies for this project, and gives the copyright holder for each of them: @itemize * @item libjansson: MIT License, AGPL- and LGPL-Compatible, owned by Petri Lehtinen and other individuals @item libgcrypt: LGPL, owned by Free Software Foundation @item postgresql: PostgreSQL License, AGPL- and LGPL-Compatible, owned by The PostgreSQL Global Development Group @item libgnunetutil (in all of its variants): GPLv3+, owned by GNUnet e.V. @item libgnunetjson: GPLv3+, GNUnet e.V. @item libgnunetgtk: GPLv3+, GNUnet e.V. @item GNU Taler: LGPLv3+ / GPLv3+ / AGPLv3+: owned by Taler Systems SA @end itemize @node Documentation,,Anastasis-gtk git //git taler net/anastasis-gtk,Anastasis licensing information @anchor{global-licensing documentation}@anchor{75} @subsection Documentation The documentation is licensed under the GNU Free Documentation License Version 1.3 or later. @node Man Pages,Complete Index,Anastasis licensing information,Documentation Overview @anchor{manindex doc}@anchor{76}@anchor{manindex man-pages}@anchor{77} @section Man Pages @menu * anastasis-config(1): anastasis-config 1. * anastasis-gtk(1): anastasis-gtk 1. * anastasis-httpd(1): anastasis-httpd 1. * anastasis-reducer(1): anastasis-reducer 1. * anastasis.conf(5): anastasis conf 5. @end menu @node anastasis-config 1,anastasis-gtk 1,,Man Pages @anchor{manpages/anastasis-config 1 doc}@anchor{78}@anchor{manpages/anastasis-config 1 anastasis-config-1}@anchor{79} @subsection anastasis-config(1) @menu * Synopsis:: * Description:: * See Also:: * Bugs:: @end menu @node Synopsis,Description,,anastasis-config 1 @anchor{manpages/anastasis-config 1 synopsis}@anchor{7a} @subsubsection Synopsis @strong{anastasis-config} [@strong{-b} @emph{backend} | @strong{––supported-backend=}@emph{backend}] [@strong{-c} @emph{filename} | @strong{––config=}@emph{filename}] [@strong{-f} | @strong{––filename}] [@strong{-F} | @strong{––full}] [@strong{-h} | @strong{––help}] [@strong{-L} @emph{loglevel} | @strong{––loglevel=}@emph{loglevel}] [@strong{-l} @emph{filename} | @strong{––logfile=}‌@emph{filename}] [@strong{-o} @emph{option} | @strong{––option=}@emph{option}] [@strong{-r} | @strong{––rewrite}] [@strong{-S} | @strong{––list-sections}] [@strong{-s} @emph{section} | @strong{––section=}@emph{section}] [@strong{-V} @emph{value} | @strong{––value=}@emph{value}] [@strong{-v} | @strong{––version}] @node Description,See Also,Synopsis,anastasis-config 1 @anchor{manpages/anastasis-config 1 description}@anchor{7b} @subsubsection Description @strong{anastasis-config} can be used to read or modify Anastasis configuration files. @table @asis @item @strong{-b} @emph{BACKEND} | @strong{––supported-backend=}@emph{BACKEND} Tests whether the specified @emph{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 @emph{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). @item @strong{-c} @emph{FILENAME} | @strong{––config=}@emph{FILENAME} Use the configuration file @emph{FILENAME}. @item @strong{-f} | @strong{––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). @item @strong{-F} | @strong{––full} Write the full configuration file, not just the differences to the defaults. @item @strong{-h} | @strong{––help} Print short help on options. @item @strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}@emph{LOGLEVEL} Use @emph{LOGLEVEL} for logging. Valid values are @code{DEBUG}, @code{INFO}, @code{WARNING}, and @code{ERROR}. @item @strong{-l} @emph{FILENAME} | @strong{––logfile=}‌@emph{FILENAME} Send logging output to @emph{FILENAME}. @item @strong{-o} @emph{OPTION} | @strong{––option=}@emph{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”. @item @strong{-r} | @strong{––rewrite} Write the configuration file even if nothing changed. Will remove all comments! @item @strong{-S} | @strong{––list-sections} List available configuration sections for use with @code{--section}. @item @strong{-s} @emph{SECTION} | @strong{––section=}@emph{SECTION} Which configuration section should be accessed or edited. Required option. @item @strong{-V} @emph{VALUE} | @strong{––value=}@emph{VALUE} Configuration value to store in the given section under the given option. Must only be given together with @code{-s} and @code{-o} options. @table @asis @item Note: Changing the configuration file with @code{-V} will remove comments and may reorder sections and remove @code{@@INLINE@@} directives. @end table @item @strong{-v} | @strong{––version} Print Anastasis version number. @end table @node See Also,Bugs,Description,anastasis-config 1 @anchor{manpages/anastasis-config 1 see-also}@anchor{7c} @subsubsection See Also anastasis.conf(5) @node Bugs,,See Also,anastasis-config 1 @anchor{manpages/anastasis-config 1 bugs}@anchor{7d} @subsubsection Bugs Report bugs by using @indicateurl{https://bugs.anastasis.lu} or by sending electronic mail to <@email{contact@@anastasis.lu}>. @node anastasis-gtk 1,anastasis-httpd 1,anastasis-config 1,Man Pages @anchor{manpages/anastasis-gtk 1 doc}@anchor{7e}@anchor{manpages/anastasis-gtk 1 anastasis-gtk-1}@anchor{7f} @subsection anastasis-gtk(1) @menu * Synopsis: Synopsis<2>. * Description: Description<2>. * See Also: See Also<2>. * Bugs: Bugs<2>. @end menu @node Synopsis<2>,Description<2>,,anastasis-gtk 1 @anchor{manpages/anastasis-gtk 1 synopsis}@anchor{80} @subsubsection Synopsis @strong{anastasis-gtk} [@strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME}] [@strong{-h} | @strong{––help}] [@strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL}] [@strong{-l} @emph{FILENAME} | @strong{––logfile=}‌@emph{FILENAME}] [@strong{-v} | @strong{––version}] @node Description<2>,See Also<2>,Synopsis<2>,anastasis-gtk 1 @anchor{manpages/anastasis-gtk 1 description}@anchor{81} @subsubsection Description @strong{anastasis-gtk} is a graphical tool to run Anastasis key recover and backup operations. @table @asis @item @strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME} Use the configuration from @emph{FILENAME}. @item @strong{-h} | @strong{––help} Print short help on options. @item @strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL} Specifies the log level to use. Accepted values are: @code{DEBUG}, @code{INFO}, @code{WARNING}, @code{ERROR}. @item @strong{-l} @emph{FILENAME} | @strong{––logfile=}‌@emph{FILENAME} Send logging output to @emph{FILENAME}. @item @strong{-v} | @strong{––version} Print version information. @end table @node See Also<2>,Bugs<2>,Description<2>,anastasis-gtk 1 @anchor{manpages/anastasis-gtk 1 see-also}@anchor{82} @subsubsection See Also anastasis-reducer(1), anastasis-httpd(1), anastasis.conf(5). @node Bugs<2>,,See Also<2>,anastasis-gtk 1 @anchor{manpages/anastasis-gtk 1 bugs}@anchor{83} @subsubsection Bugs Report bugs by using @indicateurl{https://bugs.anastasis.lu/} or by sending electronic mail to <@email{contact@@anastasis.lu}>. @node anastasis-httpd 1,anastasis-reducer 1,anastasis-gtk 1,Man Pages @anchor{manpages/anastasis-httpd 1 doc}@anchor{84}@anchor{manpages/anastasis-httpd 1 anastasis-httpd-1}@anchor{85} @subsection anastasis-httpd(1) @menu * Synopsis: Synopsis<3>. * Description: Description<3>. * Signals:: * See also:: * Bugs: Bugs<3>. @end menu @node Synopsis<3>,Description<3>,,anastasis-httpd 1 @anchor{manpages/anastasis-httpd 1 synopsis}@anchor{86} @subsubsection Synopsis @strong{anastasis-httpd} @node Description<3>,Signals,Synopsis<3>,anastasis-httpd 1 @anchor{manpages/anastasis-httpd 1 description}@anchor{87} @subsubsection 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: @table @asis @item @strong{-C} | @strong{–connection-close} Force each HTTP connection to be closed after each request. @item @strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME} Use the configuration and other resources for the merchant to operate from FILENAME. @item @strong{-h} | @strong{––help} Print short help on options. @item @strong{-v} | @strong{––version} Print version information. @end table @node Signals,See also,Description<3>,anastasis-httpd 1 @anchor{manpages/anastasis-httpd 1 signals}@anchor{88} @subsubsection Signals @strong{anastasis-httpd} responds to the following signals: @table @asis @item @code{SIGTERM} Sending a SIGTERM to the process will cause it to shutdown cleanly. @end table @node See also,Bugs<3>,Signals,anastasis-httpd 1 @anchor{manpages/anastasis-httpd 1 see-also}@anchor{89} @subsubsection See also anastasis-dbinit(1), anastasis-config(1), anastasis-gtk(1), anastasis-reducer(1) @node Bugs<3>,,See also,anastasis-httpd 1 @anchor{manpages/anastasis-httpd 1 bugs}@anchor{8a} @subsubsection Bugs Report bugs by using @indicateurl{https://bugs.anastasis.lu} or by sending electronic mail to <@email{contact@@anastasis.lu}>. @node anastasis-reducer 1,anastasis conf 5,anastasis-httpd 1,Man Pages @anchor{manpages/anastasis-reducer 1 doc}@anchor{8b}@anchor{manpages/anastasis-reducer 1 anastasis-reducer-1}@anchor{8c} @subsection anastasis-reducer(1) @menu * Synopsis: Synopsis<4>. * Description: Description<4>. * See Also: See Also<3>. * Bugs: Bugs<4>. @end menu @node Synopsis<4>,Description<4>,,anastasis-reducer 1 @anchor{manpages/anastasis-reducer 1 synopsis}@anchor{8d} @subsubsection Synopsis @strong{anastasis-reducer} [@strong{-a**_*JSON*_|_}–arguments=@emph{JSON}] [@strong{-b**_|_}–backup] [@strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME}] [@strong{-h} | @strong{––help}] [@strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL}] [@strong{-l} @emph{FILENAME} | @strong{––logfile=}‌@emph{FILENAME}] [@strong{-r**_|_}–restore] [@strong{-v} | @strong{––version}] COMMAND @node Description<4>,See Also<3>,Synopsis<4>,anastasis-reducer 1 @anchor{manpages/anastasis-reducer 1 description}@anchor{8e} @subsubsection Description @strong{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 @strong{-a} option. A list of commands can be found in the @ref{58,,Reducer API} chapter. @table @asis @item @strong{-a} @emph{JSON} | @strong{––arguments=}@emph{JSON} Provide JSON inputs for the given command. @item @strong{-b} | @strong{–backup} Begin fresh reducer operation for a back up operation. @item @strong{-c} @emph{FILENAME} | @strong{––config=}‌@emph{FILENAME} Use the configuration from @emph{FILENAME}. @item @strong{-h} | @strong{––help} Print short help on options. @item @strong{-L} @emph{LOGLEVEL} | @strong{––loglevel=}‌@emph{LOGLEVEL} Specifies the log level to use. Accepted values are: @code{DEBUG}, @code{INFO}, @code{WARNING}, @code{ERROR}. @item @strong{-l} @emph{FILENAME} | @strong{––logfile=}‌@emph{FILENAME} Send logging output to @emph{FILENAME}. @item @strong{-r} | @strong{–restore} Begin fresh reducer operation for a restore operation. @item @strong{-v} | @strong{––version} Print version information. @end table @node See Also<3>,Bugs<4>,Description<4>,anastasis-reducer 1 @anchor{manpages/anastasis-reducer 1 see-also}@anchor{8f} @subsubsection See Also anastasis-gtk(1), anastasis-httpd(1), anastasis.conf(5). @node Bugs<4>,,See Also<3>,anastasis-reducer 1 @anchor{manpages/anastasis-reducer 1 bugs}@anchor{90} @subsubsection Bugs Report bugs by using @indicateurl{https://bugs.anastasis.lu/} or by sending electronic mail to <@email{contact@@anastasis.lu}>. @node anastasis conf 5,,anastasis-reducer 1,Man Pages @anchor{manpages/anastasis conf 5 doc}@anchor{91}@anchor{manpages/anastasis conf 5 anastasis-conf-5}@anchor{92} @subsection anastasis.conf(5) @menu * Description: Description<5>. * SEE ALSO:: * BUGS:: @end menu @node Description<5>,SEE ALSO,,anastasis conf 5 @anchor{manpages/anastasis conf 5 description}@anchor{93} @subsubsection Description The configuration file is line-oriented. Blank lines and whitespace at the beginning and end of a line are ignored. Comments start with @code{#} or @code{%} 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 @code{=} (equal sign). Section names and options are @emph{case-insensitive}. The values, however, are @emph{case-sensitive}. In particular, boolean values are one of @code{YES} or @code{NO}. Values can include whitespace by surrounding the entire value with @code{"} (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 @code{/bin/sh}-like variable reference. This can be simple, such as @code{$TMPDIR/foo}, or complex, such as @code{$@{TMPDIR:-$@{TMP:-/tmp@}@}/foo}. See @code{[PATHS]} (below). Values that represent a time duration are represented as a series of one or more @code{NUMBER UNIT} pairs, e.g. @code{60 s}, @code{4 weeks 1 day}, @code{5 years 2 minutes}. Values that represent an amount are in the usual amount syntax: @code{CURRENCY:VALUE.FRACTION}, e.g. @code{EUR:1.50}. The @code{FRACTION} portion may extend up to 8 places. Files containing default values for many of the options described below are installed under @code{$ANASTASIS_PREFIX/share/taler/config.d/}. The configuration file given with @strong{-c} to Anastasis binaries overrides these defaults. A configuration file may include another, by using the @code{@@INLINE@@} directive, for example, in @code{main.conf}, you could write @code{@@INLINE@@ sub.conf} to include the entirety of @code{sub.conf} at that point in @code{main.conf}. .. TODO: Document ‘anastasis-config -V’ in light of ‘@@INLINE@@’ in taler-config(1). @menu * GLOBAL OPTIONS:: * Authorization options:: * Postgres database configuration:: @end menu @node GLOBAL OPTIONS,Authorization options,,Description<5> @anchor{manpages/anastasis conf 5 global-options}@anchor{94} @subsubsection GLOBAL OPTIONS The following options are from the @code{[anastasis]} section and used by the @strong{anastasis-httpd} service. @table @asis @item PAYMENT_BACKEND_URL Base-URL of the Taler merchant backend instance to use for payments. FIXME: How do we pass the access token? @item ANNUAL_FEE Annual fee to be paid for policy uploads, i.e. “EUR:1.5”. @item TRUTH_UPLOAD_FEE Annual fee to be paid for truth uploads, i.e. “EUR:1.5”. @item DB Database backend to use, only @code{postgres} is supported right now. @item UPLOAD_LIMIT_MB Maximum upload size for policy uploads in megabytes. Default is 1. @item ANNUAL_POLICY_UPLOAD_LIMIT Maximum number of policies uploaded per year of service. Default is 42. @item BUSINESS_NAME Name of the business. @item SERVER_SALT Must be set to a high-entropy random server salt that the provider must never change after the initial configuration. @item PORT TCP port on which the HTTP service should listen on. @end table @node Authorization options,Postgres database configuration,GLOBAL OPTIONS,Description<5> @anchor{manpages/anastasis conf 5 authorization-options}@anchor{95} @subsubsection Authorization options For each active authorization plugin, options must be configured in a section called @code{[authorization-$PLUGIN]} where @code{$PLUGIN} is the name of the authorization plugin. @table @asis @item COST Fee the user has to pay to obtain a challenge from this authorization plugin during recovery. @item ENABLED @code{yes} to enable this plugin, @code{no} to disable. @item COMMAND Helper command to run (only relevant for some plugins). @end table @node Postgres database configuration,,Authorization options,Description<5> @anchor{manpages/anastasis conf 5 postgres-database-configuration}@anchor{96} @subsubsection Postgres database configuration The following options must be in the section @code{[statis-postgres]} if @code{postgres} was used for the database under @code{DB} in the @code{[anastasis]} section. @table @asis @item CONFIG Path under which the Postgres database is that the service should use, i.e. @code{postgres://anastasis}. @end table @node SEE ALSO,BUGS,Description<5>,anastasis conf 5 @anchor{manpages/anastasis conf 5 see-also}@anchor{97} @subsubsection SEE ALSO anastasis-httpd(1), anastasis-config(1) @node BUGS,,SEE ALSO,anastasis conf 5 @anchor{manpages/anastasis conf 5 bugs}@anchor{98} @subsubsection BUGS Report bugs by using @indicateurl{https://bugs.anastasis.lu/} or by sending electronic mail to <@email{contact@@anastasis.lu}>. @node Complete Index,GNU Free Documentation License,Man Pages,Documentation Overview @anchor{genindex doc}@anchor{99}@anchor{genindex complete-index}@anchor{9a} @section Complete Index @node GNU Free Documentation License,,Complete Index,Documentation Overview @anchor{fdl-1 3 doc}@anchor{9b}@anchor{fdl-1 3 gnu-fdl-1-3}@anchor{9c}@anchor{fdl-1 3 gnu-free-documentation-license}@anchor{9d} @section GNU Free Documentation License Version 1.3, 3 November 2008 Copyright (C) 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc. @indicateurl{https://fsf.org/} Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. @menu * 0. PREAMBLE: 0 PREAMBLE. * 1. APPLICABILITY AND DEFINITIONS: 1 APPLICABILITY AND DEFINITIONS. * 2. VERBATIM COPYING: 2 VERBATIM COPYING. * 3. COPYING IN QUANTITY: 3 COPYING IN QUANTITY. * 4. MODIFICATIONS: 4 MODIFICATIONS. * 5. COMBINING DOCUMENTS: 5 COMBINING DOCUMENTS. * 6. COLLECTIONS OF DOCUMENTS: 6 COLLECTIONS OF DOCUMENTS. * 7. AGGREGATION WITH INDEPENDENT WORKS: 7 AGGREGATION WITH INDEPENDENT WORKS. * 8. TRANSLATION: 8 TRANSLATION. * 9. TERMINATION: 9 TERMINATION. * 10. FUTURE REVISIONS OF THIS LICENSE: 10 FUTURE REVISIONS OF THIS LICENSE. * 11. RELICENSING: 11 RELICENSING. * ADDENDUM; How to use this License for your documents: ADDENDUM How to use this License for your documents. @end menu @node 0 PREAMBLE,1 APPLICABILITY AND DEFINITIONS,,GNU Free Documentation License @anchor{fdl-1 3 preamble}@anchor{9e} @subsection 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. @node 1 APPLICABILITY AND DEFINITIONS,2 VERBATIM COPYING,0 PREAMBLE,GNU Free Documentation License @anchor{fdl-1 3 applicability-and-definitions}@anchor{9f} @subsection 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. @node 2 VERBATIM COPYING,3 COPYING IN QUANTITY,1 APPLICABILITY AND DEFINITIONS,GNU Free Documentation License @anchor{fdl-1 3 verbatim-copying}@anchor{a0} @subsection 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. @node 3 COPYING IN QUANTITY,4 MODIFICATIONS,2 VERBATIM COPYING,GNU Free Documentation License @anchor{fdl-1 3 copying-in-quantity}@anchor{a1} @subsection 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. @node 4 MODIFICATIONS,5 COMBINING DOCUMENTS,3 COPYING IN QUANTITY,GNU Free Documentation License @anchor{fdl-1 3 modifications}@anchor{a2} @subsection 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: @itemize - @item 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. @item 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. @item C. State on the Title page the name of the publisher of the Modified Version, as the publisher. @item @enumerate 4 @item Preserve all the copyright notices of the Document. @end enumerate @item E. Add an appropriate copyright notice for your modifications adjacent to the other copyright notices. @item 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. @item G. Preserve in that license notice the full lists of Invariant Sections and required Cover Texts given in the Document’s license notice. @item @enumerate 8 @item Include an unaltered copy of this License. @end enumerate @item 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. @item 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. @item 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. @item 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. @item M. Delete any section Entitled “Endorsements”. Such a section may not be included in the Modified Version. @item N. Do not retitle any existing section to be Entitled “Endorsements” or to conflict in title with any Invariant Section. @item @enumerate 15 @item Preserve any Warranty Disclaimers. @end enumerate @end itemize 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. @node 5 COMBINING DOCUMENTS,6 COLLECTIONS OF DOCUMENTS,4 MODIFICATIONS,GNU Free Documentation License @anchor{fdl-1 3 combining-documents}@anchor{a3} @subsection 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”. @node 6 COLLECTIONS OF DOCUMENTS,7 AGGREGATION WITH INDEPENDENT WORKS,5 COMBINING DOCUMENTS,GNU Free Documentation License @anchor{fdl-1 3 collections-of-documents}@anchor{a4} @subsection 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. @node 7 AGGREGATION WITH INDEPENDENT WORKS,8 TRANSLATION,6 COLLECTIONS OF DOCUMENTS,GNU Free Documentation License @anchor{fdl-1 3 aggregation-with-independent-works}@anchor{a5} @subsection 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. @node 8 TRANSLATION,9 TERMINATION,7 AGGREGATION WITH INDEPENDENT WORKS,GNU Free Documentation License @anchor{fdl-1 3 translation}@anchor{a6} @subsection 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. @node 9 TERMINATION,10 FUTURE REVISIONS OF THIS LICENSE,8 TRANSLATION,GNU Free Documentation License @anchor{fdl-1 3 termination}@anchor{a7} @subsection 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. @node 10 FUTURE REVISIONS OF THIS LICENSE,11 RELICENSING,9 TERMINATION,GNU Free Documentation License @anchor{fdl-1 3 future-revisions-of-this-license}@anchor{a8} @subsection 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 @indicateurl{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. @node 11 RELICENSING,ADDENDUM How to use this License for your documents,10 FUTURE REVISIONS OF THIS LICENSE,GNU Free Documentation License @anchor{fdl-1 3 relicensing}@anchor{a9} @subsection 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. @node ADDENDUM How to use this License for your documents,,11 RELICENSING,GNU Free Documentation License @anchor{fdl-1 3 addendum-how-to-use-this-license-for-your-documents}@anchor{aa} @subsection 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: @example 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". @end example If you have Invariant Sections, Front-Cover Texts and Back-Cover Texts, replace the “with … Texts.” line with this: @example with the Invariant Sections being LIST THEIR TITLES, with the Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. @end example 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. @anchor{29}@w{ } @anchor{rest tsref-type-ErrorDetail}@w{ } @c %**end of body @bye