aboutsummaryrefslogtreecommitdiff
path: root/doc/anastasis.texi
diff options
context:
space:
mode:
Diffstat (limited to 'doc/anastasis.texi')
-rw-r--r--doc/anastasis.texi6093
1 files changed, 6093 insertions, 0 deletions
diff --git a/doc/anastasis.texi b/doc/anastasis.texi
new file mode 100644
index 0000000..a5d8b11
--- /dev/null
+++ b/doc/anastasis.texi
@@ -0,0 +1,6093 @@
1\input texinfo @c -*-texinfo-*-
2@c %**start of header
3@setfilename anastasis.info
4@documentencoding UTF-8
5@ifinfo
6@*Generated by Sphinx 3.4.3.@*
7@end ifinfo
8@settitle Anastasis Manual
9@defindex ge
10@paragraphindent 0
11@exampleindent 4
12@finalout
13@dircategory CATEGORY
14@direntry
15* MENU ENTRY: (anastasis.info). DESCRIPTION
16@end direntry
17
18@definfoenclose strong,`,'
19@definfoenclose emph,`,'
20@c %**end of header
21
22@copying
23@quotation
24GNU Anastasis 0.0.0, Jul 30, 2021
25
26Anastasis SARL
27
28Copyright @copyright{} 2020-2021 Anastasis SARL (AGPLv3+ or GFDL 1.3+)
29@end quotation
30
31@end copying
32
33@titlepage
34@title Anastasis Manual
35@insertcopying
36@end titlepage
37@contents
38
39@c %** start of user preamble
40
41@c %** end of user preamble
42
43@ifnottex
44@node Top
45@top Anastasis Manual
46@insertcopying
47@end ifnottex
48
49@c %**start of body
50@anchor{index doc}@anchor{0}
51@c This file is part of GNU Anastasis.
52@c Copyright (C) 2020-2021 Anastasis SARL
53@c
54@c Anastasis is free software; you can redistribute it and/or modify it under the
55@c terms of the GNU Affero General Public License as published by the Free Software
56@c Foundation; either version 2.1, or (at your option) any later version.
57@c
58@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
59@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
60@c A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
61@c
62@c You should have received a copy of the GNU Affero General Public License along with
63@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
64@c
65@c @author Christian Grothoff
66
67GNU Anastasis is Free Software protocol and implementation that allows
68users to securely deposit @strong{core secrets} with an open set of escrow
69providers and to recover these secrets if their original copies are
70lost.
71
72Anastasis is intended for users that want to make backups of key
73material, such as OpenPGP encryption keys, hard disk encryption keys
74or master keys of electronic wallets. Anastasis is NOT intended to
75store large amounts of secret data, it is only designed to safeguard
76key material.
77
78Anastasis solves the issue of keeping key material both available
79to the authorized user(s), and confidential from anyone else.
80
81With Anastasis, the @strong{core secrets} are protected from the Anastasis
82escrow providers by encrypting each with a @strong{master key}. The
83@strong{master key} can be split and distributed across the escrow
84providers to ensure that no single escrow provider can recover the
85@strong{master key} on its own. Which subset(s) of Anastasis providers
86must be contacted to recover a @strong{master key} is freely configurable.
87
88With Anastasis, users can reliably recover their @strong{core secret},
89while Anastasis makes this difficult for everyone else. This is even
90true if the user is unable to reliably remember any secret with
91sufficiently high entropy: Anastasis does not simply reduce the
92problem to encrypting the @strong{core secret} using some other key
93material in possession of the user.
94
95@menu
96* Documentation Overview::
97
98@detailmenu
99 --- The Detailed Node Listing ---
100
101Documentation Overview
102
103* Introduction::
104* Installation::
105* Configuration::
106* Cryptography::
107* REST API::
108* Reducer API::
109* Authentication Methods::
110* DB Schema::
111* Design Documents::
112* Anastasis licensing information::
113* Man Pages::
114* Complete Index::
115* GNU Free Documentation License::
116
117Introduction
118
119* User Identifiers::
120* Adversary models::
121* The recovery document::
122
123Installation
124
125* Installing from source::
126* Installing Anastasis binary packages on Debian::
127* Installing Anastasis binary packages on Ubuntu::
128
129Installing from source
130
131* Installing GNUnet::
132* Installing the Taler Exchange::
133* Installing the Taler Merchant::
134* Installing Anastasis::
135* Installing GNUnet-gtk::
136* Installing Anastasis-gtk::
137
138Installing Anastasis binary packages on Debian
139
140* Installing the graphical front-end::
141* Installing the backend::
142
143Installing Anastasis binary packages on Ubuntu
144
145* Installing the graphical front-end: Installing the graphical front-end<2>.
146* Installing the backend: Installing the backend<2>.
147
148Configuration
149
150* Configuration format::
151* Using anastasis-config::
152
153Cryptography
154
155* Key derivations::
156* Key Usage::
157* Availability Considerations::
158
159Key derivations
160
161* Verification::
162* Encryption::
163
164Key Usage
165
166* Encryption: Encryption<2>.
167* Signatures::
168
169REST API
170
171* HTTP Request and Response::
172* Protocol Version Ranges::
173* Common encodings::
174
175Common encodings
176
177* Binary Data::
178* Hash codes::
179* Large numbers::
180* Timestamps::
181* Integers::
182* Objects::
183* Keys::
184* Signatures: Signatures<2>.
185* Amounts::
186* Time::
187* Cryptographic primitives::
188* Signatures: Signatures<3>.
189* Receiving Configuration::
190* Receiving Terms of Service::
191* Manage policy::
192* Managing truth::
193
194Reducer API
195
196* States::
197* Backup Reducer::
198* Recovery Reducer::
199* Reducer transitions::
200
201Reducer transitions
202
203* Initial state::
204* Common transitions::
205* Backup transitions::
206* Recovery transitions::
207
208Authentication Methods
209
210* SMS (sms): SMS sms.
211* Email verification (email): Email verification email.
212* Video identification (vid): Video identification vid.
213* Security question (qa): Security question qa.
214* Snail mail verification (post): Snail mail verification post.
215
216Design Documents
217
218* Design Doc 001; Anastasis User Experience: Design Doc 001 Anastasis User Experience.
219* Template::
220
221Design Doc 001: Anastasis User Experience
222
223* Summary::
224* Motivation::
225* Setup Steps::
226* Show Service Status After Setup::
227* Recovery Steps::
228
229Setup Steps
230
231* Entry point; Settings: Entry point Settings.
232* Providing Identification::
233* Add Authentication Methods::
234* Confirm/Change Service Providers::
235* Defining Recovery Options::
236* Pay for Setup::
237
238Recovery Steps
239
240* Entry point; Settings: Entry point Settings<2>.
241* Providing Identification: Providing Identification<2>.
242* Select Authentication Challenge::
243* Payment::
244* Enter Challenge Response::
245* Success::
246
247Template
248
249* Summary: Summary<2>.
250* Motivation: Motivation<2>.
251* Requirements::
252* Proposed Solution::
253* Alternatives::
254* Drawbacks::
255* Discussion / Q&A::
256
257Anastasis licensing information
258
259* Anastasis (git;//git.taler.net/anastasis): Anastasis git //git taler net/anastasis.
260* Anastasis-gtk (git;//git.taler.net/anastasis-gtk): Anastasis-gtk git //git taler net/anastasis-gtk.
261* Documentation::
262
263Anastasis (git://git.taler.net/anastasis)
264
265* Runtime dependencies::
266
267Anastasis-gtk (git://git.taler.net/anastasis-gtk)
268
269* Runtime dependencies: Runtime dependencies<2>.
270
271Man Pages
272
273* anastasis-config(1): anastasis-config 1.
274* anastasis-gtk(1): anastasis-gtk 1.
275* anastasis-httpd(1): anastasis-httpd 1.
276* anastasis-reducer(1): anastasis-reducer 1.
277* anastasis.conf(5): anastasis conf 5.
278
279anastasis-config(1)
280
281* Synopsis::
282* Description::
283* See Also::
284* Bugs::
285
286anastasis-gtk(1)
287
288* Synopsis: Synopsis<2>.
289* Description: Description<2>.
290* See Also: See Also<2>.
291* Bugs: Bugs<2>.
292
293anastasis-httpd(1)
294
295* Synopsis: Synopsis<3>.
296* Description: Description<3>.
297* Signals::
298* See also::
299* Bugs: Bugs<3>.
300
301anastasis-reducer(1)
302
303* Synopsis: Synopsis<4>.
304* Description: Description<4>.
305* See Also: See Also<3>.
306* Bugs: Bugs<4>.
307
308anastasis.conf(5)
309
310* Description: Description<5>.
311* SEE ALSO::
312* BUGS::
313
314Description
315
316* GLOBAL OPTIONS::
317* Authorization options::
318* Postgres database configuration::
319
320GNU Free Documentation License
321
322* 0. PREAMBLE: 0 PREAMBLE.
323* 1. APPLICABILITY AND DEFINITIONS: 1 APPLICABILITY AND DEFINITIONS.
324* 2. VERBATIM COPYING: 2 VERBATIM COPYING.
325* 3. COPYING IN QUANTITY: 3 COPYING IN QUANTITY.
326* 4. MODIFICATIONS: 4 MODIFICATIONS.
327* 5. COMBINING DOCUMENTS: 5 COMBINING DOCUMENTS.
328* 6. COLLECTIONS OF DOCUMENTS: 6 COLLECTIONS OF DOCUMENTS.
329* 7. AGGREGATION WITH INDEPENDENT WORKS: 7 AGGREGATION WITH INDEPENDENT WORKS.
330* 8. TRANSLATION: 8 TRANSLATION.
331* 9. TERMINATION: 9 TERMINATION.
332* 10. FUTURE REVISIONS OF THIS LICENSE: 10 FUTURE REVISIONS OF THIS LICENSE.
333* 11. RELICENSING: 11 RELICENSING.
334* ADDENDUM; How to use this License for your documents: ADDENDUM How to use this License for your documents.
335
336@end detailmenu
337@end menu
338
339@node Documentation Overview,,Top,Top
340@anchor{index anastasis-documentation}@anchor{1}@anchor{index documentation-overview}@anchor{2}
341@chapter Documentation Overview
342
343
344@c This file is part of Anastasis
345@c Copyright (C) 2019-2021 Anastasis SARL
346@c
347@c Anastasis is free software; you can redistribute it and/or modify it under the
348@c terms of the GNU Affero General Public License as published by the Free Software
349@c Foundation; either version 2.1, or (at your option) any later version.
350@c
351@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
352@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
353@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
354@c
355@c You should have received a copy of the GNU Affero General Public License along with
356@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
357@c
358@c @author Christian Grothoff
359@c @author Dominik Meister
360@c @author Dennis Neufeld
361
362@menu
363* Introduction::
364* Installation::
365* Configuration::
366* Cryptography::
367* REST API::
368* Reducer API::
369* Authentication Methods::
370* DB Schema::
371* Design Documents::
372* Anastasis licensing information::
373* Man Pages::
374* Complete Index::
375* GNU Free Documentation License::
376
377@end menu
378
379@node Introduction,Installation,,Documentation Overview
380@anchor{introduction doc}@anchor{3}@anchor{introduction introduction}@anchor{4}
381@section Introduction
382
383
384To understand how Anastasis works, you need to understand three key
385concepts: user identifiers, our adversary model and the role of the
386recovery document.
387
388@menu
389* User Identifiers::
390* Adversary models::
391* The recovery document::
392
393@end menu
394
395@node User Identifiers,Adversary models,,Introduction
396@anchor{introduction user-identifiers}@anchor{5}
397@subsection User Identifiers
398
399
400To uniquely identify users, an “unforgettable” @strong{identifier} is used. This
401identifier should be difficult to guess for anybody but the user. However, the
402@strong{identifier} is not expected to have sufficient entropy or secrecy to be
403cryptographically secure. Examples for such identifier would be a
404concatenation of the full name of the user and their social security or
405passport number(s). For Swiss citizens, the AHV number could also be used.
406
407@node Adversary models,The recovery document,User Identifiers,Introduction
408@anchor{introduction adversary-models}@anchor{6}
409@subsection Adversary models
410
411
412The adversary model of Anastasis has two types of adversaries: weak
413adversaries which do not know the user’s @strong{identifier}, and strong
414adversaries which somehow do know a user’s @strong{identifier}. For weak
415adversaries the system guarantees full confidentiality. For strong
416adversaries, breaking confidentiality additionally requires that Anastasis
417escrow providers must have colluded. The user is able to specify a set of
418@strong{policies} which determine which Anastasis escrow providers would need to
419collude to break confidentiality. These policies also set the bar for the user
420to recover their core secret.
421
422@node The recovery document,,Adversary models,Introduction
423@anchor{introduction the-recovery-document}@anchor{7}
424@subsection The recovery document
425
426
427A @strong{recovery document} includes all of the information a user needs to
428recover access to their core secret. It specifies a set of @strong{escrow
429methods}, which specify how the user should convince the Anastasis server
430that they are “real”. Escrow methods can for example include SMS-based
431verification, video identification or a security question. For each escrow
432method, the Anastasis server is provided with @strong{truth}, that is data the
433Anastasis operator may learn during the recovery process to authenticate the
434user. Examples for truth would be a phone number (for SMS), a picture of the
435user (for video identification), or the (hash of) a security answer. A strong
436adversary is assumed to be able to learn the truth, while weak adversaries
437must not. In addition to a set of escrow methods and associated Anastasis
438server operators, the @strong{recovery document} also specifies @strong{policies}, which
439describe the combination(s) of the escrow methods that suffice to obtain
440access to the core secret. For example, a @strong{policy} could say that the
441escrow methods (A and B) suffice, and a second policy may permit (A and C). A
442different user may choose to use the policy that (A and B and C) are all
443required. Anastasis imposes no limit on the number of policies in a
444@strong{recovery document}, or the set of providers or escrow methods involved in
445guarding a user’s secret. Weak adversaries must not be able to deduce
446information about a user’s @strong{recovery document} (except for its length, which
447may be exposed to an adversary which monitors the user’s network traffic).
448
449@c This file is part of Anastasis
450@c Copyright (C) 2019-2021 Anastasis SARL
451@c
452@c Anastasis is free software; you can redistribute it and/or modify it under the
453@c terms of the GNU Affero General Public License as published by the Free Software
454@c Foundation; either version 2.1, or (at your option) any later version.
455@c
456@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
457@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
458@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
459@c
460@c You should have received a copy of the GNU Affero General Public License along with
461@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
462@c
463@c @author Christian Grothoff
464@c @author Dominik Meister
465@c @author Dennis Neufeld
466
467@node Installation,Configuration,Introduction,Documentation Overview
468@anchor{installation doc}@anchor{8}@anchor{installation installation}@anchor{9}
469@section Installation
470
471
472Please install the following packages before proceeding with the
473exchange compilation.
474
475
476@itemize -
477
478@item
479libsqlite3 >= 3.16.2
480
481@item
482GNU libunistring >= 0.9.3
483
484@item
485libcurl >= 7.26 (or libgnurl >= 7.26)
486
487@item
488libqrencode >= 4.0.0
489
490@item
491GNU libgcrypt >= 1.6
492
493@item
494libsodium >= 1.0
495
496@item
497libargon2 >= 20171227
498
499@item
500libjansson >= 2.7
501
502@item
503Postgres >= 9.6, including libpq
504
505@item
506GNU libmicrohttpd >= 0.9.71
507
508@item
509GNUnet >= 0.14.0 (from source tarball@footnote{http://ftpmirror.gnu.org/gnunet/})
510
511@item
512GNU Taler exchange
513
514@item
515GNU Taler merchant backend
516@end itemize
517
518Except for the last two, these are available in most GNU/Linux distributions
519and should just be installed using the respective package manager.
520
521@menu
522* Installing from source::
523* Installing Anastasis binary packages on Debian::
524* Installing Anastasis binary packages on Ubuntu::
525
526@end menu
527
528@node Installing from source,Installing Anastasis binary packages on Debian,,Installation
529@anchor{installation installing-from-source}@anchor{a}
530@subsection Installing from source
531
532
533The following instructions will show how to install libgnunetutil and
534the GNU Taler exchange from source.
535
536@menu
537* Installing GNUnet::
538* Installing the Taler Exchange::
539* Installing the Taler Merchant::
540* Installing Anastasis::
541* Installing GNUnet-gtk::
542* Installing Anastasis-gtk::
543
544@end menu
545
546@node Installing GNUnet,Installing the Taler Exchange,,Installing from source
547@anchor{installation installing-gnunet}@anchor{b}
548@subsubsection Installing GNUnet
549
550
551Before you install GNUnet, you must download and install the dependencies
552mentioned in the previous section, otherwise the build may succeed, but could
553fail to export some of the tooling required by GNU Taler.
554
555To install GNUnet, unpack the tarball and change
556into the resulting directory, then proceed as follows:
557
558@example
559$ ./configure [--prefix=GNUNETPFX]
560$ # Each dependency can be fetched from non standard locations via
561$ # the '--with-<LIBNAME>' option. See './configure --help'.
562$ make
563# make install
564# ldconfig
565@end example
566
567If you did not specify a prefix, GNUnet will install to @code{/usr/local},
568which requires you to run the last step as @code{root}.
569The @code{ldconfig} command (also run as @code{root}) makes the
570shared object libraries (@code{.so} files)
571visible to the various installed programs.
572
573@node Installing the Taler Exchange,Installing the Taler Merchant,Installing GNUnet,Installing from source
574@anchor{installation installing-the-taler-exchange}@anchor{c}
575@subsubsection Installing the Taler Exchange
576
577
578After installing GNUnet, unpack the GNU Taler exchange tarball,
579change into the resulting directory, and proceed as follows:
580
581@example
582$ ./configure [--prefix=EXCHANGEPFX] \
583 [--with-gnunet=GNUNETPFX]
584$ # Each dependency can be fetched from non standard locations via
585$ # the '--with-<LIBNAME>' option. See './configure --help'.
586$ make
587# make install
588@end example
589
590If you did not specify a prefix, the exchange will install to @code{/usr/local},
591which requires you to run the last step as @code{root}. You have to specify
592@code{--with-gnunet=/usr/local} if you installed GNUnet to @code{/usr/local} in the
593previous step.
594
595@node Installing the Taler Merchant,Installing Anastasis,Installing the Taler Exchange,Installing from source
596@anchor{installation installing-the-taler-merchant}@anchor{d}
597@subsubsection Installing the Taler Merchant
598
599
600GNU Taler merchant has these additional dependencies:
601
602
603@itemize -
604
605@item
606libqrencode >= 4.0.0
607@end itemize
608
609The following steps assume all dependencies are installed.
610
611First, unpack the GNU Taler merchant tarball and change into
612the resulting directory.
613Then, use the following commands to build and install the merchant backend:
614
615@example
616$ ./configure [--prefix=PFX] \
617 [--with-gnunet=GNUNETPFX] \
618 [--with-exchange=EXCHANGEPFX]
619$ # Each dependency can be fetched from non standard locations via
620$ # the '--with-<LIBNAME>' option. See './configure --help'.
621$ make
622# make install
623@end example
624
625If you did not specify a prefix, the exchange will install to
626@code{/usr/local}, which requires you to run the last step as @code{root}.
627
628You have to specify @code{--with-exchange=/usr/local} and/or
629@code{--with-gnunet=/usr/local} if you installed the exchange and/or
630GNUnet to @code{/usr/local} in the previous steps.
631
632Depending on the prefixes you specified for the installation and the
633distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding
634lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/}
635(replace the prefixes with the actual paths you used). Afterwards, you should
636run @code{ldconfig}. Without this step, it is possible that the linker may not
637find the installed libraries and launching the Taler merchant backend would
638then fail.
639
640@node Installing Anastasis,Installing GNUnet-gtk,Installing the Taler Merchant,Installing from source
641@anchor{installation installing-anastasis}@anchor{e}
642@subsubsection Installing Anastasis
643
644
645The following steps assume all dependencies are installed.
646
647First, unpack the Anastasis tarball and change into
648the resulting directory.
649Then, use the following commands to build and install Anastasis:
650
651@example
652$ ./configure [--prefix=PFX] \
653 [--with-gnunet=GNUNETPFX] \
654 [--with-exchange=EXCHANGEPFX]
655$ # Each dependency can be fetched from non standard locations via
656$ # the '--with-<LIBNAME>' option. See './configure --help'.
657$ make
658# make install
659@end example
660
661If you did not specify a prefix, Anastasis will be installed to
662@code{/usr/local}, which requires you to run the last step as @code{root}.
663
664You have to specify @code{--with-exchange=/usr/local} and/or
665@code{--with-gnunet=/usr/local} if you installed the exchange and/or
666GNUnet to @code{/usr/local} in the previous steps.
667
668Depending on the prefixes you specified for the installation and the
669distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding
670lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/}
671(replace the prefixes with the actual paths you used). Afterwards, you should
672run @code{ldconfig}. Without this step, it is possible that the linker may not
673find the installed libraries and launching the Anastasis backend would
674then fail.
675
676@node Installing GNUnet-gtk,Installing Anastasis-gtk,Installing Anastasis,Installing from source
677@anchor{installation installing-gnunet-gtk}@anchor{f}
678@subsubsection Installing GNUnet-gtk
679
680
681The following steps assume at least the GNUnet and Gtk+ dependencies are installed.
682
683First, unpack the gnunet-gtk tarball and change into the resulting directory.
684Then, use the following commands to build and install gnunet-gtk:
685
686@example
687$ ./configure [--prefix=$PFX] \
688 [--with-gnunet=$GNUNETPFX]
689$ # Each dependency can be fetched from non standard locations via
690$ # the '--with-<LIBNAME>' option. See './configure --help'.
691$ make
692# make install
693@end example
694
695It is highly recommended to use the same prefix ($PFX) for gnunet-gtk that was
696used for GNUnet ($GNUNETPFX). If you did not specify a prefix, gnunet-gtk
697will be installed to @code{/usr/local}, which requires you to run the last step
698as @code{root}.
699
700You have to specify @code{--with-gnunet=/usr/local} if you installed
701GNUnet to @code{/usr/local} in the previous steps.
702
703Depending on the prefixes you specified for the installation and the
704distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding
705lines for @code{$GNUNETPFX/lib/} and @code{$PFX/lib/} (replace the prefixes with the
706actual paths you used). Afterwards, you should run @code{ldconfig}. Without this
707step, it is possible that the linker may not find the installed libraries and
708launching gnunet-gtk would then fail.
709
710@node Installing Anastasis-gtk,,Installing GNUnet-gtk,Installing from source
711@anchor{installation installing-anastasis-gtk}@anchor{10}
712@subsubsection Installing Anastasis-gtk
713
714
715The following steps assume at least the GNUnet, gnunet-gtk and Anastasis
716dependencies are installed.
717
718First, unpack the anastasis-gtk tarball and change into the resulting
719directory. Then, use the following commands to build and install
720anastasis-gtk:
721
722@example
723$ ./configure [--prefix=PFX] \
724 [--with-gnunet=GNUNETPFX] \
725 [--with-exchange=EXCHANGEPFX] \
726 [--with-anastasis=ANASTASISPFX]
727$ # Each dependency can be fetched from non standard locations via
728$ # the '--with-<LIBNAME>' option. See './configure --help'.
729$ make
730# make install
731@end example
732
733If you did not specify a prefix, anastasis-gtk will be installed to
734@code{/usr/local}, which requires you to run the last step as @code{root}.
735
736You have to specify @code{-with-anastasis=/usr/local}, @code{--with-exchange=/usr/local} and/or
737@code{--with-gnunet=/usr/local} if you installed the exchange and/or
738GNUnet to @code{/usr/local} in the previous steps.
739
740Depending on the prefixes you specified for the installation and the
741distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding
742lines for @code{GNUNETPFX/lib/} and @code{EXCHANGEPFX/lib/} and @code{PFX/lib/}
743(replace the prefixes with the actual paths you used). Afterwards, you should
744run @code{ldconfig}. Without this step, it is possible that the linker may not
745find the installed libraries and launching anastasis-gtk would then fail.
746
747@node Installing Anastasis binary packages on Debian,Installing Anastasis binary packages on Ubuntu,Installing from source,Installation
748@anchor{installation installing-anastasis-binary-packages-on-debian}@anchor{11}
749@subsection Installing Anastasis binary packages on Debian
750
751
752To install the GNU Taler Debian packages, first ensure that you have
753the right Debian distribution. At this time, the packages are built for
754Sid, which means you should use a system which at least includes
755unstable packages in its source list. We recommend using APT pinning
756to limit unstable packages to those explicitly requested. To do this,
757set your @code{/etc/apt/preferences} as follows:
758
759@example
760Package: *
761Pin: release a=stable
762Pin-Priority: 700
763
764Package: *
765Pin: release a=testing
766Pin-Priority: 650
767
768Package: *
769Pin: release a=unstable
770Pin-Priority: 600
771
772Package: *
773Pin: release l=Debian-Security
774Pin-Priority: 1000
775@end example
776
777A typical @code{/etc/apt/sources.list} file for this setup
778which combines Debian stable with more recent packages
779from testing and unstable would look like this:
780
781@example
782deb http://ftp.ch.debian.org/debian/ buster main
783deb http://security.debian.org/debian-security buster/updates main
784deb http://ftp.ch.debian.org/debian/ testing main
785deb http://ftp.ch.debian.org/debian/ unstable main
786@end example
787
788Naturally, you may want to use different mirrors depending on your region.
789Additionally, you must add a file to import the GNU Taler packages. Typically,
790this is done by adding a file @code{/etc/apt/sources.list.d/taler.list} that
791looks like this:
792
793@example
794deb https://deb.taler.net/apt/debian sid main
795@end example
796
797Next, you must import the Taler Systems SA public package signing key
798into your keyring and update the package lists:
799
800@example
801# wget -O - https://taler.net/taler-systems.gpg.key | apt-key add -
802# apt update
803@end example
804
805@cartouche
806@quotation Note
807You may want to verify the correctness of the Taler Systems key out-of-band.
808@end quotation
809@end cartouche
810
811Now your system is ready to install the official GNU Taler binary packages
812using apt.
813
814@menu
815* Installing the graphical front-end::
816* Installing the backend::
817
818@end menu
819
820@node Installing the graphical front-end,Installing the backend,,Installing Anastasis binary packages on Debian
821@anchor{installation installing-the-graphical-front-end}@anchor{12}
822@subsubsection Installing the graphical front-end
823
824
825To install the Anastasis Gtk+ frontend, you can simply run:
826
827@example
828# apt install anastasis-gtk
829@end example
830
831To use @code{anastasis-gtk}, you can simply run:
832
833@example
834$ anastasis-gtk
835@end example
836
837@node Installing the backend,,Installing the graphical front-end,Installing Anastasis binary packages on Debian
838@anchor{installation installing-the-backend}@anchor{13}
839@subsubsection Installing the backend
840
841
842If you want to install the Anastasis backend-end (which normal users do not
843need), you should run:
844
845@example
846# apt install -t sid anastasis-httpd
847@end example
848
849Note that the latter package does not perform all of the configuration work.
850It does setup the user users and the systemd service scripts, but you still
851must configure the database backup, HTTP reverse proxy (typically with TLS
852certificates), Taler merchant backend for payments, authentication services,
853prices and the terms of service.
854
855Sample configuration files for the HTTP reverse proxy can be found in
856@code{/etc/anastasis.conf}.
857
858Note that the package does not complete the integration of the backend
859with the HTTP reverse proxy (typically with TLS certificates). A
860configuration fragment for Nginx or Apache will be placed in
861@code{/etc/@{apache,nginx@}/conf-available/anastasis.conf}.
862
863To operate an Anastasis backend with payments, you additionally
864need to install a Taler merchant backend via:
865
866@example
867# apt install -t sid taler-merchant-httpd
868@end example
869
870@node Installing Anastasis binary packages on Ubuntu,,Installing Anastasis binary packages on Debian,Installation
871@anchor{installation installing-anastasis-binary-packages-on-ubuntu}@anchor{14}
872@subsection Installing Anastasis binary packages on Ubuntu
873
874
875To install the GNU Taler Ubuntu packages, first ensure that you have
876the right Ubuntu distribution. At this time, the packages are built for
877Ubuntu 20.04 LTS (Focal Fossa).
878
879A typical @code{/etc/apt/sources.list.d/taler.list} file for this setup
880would look like this:
881
882@example
883deb https://deb.taler.net/apt/ubuntu/ focal-fossa main
884@end example
885
886The last line is crucial, as it adds the GNU Taler packages.
887
888Next, you must import the Taler Systems SA public package signing key
889into your keyring and update the package lists:
890
891@example
892# wget -O - https://taler.net/taler-systems.gpg.key | apt-key add -
893# apt update
894@end example
895
896@cartouche
897@quotation Note
898You may want to verify the correctness of the Taler Systems key out-of-band.
899@end quotation
900@end cartouche
901
902Now your system is ready to install the official GNU Taler binary packages
903using apt.
904
905@menu
906* Installing the graphical front-end: Installing the graphical front-end<2>.
907* Installing the backend: Installing the backend<2>.
908
909@end menu
910
911@node Installing the graphical front-end<2>,Installing the backend<2>,,Installing Anastasis binary packages on Ubuntu
912@anchor{installation id1}@anchor{15}
913@subsubsection Installing the graphical front-end
914
915
916To install the Anastasis front-end, you can now simply run:
917
918@example
919# apt install -t focal-fossa anastasis-gtk
920@end example
921
922To use @code{anastasis-gtk}, you can simply run:
923
924@example
925$ anastasis-gtk
926@end example
927
928@node Installing the backend<2>,,Installing the graphical front-end<2>,Installing Anastasis binary packages on Ubuntu
929@anchor{installation id2}@anchor{16}
930@subsubsection Installing the backend
931
932
933If you want to install the Anastasis backend-end (which normal users do not
934need), you should run:
935
936@example
937# apt install -t focal-fossa anastasis-httpd
938@end example
939
940Note that the latter package does not perform all of the configuration work.
941It does setup the user users and the systemd service scripts, but you still
942must configure the database backup, HTTP reverse proxy (typically with TLS
943certificates), Taler merchant backend for payments, authentication services,
944prices and the terms of service.
945
946Sample configuration files for the HTTP reverse proxy can be found in
947@code{/etc/anastasis.conf}.
948
949To operate an Anastasis backend with payments, you additionally
950need to install a Taler merchant backend via:
951
952@example
953# apt install -t sid taler-merchant-httpd
954@end example
955
956@c This file is part of Anastasis
957@c Copyright (C) 2019-2021 Anastasis SARL
958@c
959@c Anastasis is free software; you can redistribute it and/or modify it under the
960@c terms of the GNU Affero General Public License as published by the Free Software
961@c Foundation; either version 2.1, or (at your option) any later version.
962@c
963@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
964@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
965@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
966@c
967@c You should have received a copy of the GNU Affero General Public License along with
968@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
969@c
970@c @author Christian Grothoff
971@c @author Dominik Meister
972@c @author Dennis Neufeld
973
974@node Configuration,Cryptography,Installation,Documentation Overview
975@anchor{configuration doc}@anchor{17}@anchor{configuration configuration}@anchor{18}
976@section Configuration
977
978
979Details about the contents of the configuration file are describe in
980the @code{anastasis.conf(5)} chapter. This chapter only describes the
981configuration format.
982
983@menu
984* Configuration format::
985* Using anastasis-config::
986
987@end menu
988
989@node Configuration format,Using anastasis-config,,Configuration
990@anchor{configuration configuration-format}@anchor{19}
991@subsection Configuration format
992
993
994In Taler realm, any component obeys to the same pattern to get
995configuration values. According to this pattern, once the component has
996been installed, the installation deploys default values in
997$@{prefix@}/share/taler/config.d/, in .conf files. In order to override
998these defaults, the user can write a custom .conf file and either pass
999it to the component at execution time, or name it taler.conf and place
1000it under $HOME/.config/.
1001
1002A config file is a text file containing sections, and each section
1003contains its values. The right format follows:
1004
1005@example
1006[section1]
1007value1 = string
1008value2 = 23
1009
1010[section2]
1011value21 = string
1012value22 = /path22
1013@end example
1014
1015Throughout any configuration file, it is possible to use @code{$}-prefixed
1016variables, like @code{$VAR}, especially when they represent filesystem
1017paths. It is also possible to provide defaults values for those
1018variables that are unset, by using the following syntax:
1019@code{$@{VAR:-default@}}. However, there are two ways a user can set
1020@code{$}-prefixable variables:
1021
1022by defining them under a @code{[paths]} section, see example below,
1023
1024@example
1025[paths]
1026TALER_DEPLOYMENT_SHARED = $@{HOME@}/shared-data
1027..
1028[section-x]
1029path-x = $@{TALER_DEPLOYMENT_SHARED@}/x
1030@end example
1031
1032or by setting them in the environment:
1033
1034@example
1035$ export VAR=/x
1036@end example
1037
1038The configuration loader will give precedence to variables set under
1039@code{[path]}, though.
1040
1041The utility @code{taler-config}, which gets installed along with the
1042exchange, serves to get and set configuration values without directly
1043editing the .conf. The option @code{-f} is particularly useful to resolve
1044pathnames, when they use several levels of @code{$}-expanded variables. See
1045@code{taler-config --help}.
1046
1047Note that, in this stage of development, the file
1048@code{$HOME/.config/taler.conf} can contain sections for @emph{all} the
1049component. For example, both an exchange and a bank can read values from
1050it.
1051
1052The repository @code{git://taler.net/deployment} contains examples of
1053configuration file used in our demos. See under @code{deployment/config}.
1054
1055@quotation
1056
1057@strong{Note}
1058
1059Expectably, some components will not work just by using default
1060values, as their work is often interdependent. For example, a
1061merchant needs to know an exchange URL, or a database name.
1062@end quotation
1063
1064@node Using anastasis-config,,Configuration format,Configuration
1065@anchor{configuration using-anastasis-config}@anchor{1a}
1066@subsection Using anastasis-config
1067
1068
1069The tool @code{anastasis-config} can be used to extract or manipulate
1070configuration values; however, the configuration use the well-known INI
1071file format and can also be edited by hand.
1072
1073Run
1074
1075@example
1076$ anastasis-config -s $SECTION
1077@end example
1078
1079to list all of the configuration values in section @code{$SECTION}.
1080
1081Run
1082
1083@example
1084$ anastasis-config -s $section -o $option
1085@end example
1086
1087to extract the respective configuration value for option @code{$option} in
1088section @code{$section}.
1089
1090Finally, to change a setting, run
1091
1092@example
1093$ anastasis-config -s $section -o $option -V $value
1094@end example
1095
1096to set the respective configuration value to @code{$value}. Note that you
1097have to manually restart the Taler backend after you change the
1098configuration to make the new configuration go into effect.
1099
1100Some default options will use $-variables, such as @code{$DATADIR} within
1101their value. To expand the @code{$DATADIR} or other $-variables in the
1102configuration, pass the @code{-f} option to @code{anastasis-config}. For example,
1103compare:
1104
1105@example
1106$ anastasis-config -s ACCOUNT-bank \
1107 -o WIRE_RESPONSE
1108$ anastasis-config -f -s ACCOUNT-bank \
1109 -o WIRE_RESPONSE
1110@end example
1111
1112While the configuration file is typically located at
1113@code{$HOME/.config/taler.conf}, an alternative location can be specified
1114to @code{taler-merchant-httpd} and @code{anastasis-config} using the @code{-c}
1115option.
1116
1117@c This file is part of Anastasis
1118@c Copyright (C) 2019-2021 Anastasis SARL
1119@c
1120@c Anastasis is free software; you can redistribute it and/or modify it under the
1121@c terms of the GNU Affero General Public License as published by the Free Software
1122@c Foundation; either version 2.1, or (at your option) any later version.
1123@c
1124@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
1125@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1126@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
1127@c
1128@c You should have received a copy of the GNU Affero General Public License along with
1129@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
1130@c
1131@c @author Christian Grothoff
1132@c @author Dominik Meister
1133@c @author Dennis Neufeld
1134
1135@node Cryptography,REST API,Configuration,Documentation Overview
1136@anchor{cryptography doc}@anchor{1b}@anchor{cryptography cryptography}@anchor{1c}
1137@section Cryptography
1138
1139
1140When a user needs to interact with Anastasis, the system first derives some key
1141material, but not the master secret, from the user’s @strong{identifier} using
1142different HKDFs. These HKDFs are salted using the respective escrow
1143provider’s @strong{server salt}, which ensures that the accounts for the same user
1144cannot be easily correlated across the various Anastasis servers.
1145
1146Each Anastasis server uses an EdDSA @strong{account key} to identify the account of
1147the user. The account private key is derived from the user’s @strong{identifier} using
1148a computationally expensive cryptographic hash function. Using an
1149expensive hash algorithm is assumed to make it infeasible for a weak adversary to
1150determine account keys by brute force (without knowing the user’s identifier).
1151However, it is assumed that a strong adversary performing a targeted attack can
1152compute the account key pair.
1153
1154The public account key is Crockford base32-encoded in the URI to identify the
1155account, and used to sign requests. These signatures are also provided in
1156base32-encoding and transmitted using the HTTP header
1157@code{Anastasis-Account-Signature}.
1158
1159When confidential data is uploaded to an Anastasis server, the respective
1160payload is encrypted using AES-GCM with a symmetric key and initialization
1161vector derived from the @strong{identifier} and a high-entropy @strong{nonce}. The
1162nonce and the GCM tag are prepended to the ciphertext before being uploaded to
1163the Anastasis server. This is done whenever confidential data is stored with
1164the server.
1165
1166The @strong{core secret} of the user is (AES) encrypted using a symmetric @strong{master
1167key}. Recovering this master key requires the user to satisfy a particular
1168@strong{policy}. Policies specify a set of @strong{escrow methods}, each of which leads
1169the user to a @strong{key share}. Combining those key shares (by hashing) allows
1170the user to obtain a @strong{policy key}, which can be used to decrypt the @strong{master
1171key}. There can be many policies, satisfying any of these will allow the
1172user to recover the master key. A @strong{recovery document} contains the
1173encrypted @strong{core secret}, a set of escrow methods and a set of policies.
1174
1175@menu
1176* Key derivations::
1177* Key Usage::
1178* Availability Considerations::
1179
1180@end menu
1181
1182@node Key derivations,Key Usage,,Cryptography
1183@anchor{cryptography key-derivations}@anchor{1d}
1184@subsection Key derivations
1185
1186
1187EdDSA and ECDHE public keys are always points on Curve25519 and represented
1188using the standard 256 bit Ed25519 compact format. The binary representation
1189is converted to Crockford Base32 when transmitted inside JSON or as part of
1190URLs.
1191
1192To start, a user provides their private, unique and unforgettable
1193@strong{identifier} as a seed to identify their account. For example, this could
1194be a social security number together with their full name. Specifics may
1195depend on the cultural context, in this document we will simply refer to this
1196information as the @strong{identifier}.
1197
1198This identifier will be first hashed with Argon2, to provide a @strong{kdf_id}
1199which will be used to derive other keys later. The Hash must also include the
1200respective @strong{server_salt}. This also ensures that the @strong{kdf_id} is different
1201on each server. The use of Argon2 and the respective @strong{server_salt} is intended
1202to make it difficult to brute-force @strong{kdf_id} values and help protect the user’s
1203privacy. Also this ensures that the @strong{kdf_id}s on every server differs. However,
1204we do not assume that the @strong{identifier} or the @strong{kdf_id} cannot be
1205determined by an adversary performing a targeted attack, as a user’s
1206@strong{identifier} is likely to always be known to state actors and may
1207likely also be available to other actors.
1208
1209@example
1210kdf_id := Argon2( identifier, server_salt, keysize )
1211@end example
1212
1213@strong{identifier}: The secret defined from the user beforehand.
1214
1215@strong{server_salt}: The salt from the Server.
1216
1217@strong{keysize}: The desired output size of the KDF, here 32 bytes.
1218
1219@menu
1220* Verification::
1221* Encryption::
1222
1223@end menu
1224
1225@node Verification,Encryption,,Key derivations
1226@anchor{cryptography verification}@anchor{1e}
1227@subsubsection Verification
1228
1229
1230For users to authorize “policy” operations we need an EdDSA key pair. As we
1231cannot assure that the corresponding private key is truly secret, such policy
1232operations must never be destructive: Should an adversary learn the private
1233key, they could access (and with the @strong{kdf_id}, decrypt) the user’s policy (but
1234not the core secret), or upload a new version of the
1235@strong{encrypted recovery document} (but not delete an existing version).
1236
1237For the generation of the private key we use the @strong{kdf_id} as the entropy source,
1238hash it to derive a base secret which will then be processed to fit the
1239requirements for EdDSA private keys. From the private key we can then
1240generate the corresponding public key. Here, “ver” is used as a salt for the
1241HKDF to ensure that the result differs from other cases where we hash
1242@strong{kdf_id}.
1243
1244@example
1245ver_secret := HKDF(kdf_id, "ver", keysize)
1246eddsa_priv := eddsa_d_to_a(ver_secret)
1247eddsa_pub := get_EdDSA_Pub(eddsa_priv)
1248@end example
1249
1250@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.
1251
1252@strong{kdf_id}: Hashed identifier.
1253
1254@strong{key_size}: Size of the output, here 32 bytes.
1255
1256@strong{ver_secret}: Derived key from the @code{kdf_id}, serves as intermediate step for the generation of the private key.
1257
1258@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:
1259
1260@example
1261digest[0] = (digest[0] & 0x7f) | 0x40;
1262digest[31] &= 0xf8;
1263@end example
1264
1265@strong{eddsa_priv}: The generated EdDSA private key.
1266
1267@strong{eddsa_pub}: The generated EdDSA public key.
1268
1269@node Encryption,,Verification,Key derivations
1270@anchor{cryptography encryption}@anchor{1f}
1271@subsubsection Encryption
1272
1273
1274For symmetric encryption of data we use AES256-GCM. For this we need a
1275symmetric key and an initialization vector (IV). To ensure that the
1276symmetric key changes for each encryption operation, we compute the
1277key material using an HKDF over a @code{nonce} and the @code{kdf_id}.
1278
1279@example
1280(iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)
1281@end example
1282
1283@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.
1284
1285@strong{kdf_id}: Hashed identifier.
1286
1287@strong{keysize}: Size of the AES symmetric key, here 32 bytes.
1288
1289@strong{ivsize}: Size of the AES GCM IV, here 12 bytes.
1290
1291@strong{prekey}: Original key material.
1292
1293@strong{nonce}: 32-byte nonce, must never match “ver” (which it cannot as the length is different). Of course, we must
1294avoid key reuse. So, we have to use different nonces to get different keys and IVs (see below).
1295
1296@strong{key}: Symmetric key which is later used to encrypt the documents with AES256-GCM.
1297
1298@strong{iv}: IV which will be used for AES-GCM.
1299
1300@node Key Usage,Availability Considerations,Key derivations,Cryptography
1301@anchor{cryptography key-usage}@anchor{20}
1302@subsection Key Usage
1303
1304
1305The keys we have generated are then used to encrypt the @strong{recovery document} and
1306the @strong{key_share} of the user.
1307
1308@menu
1309* Encryption: Encryption<2>.
1310* Signatures::
1311
1312@end menu
1313
1314@node Encryption<2>,Signatures,,Key Usage
1315@anchor{cryptography id1}@anchor{21}
1316@subsubsection Encryption
1317
1318
1319Before every encryption a 32-byte nonce is generated.
1320From this the symmetric key is computed as described above.
1321We use AES256-GCM for the encryption of the @strong{recovery document} and
1322the @strong{key_share}. To ensure that the key derivation for the encryption
1323of the @strong{recovery document} differs fundamentally from that of an
1324individual @strong{key share}, we use different salts (“erd” and “eks”, respectively).
1325
1326@example
1327(iv0, key0) := HKDF(key_id, nonce0, "erd", keysize + ivsize)
1328(encrypted_recovery_document, aes_gcm_tag) := AES256_GCM(recovery_document, key0, iv0)
1329(iv_i, key_i) := HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize)
1330(encrypted_key_share_i, aes_gcm_tag_i) := AES256_GCM(key_share_i, key_i, iv_i)
1331@end example
1332
1333@strong{encrypted_recovery_document}: The encrypted @strong{recovery document} which contains the escrow methods, policies
1334and the encrypted @strong{core secret}.
1335
1336@strong{nonce0}: Nonce which is used to generate @emph{key0} and @emph{iv0} which are used for the encryption of the @emph{recovery document}.
1337Nonce must contain the string “ERD”.
1338
1339@strong{optional data}: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider.
1340
1341@strong{encrypted_key_share_i}: The encrypted @strong{key_share} which the escrow provider must release upon successful authentication.
1342Here, @strong{i} must be a positive number used to iterate over the various @strong{key shares} used for the various @strong{escrow methods}
1343at the various providers.
1344
1345@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
1346the same number as specified above for @emph{encrypted_key_share_i}. Nonce must contain the string “EKS” plus the according @emph{i}.
1347
1348As a special rule, when a @strong{security question} is used to authorize access to an
1349@strong{encrypted_key_share_i}, then the salt “eks” is replaced with an (expensive) hash
1350of the answer to the security question as an additional way to make the key share
1351inaccessible to those who do not have the answer:
1352
1353@example
1354powh := POW_HASH (qsalt, answer)
1355ekss := HKDF("Anastasis-secure-question-uuid-salting",
1356 powh,
1357 uuid);
1358(iv_i, key_i) := HKDF(key_id, nonce_i, ekss, [optional data], keysize + ivsize)
1359@end example
1360
1361@strong{qsalt}: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing.
1362
1363@strong{answer}: Answer to the security question, in UTF-8, as entered by the user.
1364
1365@strong{powh}: Result of the (expensive, proof-of-work) hash algorithm.
1366
1367@strong{uuid}: UUID of the challenge associated with the security question and the encrypted key share.
1368
1369@strong{ekss}: Replacement salt to be used instead of “eks” when deriving the key to encrypt/decrypt the key share.
1370
1371@node Signatures,,Encryption<2>,Key Usage
1372@anchor{cryptography signatures}@anchor{22}
1373@subsubsection Signatures
1374
1375
1376The EdDSA keys are used to sign the data sent from the client to the
1377server. Everything the client sends to server is signed. The following
1378algorithm is equivalent for @strong{Anastasis-Policy-Signature}.
1379
1380@example
1381(anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv)
1382ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)
1383@end example
1384
1385@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).
1386
1387@strong{h_body}: The hashed body.
1388
1389@strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed.
1390
1391When requesting policy downloads, the client must also provide a signature:
1392
1393@example
1394(anastasis-account-signature) := eddsa_sign(version, eddsa_priv)
1395ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)
1396@end example
1397
1398@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).
1399
1400@strong{version}: The version requested as a 64-bit integer, 2^64-1 for the “latest version”.
1401
1402@strong{ver_res}: A boolean value. True: Signature verification passed, False: Signature verification failed.
1403
1404@node Availability Considerations,,Key Usage,Cryptography
1405@anchor{cryptography availability-considerations}@anchor{23}
1406@subsection Availability Considerations
1407
1408
1409Anastasis considers two main threats against availability. First, the
1410Anastasis server operators must be protected against denial-of-service attacks
1411where an adversary attempts to exhaust the operator’s resources. The API protects
1412against these attacks by allowing operators to set fees for all
1413operations. Furthermore, all data stored comes with an expiration logic, so an
1414attacker cannot force servers to store data indefinitely.
1415
1416A second availability issue arises from strong adversaries that may be able to
1417compute the account keys of some user. While we assume that such an adversary
1418cannot successfully authenticate against the truth, the account key does
1419inherently enable these adversaries to upload a new policy for the account.
1420This cannot be prevented, as the legitimate user must be able to set or change
1421a policy using only the account key. To ensure that an adversary cannot
1422exploit this, policy uploads first of all never delete existing policies, but
1423merely create another version. This way, even if an adversary uploads a
1424malicious policy, a user can still retrieve an older version of the policy to
1425recover access to their data. This append-only storage for policies still
1426leaves a strong adversary with the option of uploading many policies to
1427exhaust the Anastasis server’s capacity. We limit this attack by requiring a
1428policy upload to include a reference to a @strong{payment identifier} from a payment
1429made by the user. Thus, a policy upload requires both knowledge of the
1430@strong{identity} and making a payment. This effectively prevents an adversary
1431from using the append-only policy storage from exhausting Anastasis server
1432capacity.
1433
1434@c This file is part of Anastasis
1435@c Copyright (C) 2019-2021 Anastasis SARL
1436@c
1437@c Anastasis is free software; you can redistribute it and/or modify it under the
1438@c terms of the GNU Affero General Public License as published by the Free Software
1439@c Foundation; either version 2.1, or (at your option) any later version.
1440@c
1441@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
1442@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1443@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
1444@c
1445@c You should have received a copy of the GNU Affero General Public License along with
1446@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
1447@c
1448@c @author Christian Grothoff
1449@c @author Dominik Meister
1450@c @author Dennis Neufeld
1451
1452@node REST API,Reducer API,Cryptography,Documentation Overview
1453@anchor{rest doc}@anchor{24}@anchor{rest rest-api}@anchor{25}
1454@section REST API
1455
1456
1457@c This file is part of Anastasis
1458@c
1459@c Copyright (C) 2014-2021 Anastasis SARL
1460@c
1461@c Anastasis is free software; you can redistribute it and/or modify it under the
1462@c terms of the GNU Affero Public License as published by the Free Software
1463@c Foundation; either version 2.1, or (at your option) any later version.
1464@c
1465@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
1466@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
1467@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
1468@c
1469@c You should have received a copy of the GNU Affero General Public License along with
1470@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
1471@c
1472@c @author Christian Grothoff
1473
1474@menu
1475* HTTP Request and Response::
1476* Protocol Version Ranges::
1477* Common encodings::
1478
1479@end menu
1480
1481@node HTTP Request and Response,Protocol Version Ranges,,REST API
1482@anchor{rest http-common}@anchor{26}@anchor{rest http-request-and-response}@anchor{27}
1483@subsection HTTP Request and Response
1484
1485
1486Certain response formats are common for all requests. They are documented here
1487instead of with each individual request. Furthermore, we note that clients may
1488theoretically fail to receive any response. In this case, the client should
1489verify that the Internet connection is working properly, and then proceed to
1490handle the error as if an internal error (500) had been returned.
1491
1492@anchor{rest any--*}@anchor{28}
1493@deffn {HTTP Any} ANY /*
1494
1495@strong{Request:}
1496
1497Unless specified otherwise, HTTP requests that carry a message body must
1498have the content type @code{application/json}.
1499
1500@*Request Headers:
1501
1502@itemize *
1503
1504@item
1505Content-Type@footnote{https://tools.ietf.org/html/rfc7231#section-3.1.1.5} – application/json
1506@end itemize
1507
1508
1509@strong{Response:}
1510
1511@*Response Headers:
1512
1513@itemize *
1514
1515@item
1516Content-Type@footnote{https://tools.ietf.org/html/rfc7231#section-3.1.1.5} – application/json
1517@end itemize
1518
1519
1520
1521@table @asis
1522
1523@item 200 Ok@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
1524
1525The request was successful.
1526
1527@item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
1528
1529One of the arguments to the request is missing or malformed.
1530
1531@item 500 Internal server error@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.1}:
1532
1533This always indicates some serious internal operational error of the Anastasis
1534provider, such as a program bug, database problems, etc., and must not be used for
1535client-side problems. When facing an internal server error, clients should
1536retry their request after some delay. We recommended initially trying after
15371s, twice more at randomized times within 1 minute, then the user should be
1538informed and another three retries should be scheduled within the next 24h.
1539If the error persists, a report should ultimately be made to the auditor,
1540although the auditor API for this is not yet specified. However, as internal
1541server errors are always reported to the exchange operator, a good operator
1542should naturally be able to address them in a timely fashion, especially
1543within 24h.
1544@end table
1545
1546Unless specified otherwise, all error status codes (4xx and 5xx) have a message
1547body with an @ref{29,,ErrorDetail} JSON object.
1548
1549@strong{Details:}
1550
1551@example
1552interface ErrorDetail @{
1553
1554 // Numeric error code unique to the condition, see `@w{`}gnu-taler-error-codes`@w{`} in GANA.
1555 // The other arguments are specific to the error value reported here.
1556 code: number;
1557
1558 // Human-readable description of the error, i.e. "missing parameter", "commitment violation", ...
1559 // Should give a human-readable hint about the error's nature. Optional, may change without notice!
1560 hint?: string;
1561
1562@}
1563@end example
1564@end deffn
1565
1566@node Protocol Version Ranges,Common encodings,HTTP Request and Response,REST API
1567@anchor{rest protocol-version-ranges}@anchor{2a}
1568@subsection Protocol Version Ranges
1569
1570
1571Anastasis services expose the range of API versions they support. Clients in
1572turn have an API version range they support. These version ranges are written
1573down in the libtool version format@footnote{https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html}.
1574
1575A protocol version is a positive, non-zero integer. A protocol version range consists of three components:
1576
1577
1578@enumerate
1579
1580@item
1581The @code{current} version. This is the latest version of the protocol supported by the client or service.
1582
1583@item
1584The @code{revision} number. This value should usually not be interpreted by the client/server, but serves
1585purely as a comment. Each time a service/client for a protocol is updated while supporting the same
1586set of protocol versions, the revision should be increased.
1587In rare cases, the revision number can be used to work around unintended breakage in deployed
1588versions of a service. This is discouraged and should only be used in exceptional situations.
1589
1590@item
1591The @code{age} number. This non-zero integer identifies with how many previous protocol versions this
1592implementation is compatible. An @code{age} of 0 implies that the implementation only supports
1593the @code{current} protocol version. The @code{age} must be less or equal than the @code{current} protocol version.
1594@end enumerate
1595
1596To avoid confusion with semantic versions, the protocol version range is written down in the following format:
1597
1598@example
1599current[:revision[:age]]
1600@end example
1601
1602The angle brackets mark optional components. If either @code{revision} or @code{age} are omitted, they default to 0.
1603
1604Examples:
1605
1606
1607@itemize *
1608
1609@item
1610“1” and “1” are compatible
1611
1612@item
1613“1” and “2” are @strong{incompatible}
1614
1615@item
1616“2:0:1” and “1:0:0” are compatible
1617
1618@item
1619“2:5:1” and “1:10:0” are compatible
1620
1621@item
1622“4:0:1” and “2:0:0” are @strong{incompatible}
1623
1624@item
1625“4:0:1” and “3:0:0” are compatible
1626@end itemize
1627
1628@cartouche
1629@quotation Note
1630Semantic versions@footnote{https://semver.org/} are not a good tool for this job, as we concisely want to express
1631that the client/server supports the last @code{n} versions of the protocol.
1632Semantic versions don’t support this, and semantic version ranges are too complex for this.
1633@end quotation
1634@end cartouche
1635
1636@cartouche
1637@quotation Warning
1638A client doesn’t have one single protocol version range. Instead, it has
1639a protocol version range for each type of service it talks to.
1640@end quotation
1641@end cartouche
1642
1643@cartouche
1644@quotation Warning
1645For privacy reasons, the protocol version range of a client should not be
1646sent to the service. Instead, the client should just use the two version ranges
1647to decide whether it will talk to the service.
1648@end quotation
1649@end cartouche
1650
1651@node Common encodings,,Protocol Version Ranges,REST API
1652@anchor{rest common-encodings}@anchor{2b}@anchor{rest encodings-ref}@anchor{2c}
1653@subsection Common encodings
1654
1655
1656This section describes how certain types of values are represented throughout the API.
1657
1658@menu
1659* Binary Data::
1660* Hash codes::
1661* Large numbers::
1662* Timestamps::
1663* Integers::
1664* Objects::
1665* Keys::
1666* Signatures: Signatures<2>.
1667* Amounts::
1668* Time::
1669* Cryptographic primitives::
1670* Signatures: Signatures<3>.
1671* Receiving Configuration::
1672* Receiving Terms of Service::
1673* Manage policy::
1674* Managing truth::
1675
1676@end menu
1677
1678@node Binary Data,Hash codes,,Common encodings
1679@anchor{rest base32}@anchor{2d}@anchor{rest binary-data}@anchor{2e}
1680@subsubsection Binary Data
1681
1682
1683@example
1684type Base32 = string;
1685@end example
1686
1687Binary data is generally encoded using Crockford’s variant of Base32
1688(@indicateurl{http://www.crockford.com/wrmg/base32.html}), except that “U” is not excluded
1689but also decodes to “V” to make OCR easy. We will still simply use the JSON
1690type “base32” and the term “Crockford Base32” in the text to refer to the
1691resulting encoding.
1692
1693@node Hash codes,Large numbers,Binary Data,Common encodings
1694@anchor{rest hash-codes}@anchor{2f}
1695@subsubsection Hash codes
1696
1697
1698Hash codes are strings representing base32 encoding of the respective
1699hashed data. See @ref{2d,,base32}.
1700
1701@example
1702// 64-byte hash code.
1703type HashCode = string;
1704@end example
1705
1706@example
1707// 32-byte hash code.
1708type ShortHashCode = string;
1709@end example
1710
1711@node Large numbers,Timestamps,Hash codes,Common encodings
1712@anchor{rest large-numbers}@anchor{30}
1713@subsubsection Large numbers
1714
1715
1716Large numbers such as 256 bit keys, are transmitted as other binary data in
1717Crockford Base32 encoding.
1718
1719@node Timestamps,Integers,Large numbers,Common encodings
1720@anchor{rest timestamps}@anchor{31}
1721@subsubsection Timestamps
1722
1723
1724Timestamps are represented by the following structure:
1725
1726@example
1727interface Timestamp @{
1728 // Milliseconds since epoch, or the special
1729 // value "never" to represent an event that will
1730 // never happen.
1731 t_ms: number | "never";
1732@}
1733@end example
1734
1735@example
1736interface Duration @{
1737 // Duration in milliseconds or "forever"
1738 // to represent an infinite duration.
1739 d_ms: number | "forever";
1740@}
1741@end example
1742
1743@node Integers,Objects,Timestamps,Common encodings
1744@anchor{rest integers}@anchor{32}@anchor{rest publickey}@anchor{33}
1745@subsubsection Integers
1746
1747
1748@example
1749// JavaScript numbers restricted to integers.
1750type Integer = number;
1751@end example
1752
1753@node Objects,Keys,Integers,Common encodings
1754@anchor{rest objects}@anchor{34}
1755@subsubsection Objects
1756
1757
1758@example
1759// JavaScript objects, no further restrictions.
1760type Object = object;
1761@end example
1762
1763@node Keys,Signatures<2>,Objects,Common encodings
1764@anchor{rest keys}@anchor{35}
1765@subsubsection Keys
1766
1767
1768@example
1769// EdDSA and ECDHE public keys always point on Curve25519
1770// and represented using the standard 256 bits Ed25519 compact format,
1771// converted to Crockford `Base32`.
1772type EddsaPublicKey = string;
1773@end example
1774
1775@example
1776// EdDSA and ECDHE public keys always point on Curve25519
1777// and represented using the standard 256 bits Ed25519 compact format,
1778// converted to Crockford `Base32`.
1779type EddsaPrivateKey = string;
1780@end example
1781
1782@node Signatures<2>,Amounts,Keys,Common encodings
1783@anchor{rest signature}@anchor{36}@anchor{rest signatures}@anchor{37}
1784@subsubsection Signatures
1785
1786
1787@example
1788// EdDSA signatures are transmitted as 64-bytes `base32`
1789// binary-encoded objects with just the R and S values (base32_ binary-only).
1790type EddsaSignature = string;
1791@end example
1792
1793@node Amounts,Time,Signatures<2>,Common encodings
1794@anchor{rest amount}@anchor{38}@anchor{rest amounts}@anchor{39}
1795@subsubsection Amounts
1796
1797
1798@example
1799type Amount = string;
1800@end example
1801
1802Amounts of currency are serialized as a string of the format
1803@code{<Currency>:<DecimalAmount>}. Taler treats monetary amounts as
1804fixed-precision numbers, with 8 decimal places. Unlike floating point numbers,
1805this allows accurate representation of monetary amounts.
1806
1807The following constrains apply for a valid amount:
1808
1809
1810@enumerate
1811
1812@item
1813The @code{<Currency>} part must be at most 11 characters long and may only consist
1814of ASCII letters (@code{a-zA-Z}).
1815
1816@item
1817The integer part of @code{<DecimalAmount>} may be at most 2^52.
1818
1819@item
1820The fractional part of @code{<DecimalAmount>} may contain at most 8 decimal digits.
1821@end enumerate
1822
1823@cartouche
1824@quotation Note
1825“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”.
1826@end quotation
1827@end cartouche
1828
1829An amount that is prefixed with a @code{+} or @code{-} character is also used in certain contexts.
1830When no sign is present, the amount is assumed to be positive.
1831
1832@node Time,Cryptographic primitives,Amounts,Common encodings
1833@anchor{rest time}@anchor{3a}
1834@subsubsection Time
1835
1836
1837In signed messages, time is represented using 64-bit big-endian values,
1838denoting microseconds since the UNIX Epoch. @code{UINT64_MAX} represents “never”.
1839
1840@example
1841struct GNUNET_TIME_Absolute @{
1842 uint64_t timestamp_us;
1843@};
1844struct GNUNET_TIME_AbsoluteNBO @{
1845 uint64_t abs_value_us__; // in network byte order
1846@};
1847@end example
1848
1849@node Cryptographic primitives,Signatures<3>,Time,Common encodings
1850@anchor{rest cryptographic-primitives}@anchor{3b}
1851@subsubsection Cryptographic primitives
1852
1853
1854All elliptic curve operations are on Curve25519. Public and private keys are
1855thus 32 bytes, and signatures 64 bytes. For hashing, including HKDFs, Taler
1856uses 512-bit hash codes (64 bytes).
1857
1858@example
1859struct GNUNET_HashCode @{
1860 uint8_t hash[64]; // usually SHA-512
1861@};
1862@end example
1863@anchor{rest taler-ecdhephemeralpublickeyp}@anchor{3c}
1864@example
1865struct TALER_EcdhEphemeralPublicKeyP @{
1866 uint8_t ecdh_pub[32];
1867@};
1868@end example
1869
1870@example
1871struct UUID @{
1872 uint32_t value[4];
1873@};
1874@end example
1875
1876@node Signatures<3>,Receiving Configuration,Cryptographic primitives,Common encodings
1877@anchor{rest id1}@anchor{3d}@anchor{rest id2}@anchor{3e}
1878@subsubsection Signatures
1879
1880
1881Any piece of signed data, complies to the abstract data structure given below.
1882
1883@example
1884struct Data @{
1885 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
1886 type1_t payload1;
1887 type2_t payload2;
1888 ...
1889@};
1890
1891/*From gnunet_crypto_lib.h*/
1892struct GNUNET_CRYPTO_EccSignaturePurpose @{
1893 /**
1894
1895 The following constraints apply for a valid amount:
1896
1897 * This field is used to express the context in
1898 * which the signature is made, ensuring that a
1899 * signature cannot be lifted from one part of the protocol
1900 * to another. See `src/include/taler_signatures.h` within the
1901 * exchange's codebase (git://taler.net/exchange).
1902 */
1903 uint32_t purpose;
1904 /**
1905 * This field equals the number of bytes being signed,
1906 * namely 'sizeof (struct Data)'.
1907 */
1908 uint32_t size;
1909@};
1910@end example
1911@anchor{rest salt}@anchor{3f}
1912@node Receiving Configuration,Receiving Terms of Service,Signatures<3>,Common encodings
1913@anchor{rest config}@anchor{40}@anchor{rest receiving-configuration}@anchor{41}
1914@subsubsection Receiving Configuration
1915
1916
1917@anchor{rest get--config}@anchor{42}
1918@deffn {HTTP Get} GET /config
1919
1920Obtain the configuration details of the escrow provider.
1921
1922@strong{Response:}
1923
1924Returns an @ref{43,,EscrowConfigurationResponse}.
1925@anchor{rest escrowconfigurationresponse}@anchor{43}
1926@example
1927interface EscrowConfigurationResponse @{
1928
1929 // Protocol identifier, clarifies that this is an Anastasis provider.
1930 name: "anastasis";
1931
1932 // libtool-style representation of the Exchange protocol version, see
1933 // https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
1934 // The format is "current:revision:age".
1935 version: string;
1936
1937 // Currency in which this provider processes payments.
1938 currency: string;
1939
1940 // Supported authorization methods.
1941 methods: AuthorizationMethodConfig[];
1942
1943 // Maximum policy upload size supported.
1944 storage_limit_in_megabytes: number;
1945
1946 // Payment required to maintain an account to store policy documents for a year.
1947 // Users can pay more, in which case the storage time will go up proportionally.
1948 annual_fee: Amount;
1949
1950 // Payment required to upload truth. To be paid per upload.
1951 truth_upload_fee: Amount;
1952
1953 // Limit on the liability that the provider is offering with
1954 // respect to the services provided.
1955 liability_limit: Amount;
1956
1957 // Salt value with 128 bits of entropy.
1958 // Different providers
1959 // will use different high-entropy salt values. The resulting
1960 // **provider salt** is then used in various operations to ensure
1961 // cryptographic operations differ by provider. A provider must
1962 // never change its salt value.
1963 server_salt: string;
1964
1965@}
1966@end example
1967@anchor{rest authorizationmethodconfig}@anchor{44}
1968@example
1969interface AuthorizationMethodConfig @{
1970 // Name of the authorization method.
1971 type: string;
1972
1973 // Fee for accessing key share using this method.
1974 cost: Amount;
1975
1976@}
1977@end example
1978@end deffn
1979
1980@node Receiving Terms of Service,Manage policy,Receiving Configuration,Common encodings
1981@anchor{rest receiving-terms-of-service}@anchor{45}@anchor{rest terms}@anchor{46}
1982@subsubsection Receiving Terms of Service
1983
1984
1985@anchor{rest get--terms}@anchor{47}
1986@deffn {HTTP Get} GET /terms
1987
1988Obtain the terms of service provided by the escrow provider.
1989
1990@strong{Response:}
1991
1992Returns the terms of service of the provider, in the best language
1993and format available based on the client’s request.
1994@end deffn
1995
1996@anchor{rest get--privacy}@anchor{48}
1997@deffn {HTTP Get} GET /privacy
1998
1999Obtain the privacy policy of the service provided by the escrow provider.
2000
2001@strong{Response:}
2002
2003Returns the privacy policy of the provider, in the best language
2004and format available based on the client’s request.
2005@end deffn
2006
2007@node Manage policy,Managing truth,Receiving Terms of Service,Common encodings
2008@anchor{rest id3}@anchor{49}@anchor{rest manage-policy}@anchor{4a}
2009@subsubsection Manage policy
2010
2011
2012This API is used by the Anastasis client to deposit or request encrypted
2013recovery documents with the escrow provider. Generally, a client will deposit
2014the same encrypted recovery document with each escrow provider, but provide
2015a different truth to each escrow provider.
2016
2017Operations by the client are identified and authorized by @code{$ACCOUNT_PUB}, which
2018should be kept secret from third parties. @code{$ACCOUNT_PUB} should be an account
2019public key using the Crockford base32-encoding.
2020
2021In the following, UUID is always defined and used according to RFC 4122@footnote{https://tools.ietf.org/html/rfc4122}.
2022
2023@anchor{rest get--policy-$ACCOUNT_PUB[?version=$NUMBER]}@anchor{4b}
2024@deffn {HTTP Get} GET /policy/$ACCOUNT_PUB[?version=$NUMBER]
2025
2026Get the customer’s encrypted recovery document. If @code{version}
2027is not specified, the server returns the latest available version. If
2028@code{version} is specified, returns the policy with the respective
2029@code{version}. The response must begin with the nonce and
2030an AES-GCM tag and continue with the ciphertext. Once decrypted, the
2031plaintext is expected to contain:
2032
2033
2034@itemize *
2035
2036@item
2037the escrow policy
2038
2039@item
2040the separately encrypted master public key
2041@end itemize
2042
2043Note that the key shares required to decrypt the master public key are
2044not included, as for this the client needs to obtain authorization.
2045The policy does provide sufficient information for the client to determine
2046how to authorize requests for @strong{truth}.
2047
2048The client MAY provide an @code{If-None-Match} header with an Etag.
2049In that case, the server MUST additionally respond with an @code{304} status
2050code in case the resource matches the provided Etag.
2051
2052@strong{Response}:
2053
2054
2055@table @asis
2056
2057@item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
2058
2059The escrow provider responds with an @ref{4c,,EncryptedRecoveryDocument} object.
2060
2061@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
2062
2063The client requested the same resource it already knows.
2064
2065@item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
2066
2067The @code{$ACCOUNT_PUB} is not an EdDSA public key.
2068
2069@item 402 Payment Required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
2070
2071The account’s balance is too low for the specified operation.
2072See the Taler payment protocol specification for how to pay.
2073
2074@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
2075
2076The required account signature was invalid.
2077
2078@item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
2079
2080The requested resource was not found.
2081@end table
2082
2083@emph{Anastasis-Version}: $NUMBER — The server must return actual version of the encrypted recovery document via this header.
2084If the client specified a version number in the header of the request, the server must return that version. If the client
2085did not specify a version in the request, the server returns latest version of the @ref{4c,,EncryptedRecoveryDocument}.
2086
2087@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}.
2088
2089@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.
2090The client SHOULD send this header with every request (except for the first request) to avoid unnecessary downloads.
2091
2092@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).
2093@end deffn
2094
2095@anchor{rest post--policy-$ACCOUNT_PUB}@anchor{4d}
2096@deffn {HTTP Post} POST /policy/$ACCOUNT_PUB
2097
2098Upload a new version of the customer’s encrypted recovery document.
2099While the document’s structure is described in JSON below, the upload
2100should just be the bytestream of the raw data (i.e. 32-byte nonce followed
2101by 16-byte tag followed by the encrypted document).
2102If the request has been seen before, the server should do nothing, and otherwise store the new version.
2103The body must begin with a nonce, an AES-GCM tag and continue with the ciphertext. The format
2104is the same as specified for the response of the GET method. The
2105Anastasis server cannot fully validate the format, but MAY impose
2106minimum and maximum size limits.
2107
2108@strong{Request}:
2109
2110@*Query Parameters:
2111
2112@itemize *
2113
2114@item
2115@code{storage_duration=YEARS} – For how many years from now would the client like us to
2116store the recovery document? Defaults to 0 (that is, do
2117not extend / prolong existing storage contract).
2118The server will respond with a @code{402 Payment required}, but only
2119if the rest of the request is well-formed (account
2120signature must match). Clients that do not actually
2121intend to make a new upload but that only want to pay
2122may attempt to upload the latest backup again, as this
2123option will be checked before the @code{304 Not modified}
2124case.
2125
2126@item
2127@code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will
2128wait up to @code{timeout_ms} milliseconds for completion of the payment before
2129sending the HTTP response. A client must never rely on this behavior, as the
2130backend may return a response immediately.
2131@end itemize
2132
2133
2134@emph{If-None-Match}: This header MUST be present and set to the SHA512 hash (Etag) of the body by the client.
2135The client SHOULD also set the @code{Expect: 100-Continue} header and wait for @code{100 continue}
2136before uploading the body. The server MUST
2137use the Etag to check whether it already knows the encrypted recovery document that is about to be uploaded.
2138The server MUST refuse the upload with a @code{304} status code if the Etag matches
2139the latest version already known to the server.
2140
2141@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.
2142
2143@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.
2144
2145@strong{Response}:
2146
2147
2148@table @asis
2149
2150@item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
2151
2152The encrypted recovery document was accepted and stored. @code{Anastasis-Version} and @code{Anastasis-UUID} headers
2153indicate what version and UUID was assigned to this encrypted recovery document upload by the server.
2154
2155@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
2156
2157The same encrypted recovery document was previously accepted and stored. @code{Anastasis-Version} header
2158indicates what version was previously assigned to this encrypted recovery document.
2159
2160@item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}:
2161
2162The @code{$ACCOUNT_PUB} is not an EdDSA public key or mandatory headers are missing.
2163The response body MUST elaborate on the error using a Taler error code in the typical JSON encoding.
2164
2165@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
2166
2167The account’s balance is too low for the specified operation.
2168See the Taler payment protocol specification for how to pay.
2169The response body MAY provide alternative means for payment.
2170
2171@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
2172
2173The required account signature was invalid. The response body may elaborate on the error.
2174
2175@item 413 Request entity too large@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.14}:
2176
2177The upload is too large @emph{or} too small. The response body may elaborate on the error.
2178@end table
2179
2180@strong{Details:}
2181@anchor{rest encryptedrecoverydocument}@anchor{4c}
2182@example
2183interface EncryptedRecoveryDocument @{
2184 // Nonce used to compute the (iv,key) pair for encryption of the
2185 // encrypted_compressed_recovery_document.
2186 nonce: [32]; //bytearray
2187
2188 // Authentication tag.
2189 aes_gcm_tag: [16]; //bytearray
2190
2191 // Variable-size encrypted recovery document. After decryption,
2192 // this contains a gzip compressed JSON-encoded `RecoveryDocument`.
2193 // The nonce of the HKDF for this encryption must include the
2194 // string "ERD".
2195 encrypted_compressed_recovery_document: []; //bytearray of undefined length
2196
2197@}
2198@end example
2199@anchor{rest recoverydocument}@anchor{4e}
2200@example
2201interface RecoveryDocument @{
2202 // Account identifier at backup provider, AES-encrypted with
2203 // the (symmetric) master_key, i.e. an URL
2204 // https://sync.taler.net/$BACKUP_ID and
2205 // a private key to decrypt the backup. Anastasis is oblivious
2206 // to the details of how this is ultimately encoded.
2207 backup_account: []; //bytearray of undefined length
2208
2209 // List of escrow providers and selected authentication method.
2210 methods: EscrowMethod[];
2211
2212 // List of possible decryption policies.
2213 policy: DecryptionPolicy[];
2214
2215@}
2216@end example
2217@anchor{rest escrowmethod}@anchor{4f}
2218@example
2219interface EscrowMethod @{
2220 // URL of the escrow provider (including possibly this Anastasis server).
2221 provider_url : string;
2222
2223 // Type of the escrow method (e.g. security question, SMS etc.).
2224 escrow_type: string;
2225
2226 // UUID of the escrow method (see /truth/ API below).
2227 uuid: string;
2228
2229 // Key used to encrypt the `Truth` this `EscrowMethod` is related to.
2230 // Client has to provide this key to the server when using `@w{`}/truth/`@w{`}.
2231 truth_encryption_key: [32]; //bytearray
2232
2233 // Salt used to encrypt the truth on the Anastasis server.
2234 truth_salt: [32]; //bytearray
2235
2236 // The challenge to give to the user (i.e. the security question
2237 // if this is challenge-response).
2238 // (Q: as string in base32 encoding?)
2239 // (Q: what is the mime-type of this value?)
2240 //
2241 // For some methods, this value may be absent.
2242 //
2243 // The plaintext challenge is not revealed to the
2244 // Anastasis server.
2245 challenge: []; //bytearray of undefined length
2246
2247@}
2248@end example
2249@anchor{rest decryptionpolicy}@anchor{50}
2250@example
2251interface DecryptionPolicy @{
2252 // Salt included to encrypt master key share when
2253 // using this decryption policy.
2254 policy_salt: [32]; //bytearray
2255
2256 // Master key, AES-encrypted with key derived from
2257 // salt and keyshares revealed by the following list of
2258 // escrow methods identified by UUID.
2259 encrypted_master_key: [32]; //bytearray
2260
2261 // List of escrow methods identified by their UUID.
2262 uuid: string[];
2263
2264@}
2265@end example
2266@end deffn
2267
2268@node Managing truth,,Manage policy,Common encodings
2269@anchor{rest managing-truth}@anchor{51}@anchor{rest truth}@anchor{52}
2270@subsubsection Managing truth
2271
2272
2273This API is used by the Anastasis client to deposit @strong{truth} or request a (encrypted) @strong{key share} with
2274the escrow provider.
2275
2276An @strong{escrow method} specifies an Anastasis provider and how the user should
2277authorize themself. The @strong{truth} API allows the user to provide the
2278(encrypted) key share to the respective escrow provider, as well as auxiliary
2279data required for such a respective escrow method.
2280
2281An Anastasis-server may store truth for free for a certain time period, or
2282charge per truth operation using GNU Taler.
2283
2284@anchor{rest post--truth-$UUID}@anchor{53}
2285@deffn {HTTP Post} POST /truth/$UUID
2286
2287Upload a @ref{54,,TruthUploadRequest}-Object according to the policy the client created before (see @ref{4e,,RecoveryDocument}).
2288If request has been seen before, the server should do nothing, and otherwise store the new object.
2289
2290@strong{Request:}
2291
2292@*Query Parameters:
2293
2294@itemize *
2295
2296@item
2297@code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will
2298wait up to @code{timeout_ms} milliseconds for completion of the payment before
2299sending the HTTP response. A client must never rely on this behavior, as the
2300backend may return a response immediately.
2301@end itemize
2302
2303
2304@strong{Response:}
2305
2306
2307@table @asis
2308
2309@item 204 No content@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.5}:
2310
2311Truth stored successfully.
2312
2313@item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}:
2314
2315The same truth was previously accepted and stored under this UUID. The
2316Anastasis server must still update the expiration time for the truth when returning
2317this response code.
2318
2319@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
2320
2321This server requires payment to store truth per item.
2322See the Taler payment protocol specification for how to pay.
2323The response body MAY provide alternative means for payment.
2324
2325@item 409 Conflict@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10}:
2326
2327The server already has some truth stored under this UUID. The client should check that it
2328is generating UUIDs with enough entropy.
2329
2330@item 412 Precondition failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.13}:
2331
2332The selected authentication method is not supported on this provider.
2333@end table
2334
2335@strong{Details:}
2336@anchor{rest truthuploadrequest}@anchor{54}
2337@example
2338interface TruthUploadRequest @{
2339 // Contains the information of an interface `EncryptedKeyShare`, but simply
2340 // as one binary block (in Crockford Base32 encoding for JSON).
2341 key_share_data: []; //bytearray
2342
2343 // Key share method, i.e. "security question", "SMS", "e-mail", ...
2344 type: string;
2345
2346 // Nonce used to compute the (iv,key) pair for encryption of the
2347 // encrypted_truth.
2348 nonce: [32]; //bytearray
2349
2350 // Authentication tag of `@w{`}encrypted_truth`@w{`}.
2351 aes_gcm_tag: [16]; //bytearray
2352
2353 // Variable-size truth. After decryption,
2354 // this contains the ground truth, i.e. H(challenge answer),
2355 // phone number, e-mail address, picture, fingerprint, ...
2356 // **base32 encoded**.
2357 //
2358 // The nonce of the HKDF for this encryption must include the
2359 // string "ECT".
2360 encrypted_truth: [80]; //bytearray
2361
2362 // MIME type of truth, i.e. text/ascii, image/jpeg, etc.
2363 truth_mime: string;
2364
2365 // For how many years from now would the client like us to
2366 // store the truth?
2367 storage_duration_years: Integer;
2368
2369@}
2370@end example
2371@end deffn
2372
2373@anchor{rest get--truth-$UUID[?response=$H_RESPONSE]}@anchor{55}
2374@deffn {HTTP Get} GET /truth/$UUID[?response=$H_RESPONSE]
2375
2376Get the stored encrypted key share. If @code{$H_RESPONSE} is specified by the client, the server checks
2377if @code{$H_RESPONSE} matches the expected response specified before within the @ref{54,,TruthUploadRequest} (see @code{encrypted_truth}).
2378Also, the user has to provide the correct @emph{truth_encryption_key} with every get request (see below).
2379When @code{$H_RESPONSE} is correct, the server responds with the encrypted key share.
2380The encrypted key share is returned simply as a byte array and not in JSON format.
2381
2382@strong{Response}:
2383
2384
2385@table @asis
2386
2387@item 200 OK@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.1}:
2388
2389@ref{56,,EncryptedKeyShare} is returned in body (in binary).
2390
2391@item 202 Accepted@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2.3}:
2392
2393The escrow provider will respond out-of-band (i.e. SMS).
2394The body may contain human-readable instructions on next steps.
2395
2396@item >>208 Already Reported<<:
2397
2398An authentication challenge was recently send, client should
2399simply respond to the pending challenge.
2400
2401@item 303 See other@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.4}:
2402
2403The provider redirects for authentication (i.e. video identification/WebRTC).
2404If the client is not a browser, it should launch a browser at the URL
2405given in the @code{Location} header and allow the user to re-try the operation
2406after successful authorization.
2407
2408@item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}:
2409
2410The service requires payment for access to truth.
2411See the Taler payment protocol specification for how to pay.
2412The response body MAY provide alternative means for payment.
2413
2414@item 403 Forbidden@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.4}:
2415
2416The server requires a valid “response” to the challenge associated with the UUID.
2417
2418@item 404 Not found@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.5}:
2419
2420The server does not know any truth under the given UUID.
2421
2422@item 410 Gone@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.11}:
2423
2424The server has not (recently) issued a challenge under the given UUID,
2425but a reply was provided. (This does not apply for secure question.)
2426
2427@item 417 Expectation Failed@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.18}:
2428
2429The decrypted @code{truth} does not match the expectations of the authentication
2430backend, i.e. a phone number for sending an SMS is not a number, or
2431an e-mail address for sending an E-mail is not a valid e-mail address.
2432
2433@item 503 Service Unavailable@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5.4}:
2434
2435Server is out of Service.
2436@end table
2437
2438@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
2439the according @ref{4f,,EscrowMethod}. The server needs this key to get the info out of @ref{54,,TruthUploadRequest} needed to verify the @code{$RESPONSE}.
2440
2441@strong{Details:}
2442@anchor{rest encryptedkeyshare}@anchor{56}
2443@example
2444interface EncryptedKeyShare @{
2445 // Nonce used to compute the decryption (iv,key) pair.
2446 nonce_i: [32]; //bytearray
2447
2448 // Authentication tag.
2449 aes_gcm_tag_i: [16]; //bytearray
2450
2451 // Encrypted key-share in base32 encoding.
2452 // After decryption, this yields a `KeyShare`. Note that
2453 // the `KeyShare` MUST be encoded as a fixed-size binary
2454 // block (instead of in JSON encoding).
2455 //
2456 // HKDF for the key generation must include the
2457 // string "eks" as salt.
2458 // Depending on the method,
2459 // the HKDF may additionally include
2460 // bits from the response (i.e. some hash over the
2461 // answer to the security question).
2462 encrypted_key_share_i: [32]; //bytearray
2463
2464@}
2465@end example
2466@anchor{rest keyshare}@anchor{57}
2467@example
2468interface KeyShare @{
2469 // Key material to concatenate with policy_salt and KDF to derive
2470 // the key to decrypt the master key.
2471 key_share: [32]; //bytearray
2472
2473 // Signature over method, UUID, and `@w{`}key_share`@w{`}.
2474 account_sig: EddsaSignature;
2475
2476@}
2477@end example
2478@end deffn
2479
2480@c This file is part of Anastasis
2481@c Copyright (C) 2019-2021 Anastasis SARL
2482@c
2483@c Anastasis is free software; you can redistribute it and/or modify it under the
2484@c terms of the GNU Affero General Public License as published by the Free Software
2485@c Foundation; either version 2.1, or (at your option) any later version.
2486@c
2487@c Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
2488@c WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
2489@c A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
2490@c
2491@c You should have received a copy of the GNU Affero General Public License along with
2492@c Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
2493@c
2494@c @author Christian Grothoff
2495@c @author Dominik Meister
2496@c @author Dennis Neufeld
2497
2498@node Reducer API,Authentication Methods,REST API,Documentation Overview
2499@anchor{reducer doc}@anchor{58}@anchor{reducer reducer-api}@anchor{59}
2500@section Reducer API
2501
2502
2503This section describes the Anastasis Reducer API which is used by client applications
2504to store or load the different states the client application can have.
2505The reducer takes a @ref{5a,,state} in JSON syntax and returns the new state in JSON syntax.
2506
2507For example a @strong{state} may take the following structure:
2508
2509@example
2510@{
2511 "backup_state": "CONTINENT_SELECTING",
2512 "continents": [
2513 "Europe",
2514 "North_America"
2515 ]
2516@}
2517@end example
2518
2519The new state depends on the previous one and on the transition @ref{5b,,action} with its
2520arguments given to the reducer. A @strong{transition argument} also is a statement in JSON syntax:
2521
2522@example
2523@{
2524 "continent": "Europe"
2525@}
2526@end example
2527
2528The new state returned by the reducer with the state and transition argument defined
2529above would look like following for the transition @ref{5b,,action} @code{select_continent}:
2530
2531@example
2532@{
2533 "backup_state": "COUNTRY_SELECTING",
2534 "continents": [
2535 "Europe",
2536 "North_America"
2537 ],
2538 "selected_continent": "Europe",
2539 "countries": [
2540 @{
2541 "code": "ch",
2542 "name": "Switzerland",
2543 "continent": "Europe",
2544 "name_i18n": @{
2545 "de_DE": "Schweiz",
2546 "de_CH": "Schwiiz",
2547 "fr": "Suisse",
2548 "en": "Swiss"
2549 @},
2550 "currency": "CHF"
2551 @},
2552 @{
2553 "code": "de",
2554 "name": "Germany",
2555 "continent": "Europe",
2556 "continent_i18n": @{
2557 "de": "Europa"
2558 @},
2559 "name_i18n": @{
2560 "de_DE": "Deutschland",
2561 "de_CH": "Deutschland",
2562 "fr": "Allemagne",
2563 "en": "Germany"
2564 @},
2565 "currency": "EUR"
2566 @}
2567 ]
2568@}
2569@end example
2570
2571@menu
2572* States::
2573* Backup Reducer::
2574* Recovery Reducer::
2575* Reducer transitions::
2576
2577@end menu
2578
2579@node States,Backup Reducer,,Reducer API
2580@anchor{reducer states}@anchor{5c}
2581@subsection States
2582
2583
2584Overall, the reducer knows the following states:
2585
2586@quotation
2587
2588
2589@itemize -
2590
2591@item
2592
2593@table @asis
2594
2595@item @strong{ERROR}: The transition led to an error. No further transitions are possible from
2596
2597this state, but the client may want to continue from a previous state.
2598@end table
2599
2600@item
2601
2602@table @asis
2603
2604@item @strong{CONTINENT_SELECTING}: The user should specify the continent where they are living,
2605
2606so that we can show a list of countries to choose from.
2607@end table
2608
2609@item
2610
2611@table @asis
2612
2613@item @strong{COUNTRY_SELECTING}: The user should specify the country where they are living,
2614
2615so that we can determine appropriate attributes, currencies and Anastasis
2616providers.
2617@end table
2618
2619@item
2620
2621@table @asis
2622
2623@item @strong{USER_ATTRIBUTES_COLLECTING}: The user should provide the country-specific personal
2624
2625attributes.
2626@end table
2627
2628@item
2629
2630@table @asis
2631
2632@item @strong{AUTHENTICATIONS_EDITING}: The user should add authentication methods to be used
2633
2634during recovery.
2635@end table
2636
2637@item
2638@strong{POLICIES_REVIEWING}: The user should review the recovery policies.
2639
2640@item
2641@strong{SECRET_EDITING}: The user should edit the secret to be backed up.
2642
2643@item
2644
2645@table @asis
2646
2647@item @strong{TRUTHS_PAYING}: The user needs to pay for one or more uploads of data associated
2648
2649with an authentication method.
2650@end table
2651
2652@item
2653@strong{POLICIES_PAYING}: The user needs to pay for storing the recovery policy document.
2654
2655@item
2656@strong{BACKUP_FINISHED}: A backup has been successfully generated.
2657
2658@item
2659
2660@table @asis
2661
2662@item @strong{SECRET_SELECTING}: The user needs to select a recovery policy document with
2663
2664the secret that is to be recovered.
2665@end table
2666
2667@item
2668
2669@table @asis
2670
2671@item @strong{CHALLENGE_SELECTING}: The user needs to select an authorization challenge to
2672
2673proceed with recovery.
2674@end table
2675
2676@item
2677@strong{CHALLENGE_PAYING}: The user needs to pay to proceed with the authorization challenge.
2678
2679@item
2680@strong{CHALLENGE_SOLVING}: The user needs to solve the authorization challenge.
2681
2682@item
2683@strong{RECOVERY_FINISHED}: The secret of the user has been recovered.
2684@end itemize
2685@end quotation
2686
2687State names:
2688
2689@quotation
2690
2691
2692@itemize -
2693
2694@item
2695In 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).
2696
2697@item
2698In COLLECTING-states, the user has to give certain values.
2699
2700@item
2701In EDITING-states, the user is free to choose which values he wants to give.
2702
2703@item
2704In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something.
2705
2706@item
2707in PAYING-states, the user must make a payment.
2708
2709@item
2710in FINISHED-states, the operation has definitively concluded.
2711@end itemize
2712@end quotation
2713
2714@node Backup Reducer,Recovery Reducer,States,Reducer API
2715@anchor{reducer backup-reducer}@anchor{5d}
2716@subsection Backup Reducer
2717
2718@anchor{reducer state}@anchor{5a}@anchor{reducer action}@anchor{5b}
2719
2720@float Figure
2721
2722@image{anastasis-figures/anastasis_reducer_backup,,,fig-anastasis_reducer_backup,png}
2723
2724@caption{Backup states and their transitions.}
2725
2726@end float
2727
2728
2729The illustration above shows the different states the reducer can have during a backup
2730process.
2731
2732@node Recovery Reducer,Reducer transitions,Backup Reducer,Reducer API
2733@anchor{reducer recovery-reducer}@anchor{5e}
2734@subsection Recovery Reducer
2735
2736
2737
2738@float Figure
2739
2740@image{anastasis-figures/anastasis_reducer_recovery,,,fig-anastasis_reducer_recovery,png}
2741
2742@caption{Recovery states and their transitions.}
2743
2744@end float
2745
2746
2747The illustration above shows the different states the reducer can have during a recovery
2748process.
2749
2750@node Reducer transitions,,Recovery Reducer,Reducer API
2751@anchor{reducer reducer-transitions}@anchor{5f}
2752@subsection Reducer transitions
2753
2754
2755In the following, the individual transitions will be specified in more detail.
2756Note that we only show fields added by the reducer, typically the previous
2757state is preserved to enable “back” transitions to function smoothly.
2758
2759@menu
2760* Initial state::
2761* Common transitions::
2762* Backup transitions::
2763* Recovery transitions::
2764
2765@end menu
2766
2767@node Initial state,Common transitions,,Reducer transitions
2768@anchor{reducer initial-state}@anchor{60}
2769@subsubsection Initial state
2770
2771
2772The initial states for backup and recovery processes are:
2773
2774@strong{Initial backup state:}
2775
2776@example
2777@{
2778 "backup_state": "CONTINENT_SELECTING",
2779 "continents": [
2780 "Europe",
2781 "North America"
2782 ]
2783@}
2784@end example
2785
2786@strong{Initial recovery state:}
2787
2788@example
2789@{
2790 "recovery_state": "CONTINENT_SELECTING",
2791 "continents": [
2792 "Europe",
2793 "North America"
2794 ]
2795@}
2796@end example
2797
2798Here, “continents” is an array of English strings with the names of the
2799continents which contain countries for which Anastasis could function (based
2800on having providers that are known to operate and rules being provided for
2801user attributes from those countries).
2802
2803For internationalization, another field @code{continents_i18n} may be present.
2804This field would be a map of language names to arrays of translated
2805continent names:
2806
2807@example
2808@{
2809 "recovery_state": "CONTINENT_SELECTING",
2810 "continents": [
2811 "Europe",
2812 "North America"
2813 ]
2814 "continents_i18n":
2815 @{
2816 "de_DE" : [
2817 "Europa",
2818 "Nordamerika"
2819 ],
2820 "de_CH" : [
2821 "Europa",
2822 "Nordamerika"
2823 ]
2824 @}
2825@}
2826@end example
2827
2828Translations must be given in the same order as the main English array.
2829
2830@node Common transitions,Backup transitions,Initial state,Reducer transitions
2831@anchor{reducer common-transitions}@anchor{61}
2832@subsubsection Common transitions
2833
2834
2835@strong{select_continent:}
2836
2837Here the user specifies the continent they live on. Arguments (example):
2838
2839@example
2840@{
2841 "continent": "Europe"
2842@}
2843@end example
2844
2845The continent must be given using the English name from the @code{continents} array.
2846Using a translated continent name is invalid and may result in failure.
2847
2848The reducer returns an updated state with a list of countries to choose from,
2849for example:
2850
2851@example
2852@{
2853 "backup_state": "COUNTRY_SELECTING",
2854 "selected_continent": "Europe",
2855 "countries": [
2856 @{
2857 "code": "ch",
2858 "name": "Switzerland",
2859 "continent": "Europe",
2860 "name_i18n": @{
2861 "de_DE": "Schweiz",
2862 "de_CH": "Schwiiz",
2863 "fr": "Suisse",
2864 "en": "Swiss"
2865 @},
2866 "currency": "CHF"
2867 @},
2868 @{
2869 "code": "de",
2870 "name": "Germany",
2871 "continent": "Europe",
2872 "continent_i18n": @{
2873 "de": "Europa"
2874 @},
2875 "name_i18n": @{
2876 "de_DE": "Deutschland",
2877 "de_CH": "Deutschland",
2878 "fr": "Allemagne",
2879 "en": "Germany"
2880 @},
2881 "currency": "EUR"
2882 @}
2883 ]
2884@}
2885@end example
2886
2887Here @code{countries} is an array of countries on the @code{selected_continent}. For
2888each country, the @code{code} is the ISO 3166-1 alpha-2 country code. The
2889@code{continent} is only present because some countries span continents, the
2890information is redundant and will always match @code{selected_continent}. The
2891@code{name} is the name of the country in English, internationalizations of the
2892name may be provided in @code{name_i18n}. The @code{currency} is @strong{an} official
2893currency of the country, if a country has multiple currencies, it may appear
2894multiple times in the list. In this case, the user should select the entry
2895with the currency they intend to pay with. It is also possible for users
2896to select a currency that does not match their country, but user interfaces
2897should by default try to use currencies that match the user’s residence.
2898
2899@strong{select_country:}
2900
2901Selects the country (via the country code) and specifies the currency.
2902The latter is needed as some countries have more than one currency,
2903and some use-cases may also involve users insisting on paying with
2904foreign currency.
2905
2906Arguments (example):
2907
2908@example
2909@{
2910 "country_code": "de",
2911 "currency": "EUR"
2912@}
2913@end example
2914
2915The @code{country_code} must be an ISO 3166-1 alpha-2 country code from
2916the array of @code{countries} of the reducer’s state. The @code{currency}
2917field must be a valid currency accepted by the Taler payment system.
2918
2919The reducer returns a new state with the list of attributes the
2920user is expected to provide, as well as possible authentication
2921providers that accept payments in the selected currency:
2922
2923@example
2924@{
2925 "backup_state": "USER_ATTRIBUTES_COLLECTING",
2926 "selected_country": "de",
2927 "currency": "EUR",
2928 "required_attributes": [
2929 @{
2930 "type": "string",
2931 "name": "full_name",
2932 "label": "Full name",
2933 "label_i18n": @{
2934 "de_DE": "Vollstaendiger Name",
2935 "de_CH": "Vollstaendiger. Name",
2936 "fr": "Nom complet",
2937 "en": "Full name"
2938 @},
2939 "widget": "anastasis_gtk_ia_full_name",
2940 "uuid" : "9e8f463f-575f-42cb-85f3-759559997331"
2941 @},
2942 @{
2943 "type": "date",
2944 "name": "birthdate",
2945 "label": "Birthdate",
2946 "label_i18n": @{
2947 "de_DE": "Geburtsdatum",
2948 "de_CH": "Geburtsdatum",
2949 "fr": "Date de naissance",
2950 "en": "Birthdate"
2951 @},
2952 "uuid" : "83d655c7-bdb6-484d-904e-80c1058c8854"
2953 "widget": "anastasis_gtk_ia_birthdate"
2954 @},
2955 @{
2956 "type": "string",
2957 "name": "tax_number",
2958 "label": "Taxpayer identification number",
2959 "label_i18n":@{
2960 "de_DE": "Steuerliche Identifikationsnummer",
2961 "de_CH": "Steuerliche Identifikationsnummer",
2962 "en": "German taxpayer identification number"
2963 @},
2964 "widget": "anastasis_gtk_ia_tax_de",
2965 "uuid": "dae48f85-e3ff-47a4-a4a3-ed981ed8c3c6",
2966 "validation-regex": "^[0-9]@{11@}$",
2967 "validation-logic": "DE_TIN_check"
2968 @},
2969 @{
2970 "type": "string",
2971 "name": "social_security_number",
2972 "label": "Social security number",
2973 "label_i18n": @{
2974 "de_DE": "Sozialversicherungsnummer",
2975 "de_CH": "Sozialversicherungsnummer",
2976 "fr": "Numéro de sécurité sociale",
2977 "en": "Social security number"
2978 @},
2979 "widget": "anastasis_gtk_ia_ssn",
2980 "validation-regex": "^[0-9]@{8@}[[:upper:]][0-9]@{3@}$",
2981 "validation-logic": "DE_SVN_check"
2982 "optional" : true
2983 @}
2984 ],
2985 "authentication_providers": @{
2986 "http://localhost:8089/": @{
2987 "http_status": 200,
2988 "methods": [
2989 @{ "type" : "question",
2990 "usage_fee" : "EUR:0.0" @},
2991 @{ "type" : "sms",
2992 "usage_fee" : "EUR:0.5" @}
2993 ],
2994 "annual_fee": "EUR:4.99",
2995 "truth_upload_fee": "EUR:4.99",
2996 "liability_limit": "EUR:1",
2997 "currency": "EUR",
2998 "truth_lifetime": @{ "d_ms" : 50000000 @},
2999 "storage_limit_in_megabytes": 1,
3000 "provider_name": "Anastasis 4",
3001 "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
3002 @},
3003 "http://localhost:8088/": @{
3004 "http_status": 200,
3005 "methods": [
3006 @{ "type" : "question",
3007 "usage_fee" : "EUR:0.01" @},
3008 @{ "type" : "sms",
3009 "usage_fee" : "EUR:0.55" @}
3010 ],
3011 "annual_fee": "EUR:0.99",
3012 "truth_upload_fee": "EUR:3.99",
3013 "liability_limit": "EUR:1",
3014 "currency": "EUR",
3015 "truth_lifetime": @{ "d_ms" : 50000000 @},
3016 "storage_limit_in_megabytes": 1,
3017 "provider_name": "Anastasis 4",
3018 "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
3019 @}
3020 @}
3021@}
3022@end example
3023
3024The array of @code{required_attributes} contains attributes about the user
3025that must be provided includes:
3026
3027@quotation
3028
3029
3030@itemize -
3031
3032@item
3033@strong{type}: The type of the attribute, for now only @code{string} and @code{date} are
3034supported.
3035
3036@item
3037@strong{name}: The name of the attribute, this is the key under which the
3038attribute value must be provided later. The name must be unique per response.
3039
3040@item
3041@strong{label}: A human-readable description of the attribute in English.
3042Translated descriptions may be provided under @strong{label_i18n}.
3043
3044@item
3045@strong{uuid}: A UUID that uniquely identifies identical attributes across
3046different countries. Useful to preserve values should the user enter
3047some attributes, and then switch to another country. Note that
3048attributes must not be preserved if they merely have the same @strong{name},
3049only the @strong{uuid} will be identical if the semantics is identical.
3050
3051@item
3052@strong{widget}: An optional name of a widget that is known to nicely render
3053the attribute entry in user interfaces where named widgets are
3054supported.
3055
3056@item
3057@strong{validation-regex}: An optional extended POSIX regular expression
3058that is to be used to validate (string) inputs to ensure they are
3059well-formed.
3060
3061@item
3062@strong{validation-logic}: Optional name of a function that should be called
3063to validate the input. If the function is not known to the particular
3064client, the respective validation can be skipped (at the expense of
3065typos by users not being detected, possibly rendering secrets
3066irrecoverable).
3067
3068@item
3069@strong{optional}: Optional boolean field that, if @code{true}, indicates that
3070this attribute is not actually required but optional and users MAY leave
3071it blank in case they do not have the requested information. Used for
3072common fields that apply to some large part of the population but are
3073not sufficiently universal to be actually required.
3074@end itemize
3075@end quotation
3076
3077The authentication providers are listed under a key that is the
3078base URL of the service. For each provider, the following
3079information is provided if the provider was successfully contacted:
3080
3081@quotation
3082
3083
3084@itemize -
3085
3086@item
3087@strong{http_status}: HTTP status code, always @code{200} on success.
3088
3089@item
3090@strong{methods}: Array of authentication methods supported by this
3091provider. Includes the @strong{type} of the authentication method
3092and the @strong{usage_fee} (how much the user must pay for authorization
3093using this method during recovery).
3094
3095@item
3096@strong{annual_fee}: Fee the provider charges to store the recovery
3097policy for one year.
3098
3099@item
3100@strong{truth_upload_fee}: Fee the provider charges to store a key share.
3101
3102@item
3103@strong{liability_limit}: Amount the provider can be held liable for in
3104case a key share or recovery document cannot be recovered due to
3105provider failures.
3106
3107@item
3108@strong{currency}: Currency in which the provider wants to be paid,
3109will match all of the fees.
3110
3111@item
3112@strong{storage_limit_in_megabytes}: Maximum size of an upload (for
3113both recovery document and truth data) in megabytes.
3114
3115@item
3116@strong{provider_name}: Human-readable name of the provider’s business.
3117
3118@item
3119@strong{salt}: Salt value used by the provider, used to derive the
3120user’s identity at this provider. Should be unique per provider,
3121and must never change for a given provider. The salt is
3122base32 encoded.
3123@end itemize
3124@end quotation
3125
3126If contacting the provider failed, the information returned is:
3127
3128@quotation
3129
3130
3131@itemize -
3132
3133@item
3134@strong{http_status}: HTTP status code (if available, possibly 0 if
3135we did not even obtain an HTTP response).
3136
3137@item
3138@strong{error_code}: Taler error code, never 0.
3139@end itemize
3140@end quotation
3141
3142@strong{add_provider}:
3143
3144This operation can be performed in state @code{USER_ATTRIBUTES_COLLECTING}. It
3145adds one or more Anastasis providers to the list of providers the reducer
3146should henceforth consider. Note that removing providers is not possible at
3147this time.
3148
3149Here, the client must provide an array with the base URLs of the
3150providers to add, for example:
3151
3152@example
3153@{
3154 "urls": [
3155 "http://localhost:8888/",
3156 "http://localhost:8089/"
3157 ]
3158@}
3159@end example
3160
3161Note that existing providers will remain in the state. The following is an
3162example for an expected new state where the service on port 8089 is
3163unreachable, the service on port 8088 was previously known, and service on
3164port 8888 was now added:
3165
3166@example
3167@{
3168 "backup_state": "USER_ATTRIBUTES_COLLECTING",
3169 "authentication_providers": @{
3170 "http://localhost:8089/": @{
3171 "error_code": 11,
3172 "http_status": 0
3173 @},
3174 "http://localhost:8088/": @{
3175 "http_status": 200,
3176 "methods": [
3177 @{ "type" : "question",
3178 "usage_fee" : "EUR:0.01" @},
3179 @{ "type" : "sms",
3180 "usage_fee" : "EUR:0.55" @}
3181 ],
3182 "annual_fee": "EUR:0.99",
3183 "truth_upload_fee": "EUR:3.99",
3184 "liability_limit": "EUR:1",
3185 "currency": "EUR",
3186 "truth_lifetime": @{ "d_ms" : 50000000 @},
3187 "storage_limit_in_megabytes": 1,
3188 "provider_name": "Anastasis 4",
3189 "salt": "CXAPCKSH9D3MYJTS9536RHJHCW"
3190 @}
3191 "http://localhost:8888/": @{
3192 "methods": [
3193 @{ "type" : "question",
3194 "usage_fee" : "EUR:0.01" @},
3195 @{ "type" : "sms",
3196 "usage_fee" : "EUR:0.55" @}
3197 ],
3198 "annual_fee": "EUR:0.99",
3199 "truth_upload_fee": "EUR:3.99",
3200 "liability_limit": "EUR:1",
3201 "currency": "EUR",
3202 "truth_lifetime": @{ "d_ms" : 50000000 @},
3203 "storage_limit_in_megabytes": 1,
3204 "provider_name": "Anastasis 42",
3205 "salt": "BXAPCKSH9D3MYJTS9536RHJHCX"
3206 @}
3207 @}
3208@}
3209@end example
3210
3211@node Backup transitions,Recovery transitions,Common transitions,Reducer transitions
3212@anchor{reducer backup-transitions}@anchor{62}
3213@subsubsection Backup transitions
3214
3215
3216@strong{enter_user_attributes:}
3217
3218This transition provides the user’s personal attributes. The specific set of
3219attributes required depends on the country of residence of the user. Some
3220attributes may be optional, in which case they should be omitted entirely
3221(that is, not simply be set to @code{null} or an empty string). Example
3222arguments would be:
3223
3224@example
3225@{
3226 "identity_attributes": @{
3227 "full_name": "Max Musterman",
3228 "social_security_number": "123456789",
3229 "birthdate": "2000-01-01",
3230 "birthplace": "Earth"
3231 @}
3232@}
3233@end example
3234
3235Note that at this stage, the state machines between backup and
3236recovery diverge and the @code{recovery_state} will begin to look
3237very different from the @code{backup_state}.
3238
3239For backups, if all required attributes are present, the reducer will
3240transition to an @code{AUTHENTICATIONS_EDITING} state with the attributes added
3241to it:
3242
3243@example
3244@{
3245 "backup_state": "AUTHENTICATIONS_EDITING",
3246 "identity_attributes": @{
3247 "full_name": "Max Musterman",
3248 "social_security_number": "123456789",
3249 "birthdate": "2000-01-01",
3250 "birthplace": "Earth"
3251 @}
3252@}
3253@end example
3254
3255If required attributes are missing, do not match the required regular
3256expression, or fail the custom validation logic, the reducer SHOULD transition
3257to an error state indicating what was wrong about the input. A reducer that
3258does not support some specific validation logic MAY accept the invalid input
3259and proceed anyway. The error state will include a Taler error code that
3260is specific to the failure, and optional details. Example:
3261
3262@example
3263@{
3264 "backup_state": "ERROR",
3265 "code": 8404,
3266 "hint": "An input did not match the regular expression.",
3267 "detail": "social_security_number"
3268@}
3269@end example
3270
3271Clients may safely repeat this transition to validate the user’s inputs
3272until they satisfy all of the constraints. This way, the user interface
3273does not have to perform the input validation directly.
3274
3275@strong{add_authentication}:
3276
3277This transition adds an authentication method. The method must be supported
3278by one or more providers that are included in the current state. Adding an
3279authentication method requires specifying the @code{type} and @code{instructions} to
3280be given to the user. The @code{challenge} is encrypted and stored at the
3281Anastasis provider. The specific semantics of the value depend on the
3282@code{type}. Typical challenges values are a phone number (to send an SMS to),
3283an e-mail address (to send a PIN code to) or the answer to a security
3284question. Note that these challenge values will still be encrypted (and
3285possibly hashed) before being given to the Anastasis providers.
3286
3287Note that the @code{challenge} must be given in Crockford Base32 encoding, as it
3288MAY include binary data (such as a photograph of the user). In the latter
3289case, the optional @code{mime_type} field must be provided to give the MIME type
3290of the value encoded in @code{challenge}.
3291
3292@example
3293@{
3294 "authentication_method":
3295 @{
3296 "type": "question",
3297 "mime_type" : "text/plain",
3298 "instructions" : "What is your favorite GNU package?",
3299 "challenge" : "E1QPPS8A",
3300 @}
3301@}
3302@end example
3303
3304If the information provided is valid, the reducer will add the new
3305authentication method to the array of authentication methods:
3306
3307@example
3308@{
3309 "backup_state": "AUTHENTICATIONS_EDITING",
3310 "authentication_methods": [
3311 @{
3312 "type": "question",
3313 "mime_type" : "text/plain",
3314 "instructions" : "What is your favorite GNU package?",
3315 "challenge" : "E1QPPS8A",
3316 @},
3317 @{
3318 "type": "email",
3319 "instructions" : "E-mail to user@@*le.com",
3320 "challenge": "ENSPAWJ0CNW62VBGDHJJWRVFDM50"
3321 @}
3322 ]
3323@}
3324@end example
3325
3326@strong{delete_authentication}:
3327
3328This transition can be used to remove an authentication method from the
3329array of authentication methods. It simply requires the index of the
3330authentication method to remove. Note that the array is 0-indexed:
3331
3332@example
3333@{
3334 "authentication_method": 1
3335@}
3336@end example
3337
3338Assuming we begin with the state from the example above, this would
3339remove the @code{email} authentication method, resulting in the following
3340response:
3341
3342@example
3343@{
3344 "backup_state": "AUTHENTICATIONS_EDITING",
3345 "authentication_methods": [
3346 @{
3347 "type": "question",
3348 "mime_type" : "text/plain",
3349 "instructions" : "What is your favorite GNU package?",
3350 "challenge" : "gdb",
3351 @}
3352 ]
3353@}
3354@end example
3355
3356If the index is invalid, the reducer will instead
3357transition into an @code{ERROR} state.
3358
3359@strong{next} (from @code{AUTHENTICATIONS_EDITING}):
3360
3361This transition confirms that the user has finished adding (or removing)
3362authentication methods, and that the system should now automatically compute
3363a set of reasonable recovery policies.
3364
3365This transition does not take any mandatory arguments. Optional arguments can
3366be provided to upload the recovery document only to a specific subset of the
3367providers:
3368
3369@example
3370@{
3371 "providers": [
3372 "http://localhost:8088/",
3373 "http://localhost:8089/"
3374 ]
3375@}
3376@end example
3377
3378The resulting state provides the suggested recovery policies in a way suitable
3379for presentation to the user:
3380
3381@example
3382@{
3383 "backup_state": "POLICIES_REVIEWING",
3384 "policy_providers" : [
3385 @{ "provider_url" : "http://localhost:8088/" @},
3386 @{ "provider_url" : "http://localhost:8089/" @}
3387 ],
3388 "policies": [
3389 @{
3390 "methods": [
3391 @{
3392 "authentication_method": 0,
3393 "provider": "http://localhost:8088/"
3394 @},
3395 @{
3396 "authentication_method": 1,
3397 "provider": "http://localhost:8089/"
3398 @},
3399 @{
3400 "authentication_method": 2,
3401 "provider": "http://localhost:8087/"
3402 @}
3403 ]
3404 @},
3405 @{
3406 "methods": [
3407 @{
3408 "authentication_method": 0,
3409 "provider": "http://localhost:8088/"
3410 @},
3411 @{
3412 "authentication_method": 1,
3413 "provider": "http://localhost:8089/"
3414 @},
3415 @{
3416 "authentication_method": 3,
3417 "provider": "http://localhost:8089/"
3418 @}
3419 ]
3420 @}
3421 ]
3422@}
3423@end example
3424
3425For each recovery policy, the state includes the specific details of which
3426authentication @code{methods} must be solved to recovery the secret using this
3427policy. The @code{methods} array specifies the index of the
3428@code{authentication_method} in the @code{authentication_methods} array, as well as
3429the provider that was selected to supervise this authentication.
3430
3431If no authentication method was provided, the reducer will transition into an
3432@code{ERROR} state instead of suggesting policies.
3433
3434@strong{add_policy}:
3435
3436Using this transition, the user can add an additional recovery policy to the
3437state. The argument format is the same that is used in the existing state.
3438An example for a possible argument would thus be:
3439
3440@example
3441@{
3442 "policy": [
3443 @{
3444 "authentication_method": 1,
3445 "provider": "http://localhost:8088/"
3446 @},
3447 @{
3448 "authentication_method": 3,
3449 "provider": "http://localhost:8089/"
3450 @}
3451 ]
3452@}
3453@end example
3454
3455Note that the specified providers must already be in the
3456@code{authentication_providers} of the state. You cannot add new providers at
3457this stage. The reducer will simply attempt to append the suggested policy to
3458the “policies” array, returning an updated state:
3459
3460@example
3461@{
3462 "backup_state": "POLICIES_REVIEWING",
3463 "policies": [
3464 @{
3465 "methods": [
3466 @{
3467 "authentication_method": 0,
3468 "provider": "http://localhost:8089/"
3469 @},
3470 @{
3471 "authentication_method": 1,
3472 "provider": "http://localhost:8088/"
3473 @}
3474 ]
3475 @},
3476 @{
3477 "methods": [
3478 @{
3479 "authentication_method": 0,
3480 "provider": "http://localhost:8089/"
3481 @},
3482 @{
3483 "authentication_method": 2,
3484 "provider": "http://localhost:8088/"
3485 @}
3486 ]
3487 @},
3488 @{
3489 "methods": [
3490 @{
3491 "authentication_method": 1,
3492 "provider": "http://localhost:8089/"
3493 @},
3494 @{
3495 "authentication_method": 2,
3496 "provider": "http://localhost:8088/"
3497 @}
3498 ]
3499 @},
3500 @{
3501 "methods": [
3502 @{
3503 "authentication_method": 1,
3504 "provider": "http://localhost:8088/"
3505 @},
3506 @{
3507 "authentication_method": 3,
3508 "provider": "http://localhost:8089/"
3509 @}
3510 ]
3511 @}
3512 ]
3513@}
3514@end example
3515
3516If the new policy is invalid, for example because it adds an unknown
3517authentication method, or the selected provider does not support the type of
3518authentication, the reducer will transition into an @code{ERROR} state instead of
3519adding the new policy.
3520
3521@strong{update_policy}:
3522
3523Using this transition, the user can modify an existing recovery policy
3524in the state.
3525The argument format is the same that is used in @strong{add_policy},
3526except there is an additional key @code{policy_index} which
3527identifies the policy to modify.
3528An example for a possible argument would thus be:
3529
3530@example
3531@{
3532 "policy_index" : 1,
3533 "policy": [
3534 @{
3535 "authentication_method": 1,
3536 "provider": "http://localhost:8088/"
3537 @},
3538 @{
3539 "authentication_method": 3,
3540 "provider": "http://localhost:8089/"
3541 @}
3542 ]
3543@}
3544@end example
3545
3546If the new policy is invalid, for example because it adds an unknown
3547authentication method, or the selected provider does not support the type of
3548authentication, the reducer will transition into an @code{ERROR} state instead of
3549modifying the policy.
3550
3551@strong{delete_policy:}
3552
3553This transition allows the deletion of a recovery policy. The argument
3554simply specifies the index of the policy to delete, for example:
3555
3556@example
3557@{
3558 "policy_index": 3
3559@}
3560@end example
3561
3562Given as input the state from the example above, the expected new state would
3563be:
3564
3565@example
3566@{
3567 "backup_state": "POLICIES_REVIEWING",
3568 "policies": [
3569 @{
3570 "methods": [
3571 @{
3572 "authentication_method": 0,
3573 "provider": "http://localhost:8089/"
3574 @},
3575 @{
3576 "authentication_method": 1,
3577 "provider": "http://localhost:8088/"
3578 @}
3579 ]
3580 @},
3581 @{
3582 "methods": [
3583 @{
3584 "authentication_method": 0,
3585 "provider": "http://localhost:8089/"
3586 @},
3587 @{
3588 "authentication_method": 2,
3589 "provider": "http://localhost:8088/"
3590 @}
3591 ]
3592 @},
3593 @{
3594 "methods": [
3595 @{
3596 "authentication_method": 1,
3597 "provider": "http://localhost:8089/"
3598 @},
3599 @{
3600 "authentication_method": 2,
3601 "provider": "http://localhost:8088/"
3602 @}
3603 ]
3604 @}
3605 ]
3606@}
3607@end example
3608
3609If the index given is invalid, the reducer will transition into an @code{ERROR} state
3610instead of deleting a policy.
3611
3612@strong{delete_challenge:}
3613
3614This transition allows the deletion of an individual
3615challenge from a recovery policy. The argument
3616simply specifies the index of the policy and challenge
3617to delete, for example:
3618
3619@example
3620@{
3621 "policy_index": 1,
3622 "challenge_index" : 1
3623@}
3624@end example
3625
3626Given as input the state from the example above, the expected new state would
3627be:
3628
3629@example
3630@{
3631 "backup_state": "POLICIES_REVIEWING",
3632 "policies": [
3633 @{
3634 "methods": [
3635 @{
3636 "authentication_method": 0,
3637 "provider": "http://localhost:8089/"
3638 @},
3639 @{
3640 "authentication_method": 1,
3641 "provider": "http://localhost:8088/"
3642 @}
3643 ]
3644 @},
3645 @{
3646 "methods": [
3647 @{
3648 "authentication_method": 0,
3649 "provider": "http://localhost:8089/"
3650 @}
3651 ]
3652 @},
3653 @{
3654 "methods": [
3655 @{
3656 "authentication_method": 1,
3657 "provider": "http://localhost:8089/"
3658 @},
3659 @{
3660 "authentication_method": 2,
3661 "provider": "http://localhost:8088/"
3662 @}
3663 ]
3664 @}
3665 ]
3666@}
3667@end example
3668
3669If the index given is invalid, the reducer will transition into an @code{ERROR} state
3670instead of deleting a challenge.
3671
3672@strong{next} (from @code{POLICIES_REVIEWING}):
3673
3674Using this transition, the user confirms that the policies in the current
3675state are acceptable. The transition does not take any arguments.
3676
3677The reducer will simply transition to the @code{SECRET_EDITING} state:
3678
3679@example
3680@{
3681 "backup_state": "SECRET_EDITING",
3682 "upload_fees" : [ "KUDOS:42" ],
3683 "expiration" : @{ "t_ms" : 1245362362 @}
3684@}
3685@end example
3686
3687Here, @code{upload_fees} is an array of applicable upload fees for the
3688given policy expiration time. This is an array because fees could
3689be in different currencies. The final cost may be lower if the
3690user already paid for some of the time.
3691
3692If the array of @code{policies} is currently empty, the reducer will transition
3693into an @code{ERROR} state instead of allowing the user to continue.
3694
3695@strong{enter_secret:}
3696
3697This transition provides the reducer with the actual core @code{secret} of the user
3698that Anastasis is supposed to backup (and possibly recover). The argument is
3699simply the Crockford-Base32 encoded @code{value} together with its @code{mime} type, or a @code{text} field with a human-readable secret text.
3700For example:
3701
3702@example
3703@{
3704 "secret": @{
3705 "value": "EDJP6WK5EG50",
3706 "mime" : "text/plain"
3707 @},
3708 "expiration" : @{ "t_ms" : 1245362362 @}
3709@}
3710@end example
3711
3712If the application is unaware of the format, it set the @code{mime} field to @code{null}.
3713The @code{expiration} field is optional.
3714
3715The reducer remains in the @code{SECRET_EDITING} state, but now the secret and
3716updated expiration time are part of the state and the cost calculations will
3717be updated.
3718
3719@example
3720@{
3721 "backup_state": "SECRET_EDITING",
3722 "core_secret" : @{
3723 "value": "EDJP6WK5EG50",
3724 "mime" : "text/plain"
3725 @},
3726 "expiration" : @{ "t_ms" : 1245362362 @},
3727 "upload_fees" : [ "KUDOS:42" ]
3728@}
3729@end example
3730
3731@strong{clear_secret:}
3732
3733This transition removes the core secret from the state. It is simply a
3734convenience function to undo @code{enter_secret} without providing a new value
3735immediately. The transition takes no arguments. The resuting state will no
3736longer have the @code{core_secret} field, and be otherwise unchanged. Calling
3737@strong{clear_secret} on a state without a @code{core_secret} will result in an error.
3738
3739@strong{enter_secret_name:}
3740
3741This 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.
3742Applications that have built-in support for Anastasis MUST prefix the
3743secret name with an underscore and an application-specific identifier
3744registered in GANA so that they can use recognize their own backups.
3745An example argument would be:
3746
3747@example
3748@{
3749 "name": "_TALERWALLET_MyPinePhone",
3750@}
3751@end example
3752
3753Here, @code{MyPinePhone} might be chosen by the user to identify the
3754device that was being backed up.
3755
3756The reducer remains in the @code{SECRET_EDITING} state, but now the
3757secret name is updated:
3758
3759@example
3760@{
3761 "secret_name" : "_TALERWALLET_MyPinePhone"
3762@}
3763@end example
3764
3765@strong{update_expiration:}
3766
3767This transition asks the reducer to change the desired expiration time
3768and to update the associated cost. For example:
3769
3770@example
3771@{
3772 "expiration" : @{ "t_ms" : 1245362362 @}
3773@}
3774@end example
3775
3776The reducer remains in the @code{SECRET_EDITING} state, but the
3777expiration time and cost calculation will be updated.
3778
3779@example
3780@{
3781 "backup_state": "SECRET_EDITING",
3782 "expiration" : @{ "t_ms" : 1245362362 @},
3783 "upload_fees" : [ @{ "fee": "KUDOS:43" @} ]
3784@}
3785@end example
3786
3787@strong{next} (from @code{SECRET_EDITING}):
3788
3789Using this transition, the user confirms that the secret and expiration
3790settings in the current state are acceptable. The transition does not take any
3791arguments.
3792
3793If the secret is currently empty, the reducer will transition into an
3794@code{ERROR} state instead of allowing the user to continue.
3795
3796After adding a secret, the reducer may transition into different states
3797depending on whether payment(s) are necessary. If payments are needed, the
3798@code{secret} will be stored in the state under @code{core_secret}. Applications
3799should be careful when persisting the resulting state, as the @code{core_secret}
3800is not protected in the @code{PAYING} states. The @code{PAYING} states only differ
3801in terms of what the payments are for (key shares or the recovery document),
3802in all cases the state simply includes an array of Taler URIs that refer to
3803payments that need to be made with the Taler wallet.
3804
3805If all payments are complete, the reducer will transition into the
3806@code{BACKUP_FINISHED} state and (if applicable) delete the @code{core_secret} as an
3807additional safety measure.
3808
3809Example results are thus:
3810
3811@example
3812@{
3813 "backup_state": "TRUTHS_PAYING",
3814 "secret_name" : "$NAME",
3815 "core_secret" : @{ "$anything":"$anything" @},
3816 "payments": [
3817 "taler://pay/...",
3818 "taler://pay/..."
3819 ]
3820@}
3821@end example
3822
3823@example
3824@{
3825 "backup_state": "POLICIES_PAYING",
3826 "secret_name" : "$NAME",
3827 "core_secret" : @{ "$anything":"$anything" @},
3828 "payments": [
3829 "taler://pay/...",
3830 "taler://pay/..."
3831 ]
3832@}
3833@end example
3834
3835@example
3836@{
3837 "backup_state": "BACKUP_FINISHED",
3838@}
3839@end example
3840
3841@strong{pay:}
3842
3843This transition suggests to the reducer that a payment may have been made or
3844is immanent, and that the reducer should check with the Anastasis service
3845provider to see if the operation is now possible. The operation takes one
3846optional argument, which is a @code{timeout} value that specifies how long the
3847reducer may wait (in long polling) for the payment to complete:
3848
3849@example
3850@{
3851 "timeout": @{ "d_ms" : 5000 @},
3852@}
3853@end example
3854
3855The specified timeout is passed on to the Anastasis service provider(s), which
3856will wait this long before giving up. If no timeout is given, the check is
3857done as quickly as possible without additional delays. The reducer will continue
3858to either an updated state with the remaining payment requests, to the
3859@code{BACKUP_FINISHED} state (if all payments have been completed and the backup
3860finished), or into an @code{ERROR} state in case there was an irrecoverable error,
3861indicating the specific provider and how it failed. An example for this
3862final error state would be:
3863
3864@example
3865@{
3866 "backup_state": "ERROR",
3867 "http_status" : 500,
3868 "upload_status" : 52,
3869 "provider_url" : "https://bad.example.com/",
3870@}
3871@end example
3872
3873Here, the fields have the following meaning:
3874
3875@quotation
3876
3877
3878@itemize -
3879
3880@item
3881@strong{http_status} is the HTTP status returned by the Anastasis provider.
3882
3883@item
3884@strong{upload_status} is the Taler error code return by the provider.
3885
3886@item
3887@strong{provider_url} is the base URL of the failing provider.
3888@end itemize
3889@end quotation
3890
3891In the above example, 52 would thus imply that the Anastasis provider failed to
3892store information into its database.
3893
3894@node Recovery transitions,,Backup transitions,Reducer transitions
3895@anchor{reducer recovery-transitions}@anchor{63}
3896@subsubsection Recovery transitions
3897
3898
3899@strong{enter_user_attributes:}
3900
3901This transition provides the user’s personal attributes. The specific set of
3902attributes required depends on the country of residence of the user. Some
3903attributes may be optional, in which case they should be omitted entirely
3904(that is, not simply be set to @code{null} or an empty string). The
3905arguments are identical to the @strong{enter_user_attributes} transition from
3906the backup process. Example arguments would thus be:
3907
3908@example
3909@{
3910 "identity_attributes": @{
3911 "full_name": "Max Musterman",
3912 "social_security_number": "123456789",
3913 "birthdate": "2000-01-01",
3914 "birthplace": "Earth"
3915 @}
3916@}
3917@end example
3918
3919However, in contrast to the backup process, the reducer will attempt to
3920retrieve the latest recovery document from all known providers for the
3921selected currency given the above inputs. If a recovery document was found
3922by any provider, the reducer will attempt to load it and transition to
3923a state where the user can choose which challenges to satisfy:
3924
3925@example
3926@{
3927 "recovery_state": "CHALLENGE_SELECTING",
3928 "recovery_information": @{
3929 "challenges": [
3930 @{
3931 "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G",
3932 "cost": "TESTKUDOS:0",
3933 "type": "question",
3934 "instructions": "q1"
3935 @},
3936 @{
3937 "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
3938 "cost": "TESTKUDOS:0",
3939 "type": "email",
3940 "instructions": "e-mail address m?il@@f*.bar"
3941 @},
3942 ],
3943 "policies": [
3944 [
3945 @{
3946 "uuid": "MW2R3RCBZPHNC78AW8AKWRCHF9KV3Y82EN62T831ZP54S3K5599G"
3947 @},
3948 @{
3949 "uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0"
3950 @},
3951 ],
3952 ],
3953 "provider_url": "http://localhost:8088/",
3954 "version": 1,
3955 @},
3956 "recovery_document": @{
3957 "...": "..."
3958 @}
3959@}
3960@end example
3961
3962The @code{recovery_document} is an internal representation of the recovery
3963information and of no concern to the user interface. The pertinent information
3964is in the @code{recovery_information}. Here, the @code{challenges} array is a list
3965of possible challenges the user could attempt to solve next, while @code{policies}
3966is an array of policies, with each policy being an array of challenges.
3967Satisfying all of the challenges of one of the policies will enable the secret
3968to be recovered. The @code{provider_url} from where the recovery document was
3969obtained and its @code{version} are also provided. Each challenge comes with
3970four mandatory fields:
3971
3972@quotation
3973
3974
3975@itemize -
3976
3977@item
3978@strong{uuid}: A unique identifier of the challenge; this is what the
3979UUIDs in the policies array refer to, but also this UUID may be
3980included in messages sent to the user. They allow the user to
3981distinguish different PIN/TANs should say the same phone number be
3982used for SMS-authentication with different providers.
3983
3984@item
3985@strong{cost}: This is the amount the Anastasis provider will charge
3986to allow the user to pass the challenge.
3987
3988@item
3989@strong{type}: This is the type of the challenge, as a string.
3990
3991@item
3992@strong{instructions}: Contains additional important hints for the user
3993to allow the user to satisfy the challenge. It typically includes
3994an abbreviated form of the contact information or the security
3995question. Details depend on @code{type}.
3996@end itemize
3997@end quotation
3998
3999If a recovery document was not found, either the user never performed
4000a backup, entered incorrect attributes, or used a provider not yet in
4001the list of Anastasis providers. Hence, the user must now either
4002select a different provider, or go @code{back} and update the identity
4003attributes. In the case a recovery document was not found, the
4004transition fails, returning the error code and a human-readable error
4005message together with a transition failure:
4006
4007@example
4008@{
4009 "recovery_state": "ERROR",
4010 "error_message": "account unknown to Anastasis server",
4011 "error_code": 9,
4012@}
4013@end example
4014
4015Here, the @code{error_code} is from the @code{enum ANASTASIS_RecoveryStatus}
4016and describes precisely what failed about the download, while the
4017@code{error_message} is a human-readable (English) explanation of the code.
4018Applications may want to translate the message using GNU gettext;
4019translations should be available in the @code{anastasis} text domain.
4020However, in general it should be sufficient to display the slightly
4021more generic Taler error code that is returned with the new state.
4022
4023@strong{change_version:}
4024
4025Even if a recovery document was found, it is possible that the user
4026intended to recover a different version, or recover a backup where
4027the recovery document is stored at a different provider. Thus, the
4028reducer allows the user to explicitly switch to a different provider
4029or recovery document version using the @code{change_version} transition,
4030which takes a provider URL and policy version as arguments:
4031
4032@example
4033@{
4034 "provider_url": "https://localhost:8080/",
4035 "version": 2
4036@}
4037@end example
4038
4039Note that using a version of 0 implies fetching “the latest version”. The
4040resulting states are the same as those of the @code{enter_user_attributes}
4041transition, except that the recovery document version is not necessarily the
4042latest available version at the provider.
4043
4044@strong{select_challenge:}
4045
4046Selecting a challenge takes different, depending on the state of the payment.
4047A comprehensive example for @code{select_challenge} would be:
4048
4049@example
4050@{
4051 "uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
4052 "timeout" : @{ "d_ms" : 5000 @},
4053 "payment_secret": "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
4054@}
4055@end example
4056
4057The @code{uuid} field is mandatory and specifies the selected challenge.
4058The other fields are optional, and are needed in case the user has
4059previously been requested to pay for the challenge. In this case,
4060the @code{payment_secret} identifies the previous payment request, and
4061@code{timeout} says how long the Anastasis service should wait for the
4062payment to be completed before giving up (long polling).
4063
4064Depending on the type of the challenge and the need for payment, the
4065reducer may transition into @code{CHALLENGE_SOLVING} or @code{CHALLENGE_PAYING}
4066states. In @code{CHALLENGE_SOLVING}, the new state will primarily specify
4067the selected challenge:
4068
4069@example
4070@{
4071 "backup_state": "CHALLENGE_SOLVING",
4072 "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30"
4073@}
4074@end example
4075
4076In @code{CHALLENGE_PAYING}, the new state will include instructions for payment
4077in the @code{challenge_feedback}. In general, @code{challenge_feedback} includes
4078information about attempted challenges, with the final state being @code{solved}:
4079
4080@example
4081@{
4082 "recovery_state": "CHALLENGE_SELECTING",
4083 "recovery_information": @{
4084 "...": "..."
4085 @}
4086 "challenge_feedback": @{
4087 "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
4088 "state" : "solved"
4089 @}
4090 @}
4091@}
4092@end example
4093
4094Challenges feedback for a challenge can have many different @code{state} values
4095that applications must all handle. States other than @code{solved} are:
4096
4097@quotation
4098
4099
4100@itemize -
4101
4102@item
4103@strong{payment}: Here, the user must pay for a challenge. An example would be:
4104
4105@example
4106@{
4107 "backup_state": "CHALLENGE_PAYING",
4108 "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30",
4109 "challenge_feedback": @{
4110 "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" : @{
4111 "state" : "payment",
4112 "taler_pay_uri" : "taler://pay/...",
4113 "provider" : "https://localhost:8080/",
4114 "payment_secret" : "3P4561HAMHRRYEYD6CM6J7TS5VTD5SR2K2EXJDZEFSX92XKHR4KG"
4115 @}
4116 @}
4117@}
4118@end example
4119@end itemize
4120
4121@quotation
4122
4123
4124@itemize -
4125
4126@item
4127@strong{body}: Here, the server provided an HTTP reply for
4128how to solve the challenge, but the reducer could not parse
4129them into a known format. A mime-type may be provided and may
4130help parse the details.
4131
4132@example
4133@{
4134 "recovery_state": "CHALLENGE_SOLVING",
4135 "recovery_information": @{
4136 "...": "..."
4137 @}
4138 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4139 "challenge_feedback": @{
4140 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4141 "state": "body",
4142 "body": "CROCKFORDBASE32ENCODEDBODY",
4143 "http_status": 403,
4144 "mime_type" : "anything/possible"
4145 @}
4146 @}
4147@}
4148@end example
4149
4150@item
4151@strong{hint}: Here, the server provided human-readable hint for
4152how to solve the challenge. Note that the @code{hint} provided this
4153time is from the Anastasis provider and may differ from the @code{instructions}
4154for the challenge under @code{recovery_information}:
4155
4156@example
4157@{
4158 "recovery_state": "CHALLENGE_SOLVING",
4159 "recovery_information": @{
4160 "...": "..."
4161 @}
4162 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4163 "challenge_feedback": @{
4164 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4165 "state": "hint",
4166 "hint": "Recovery TAN send to email mail@@DOMAIN",
4167 "http_status": 403
4168 @}
4169 @}
4170@}
4171@end example
4172
4173@item
4174@strong{details}: Here, the server provided a detailed JSON status response
4175related to solving the challenge:
4176
4177@example
4178@{
4179 "recovery_state": "CHALLENGE_SOLVING",
4180 "recovery_information": @{
4181 "...": "..."
4182 @}
4183 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4184 "challenge_feedback": @{
4185 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4186 "state": "details",
4187 "details": @{
4188 "code": 8111,
4189 "hint": "The client's response to the challenge was invalid.",
4190 "detail" : null
4191 @},
4192 "http_status": 403
4193 @}
4194 @}
4195@}
4196@end example
4197@end itemize
4198
4199@quotation
4200
4201
4202@itemize -
4203
4204@item
4205@strong{redirect}: To solve the challenge, the user must visit the indicated
4206Web site at @code{redirect_url}, for example to perform video authentication:
4207@end itemize
4208
4209@quotation
4210
4211@example
4212@{
4213 "recovery_state": "CHALLENGE_SOLVING",
4214 "recovery_information": @{
4215 "...": "..."
4216 @}
4217 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4218 "challenge_feedback": @{
4219 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4220 "state": "redirect",
4221 "redirect_url": "https://videoconf.example.com/",
4222 "http_status": 303
4223 @}
4224 @}
4225@}
4226@end example
4227
4228
4229@itemize -
4230
4231@item
4232@strong{server-failure}: This indicates that the Anastasis provider encountered
4233a failure and recovery using this challenge cannot proceed at this time.
4234Examples for failures might be that the provider is unable to send SMS
4235messages at this time due to an outage. The body includes details about
4236the failure. The user may try again later or continue with other challenges.
4237@end itemize
4238
4239@example
4240@{
4241 "recovery_state": "CHALLENGE_SELECTING",
4242 "recovery_information": @{
4243 "...": "..."
4244 @}
4245 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4246 "challenge_feedback": @{
4247 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4248 "state": "server-failure",
4249 "http_status": "500",
4250 "error_code": 52
4251 @}
4252 @}
4253@}
4254@end example
4255
4256
4257@itemize -
4258
4259@item
4260@strong{truth-unknown}: This indicates that the Anastasis provider is unaware of
4261the specified challenge. This is typically a permanent failure, and user
4262interfaces should not allow users to re-try this challenge.
4263@end itemize
4264
4265@example
4266@{
4267 "recovery_state": "CHALLENGE_SELECTING",
4268 "recovery_information": @{
4269 "...": "..."
4270 @}
4271 "selected_challenge_uuid": "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0",
4272 "challenge_feedback": @{
4273 "TXYKGE1SJZHJ4M2FKSV1P2RZVNTHZFB9E3A79QE956D3SCAWXPK0": @{
4274 "state": "truth-unknown",
4275 "error_code": 8108
4276 @}
4277 @}
4278@}
4279@end example
4280
4281