\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