diff options
Diffstat (limited to 'doc/anastasis.texi')
-rw-r--r-- | doc/anastasis.texi | 6093 |
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 | ||
24 | GNU Anastasis 0.0.0, Jul 30, 2021 | ||
25 | |||
26 | Anastasis SARL | ||
27 | |||
28 | Copyright @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 | |||
67 | GNU Anastasis is Free Software protocol and implementation that allows | ||
68 | users to securely deposit @strong{core secrets} with an open set of escrow | ||
69 | providers and to recover these secrets if their original copies are | ||
70 | lost. | ||
71 | |||
72 | Anastasis is intended for users that want to make backups of key | ||
73 | material, such as OpenPGP encryption keys, hard disk encryption keys | ||
74 | or master keys of electronic wallets. Anastasis is NOT intended to | ||
75 | store large amounts of secret data, it is only designed to safeguard | ||
76 | key material. | ||
77 | |||
78 | Anastasis solves the issue of keeping key material both available | ||
79 | to the authorized user(s), and confidential from anyone else. | ||
80 | |||
81 | With Anastasis, the @strong{core secrets} are protected from the Anastasis | ||
82 | escrow providers by encrypting each with a @strong{master key}. The | ||
83 | @strong{master key} can be split and distributed across the escrow | ||
84 | providers to ensure that no single escrow provider can recover the | ||
85 | @strong{master key} on its own. Which subset(s) of Anastasis providers | ||
86 | must be contacted to recover a @strong{master key} is freely configurable. | ||
87 | |||
88 | With Anastasis, users can reliably recover their @strong{core secret}, | ||
89 | while Anastasis makes this difficult for everyone else. This is even | ||
90 | true if the user is unable to reliably remember any secret with | ||
91 | sufficiently high entropy: Anastasis does not simply reduce the | ||
92 | problem to encrypting the @strong{core secret} using some other key | ||
93 | material in possession of the user. | ||
94 | |||
95 | @menu | ||
96 | * Documentation Overview:: | ||
97 | |||
98 | @detailmenu | ||
99 | --- The Detailed Node Listing --- | ||
100 | |||
101 | Documentation 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 | |||
117 | Introduction | ||
118 | |||
119 | * User Identifiers:: | ||
120 | * Adversary models:: | ||
121 | * The recovery document:: | ||
122 | |||
123 | Installation | ||
124 | |||
125 | * Installing from source:: | ||
126 | * Installing Anastasis binary packages on Debian:: | ||
127 | * Installing Anastasis binary packages on Ubuntu:: | ||
128 | |||
129 | Installing 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 | |||
138 | Installing Anastasis binary packages on Debian | ||
139 | |||
140 | * Installing the graphical front-end:: | ||
141 | * Installing the backend:: | ||
142 | |||
143 | Installing 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 | |||
148 | Configuration | ||
149 | |||
150 | * Configuration format:: | ||
151 | * Using anastasis-config:: | ||
152 | |||
153 | Cryptography | ||
154 | |||
155 | * Key derivations:: | ||
156 | * Key Usage:: | ||
157 | * Availability Considerations:: | ||
158 | |||
159 | Key derivations | ||
160 | |||
161 | * Verification:: | ||
162 | * Encryption:: | ||
163 | |||
164 | Key Usage | ||
165 | |||
166 | * Encryption: Encryption<2>. | ||
167 | * Signatures:: | ||
168 | |||
169 | REST API | ||
170 | |||
171 | * HTTP Request and Response:: | ||
172 | * Protocol Version Ranges:: | ||
173 | * Common encodings:: | ||
174 | |||
175 | Common 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 | |||
194 | Reducer API | ||
195 | |||
196 | * States:: | ||
197 | * Backup Reducer:: | ||
198 | * Recovery Reducer:: | ||
199 | * Reducer transitions:: | ||
200 | |||
201 | Reducer transitions | ||
202 | |||
203 | * Initial state:: | ||
204 | * Common transitions:: | ||
205 | * Backup transitions:: | ||
206 | * Recovery transitions:: | ||
207 | |||
208 | Authentication 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 | |||
216 | Design Documents | ||
217 | |||
218 | * Design Doc 001; Anastasis User Experience: Design Doc 001 Anastasis User Experience. | ||
219 | * Template:: | ||
220 | |||
221 | Design Doc 001: Anastasis User Experience | ||
222 | |||
223 | * Summary:: | ||
224 | * Motivation:: | ||
225 | * Setup Steps:: | ||
226 | * Show Service Status After Setup:: | ||
227 | * Recovery Steps:: | ||
228 | |||
229 | Setup 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 | |||
238 | Recovery 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 | |||
247 | Template | ||
248 | |||
249 | * Summary: Summary<2>. | ||
250 | * Motivation: Motivation<2>. | ||
251 | * Requirements:: | ||
252 | * Proposed Solution:: | ||
253 | * Alternatives:: | ||
254 | * Drawbacks:: | ||
255 | * Discussion / Q&A:: | ||
256 | |||
257 | Anastasis 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 | |||
263 | Anastasis (git://git.taler.net/anastasis) | ||
264 | |||
265 | * Runtime dependencies:: | ||
266 | |||
267 | Anastasis-gtk (git://git.taler.net/anastasis-gtk) | ||
268 | |||
269 | * Runtime dependencies: Runtime dependencies<2>. | ||
270 | |||
271 | Man 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 | |||
279 | anastasis-config(1) | ||
280 | |||
281 | * Synopsis:: | ||
282 | * Description:: | ||
283 | * See Also:: | ||
284 | * Bugs:: | ||
285 | |||
286 | anastasis-gtk(1) | ||
287 | |||
288 | * Synopsis: Synopsis<2>. | ||
289 | * Description: Description<2>. | ||
290 | * See Also: See Also<2>. | ||
291 | * Bugs: Bugs<2>. | ||
292 | |||
293 | anastasis-httpd(1) | ||
294 | |||
295 | * Synopsis: Synopsis<3>. | ||
296 | * Description: Description<3>. | ||
297 | * Signals:: | ||
298 | * See also:: | ||
299 | * Bugs: Bugs<3>. | ||
300 | |||
301 | anastasis-reducer(1) | ||
302 | |||
303 | * Synopsis: Synopsis<4>. | ||
304 | * Description: Description<4>. | ||
305 | * See Also: See Also<3>. | ||
306 | * Bugs: Bugs<4>. | ||
307 | |||
308 | anastasis.conf(5) | ||
309 | |||
310 | * Description: Description<5>. | ||
311 | * SEE ALSO:: | ||
312 | * BUGS:: | ||
313 | |||
314 | Description | ||
315 | |||
316 | * GLOBAL OPTIONS:: | ||
317 | * Authorization options:: | ||
318 | * Postgres database configuration:: | ||
319 | |||
320 | GNU 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 | |||
384 | To understand how Anastasis works, you need to understand three key | ||
385 | concepts: user identifiers, our adversary model and the role of the | ||
386 | recovery 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 | |||
400 | To uniquely identify users, an “unforgettable” @strong{identifier} is used. This | ||
401 | identifier 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 | ||
403 | cryptographically secure. Examples for such identifier would be a | ||
404 | concatenation of the full name of the user and their social security or | ||
405 | passport 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 | |||
412 | The adversary model of Anastasis has two types of adversaries: weak | ||
413 | adversaries which do not know the user’s @strong{identifier}, and strong | ||
414 | adversaries which somehow do know a user’s @strong{identifier}. For weak | ||
415 | adversaries the system guarantees full confidentiality. For strong | ||
416 | adversaries, breaking confidentiality additionally requires that Anastasis | ||
417 | escrow 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 | ||
419 | collude to break confidentiality. These policies also set the bar for the user | ||
420 | to 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 | |||
427 | A @strong{recovery document} includes all of the information a user needs to | ||
428 | recover access to their core secret. It specifies a set of @strong{escrow | ||
429 | methods}, which specify how the user should convince the Anastasis server | ||
430 | that they are “real”. Escrow methods can for example include SMS-based | ||
431 | verification, video identification or a security question. For each escrow | ||
432 | method, the Anastasis server is provided with @strong{truth}, that is data the | ||
433 | Anastasis operator may learn during the recovery process to authenticate the | ||
434 | user. Examples for truth would be a phone number (for SMS), a picture of the | ||
435 | user (for video identification), or the (hash of) a security answer. A strong | ||
436 | adversary is assumed to be able to learn the truth, while weak adversaries | ||
437 | must not. In addition to a set of escrow methods and associated Anastasis | ||
438 | server operators, the @strong{recovery document} also specifies @strong{policies}, which | ||
439 | describe the combination(s) of the escrow methods that suffice to obtain | ||
440 | access to the core secret. For example, a @strong{policy} could say that the | ||
441 | escrow methods (A and B) suffice, and a second policy may permit (A and C). A | ||
442 | different user may choose to use the policy that (A and B and C) are all | ||
443 | required. 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 | ||
445 | guarding a user’s secret. Weak adversaries must not be able to deduce | ||
446 | information about a user’s @strong{recovery document} (except for its length, which | ||
447 | may 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 | |||
472 | Please install the following packages before proceeding with the | ||
473 | exchange compilation. | ||
474 | |||
475 | |||
476 | @itemize - | ||
477 | |||
478 | @item | ||
479 | libsqlite3 >= 3.16.2 | ||
480 | |||
481 | @item | ||
482 | GNU libunistring >= 0.9.3 | ||
483 | |||
484 | @item | ||
485 | libcurl >= 7.26 (or libgnurl >= 7.26) | ||
486 | |||
487 | @item | ||
488 | libqrencode >= 4.0.0 | ||
489 | |||
490 | @item | ||
491 | GNU libgcrypt >= 1.6 | ||
492 | |||
493 | @item | ||
494 | libsodium >= 1.0 | ||
495 | |||
496 | @item | ||
497 | libargon2 >= 20171227 | ||
498 | |||
499 | @item | ||
500 | libjansson >= 2.7 | ||
501 | |||
502 | @item | ||
503 | Postgres >= 9.6, including libpq | ||
504 | |||
505 | @item | ||
506 | GNU libmicrohttpd >= 0.9.71 | ||
507 | |||
508 | @item | ||
509 | GNUnet >= 0.14.0 (from source tarball@footnote{http://ftpmirror.gnu.org/gnunet/}) | ||
510 | |||
511 | @item | ||
512 | GNU Taler exchange | ||
513 | |||
514 | @item | ||
515 | GNU Taler merchant backend | ||
516 | @end itemize | ||
517 | |||
518 | Except for the last two, these are available in most GNU/Linux distributions | ||
519 | and 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 | |||
533 | The following instructions will show how to install libgnunetutil and | ||
534 | the 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 | |||
551 | Before you install GNUnet, you must download and install the dependencies | ||
552 | mentioned in the previous section, otherwise the build may succeed, but could | ||
553 | fail to export some of the tooling required by GNU Taler. | ||
554 | |||
555 | To install GNUnet, unpack the tarball and change | ||
556 | into 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 | |||
567 | If you did not specify a prefix, GNUnet will install to @code{/usr/local}, | ||
568 | which requires you to run the last step as @code{root}. | ||
569 | The @code{ldconfig} command (also run as @code{root}) makes the | ||
570 | shared object libraries (@code{.so} files) | ||
571 | visible 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 | |||
578 | After installing GNUnet, unpack the GNU Taler exchange tarball, | ||
579 | change 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 | |||
590 | If you did not specify a prefix, the exchange will install to @code{/usr/local}, | ||
591 | which 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 | ||
593 | previous 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 | |||
600 | GNU Taler merchant has these additional dependencies: | ||
601 | |||
602 | |||
603 | @itemize - | ||
604 | |||
605 | @item | ||
606 | libqrencode >= 4.0.0 | ||
607 | @end itemize | ||
608 | |||
609 | The following steps assume all dependencies are installed. | ||
610 | |||
611 | First, unpack the GNU Taler merchant tarball and change into | ||
612 | the resulting directory. | ||
613 | Then, 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 | |||
625 | If 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 | |||
628 | You have to specify @code{--with-exchange=/usr/local} and/or | ||
629 | @code{--with-gnunet=/usr/local} if you installed the exchange and/or | ||
630 | GNUnet to @code{/usr/local} in the previous steps. | ||
631 | |||
632 | Depending on the prefixes you specified for the installation and the | ||
633 | distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding | ||
634 | lines 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 | ||
636 | run @code{ldconfig}. Without this step, it is possible that the linker may not | ||
637 | find the installed libraries and launching the Taler merchant backend would | ||
638 | then 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 | |||
645 | The following steps assume all dependencies are installed. | ||
646 | |||
647 | First, unpack the Anastasis tarball and change into | ||
648 | the resulting directory. | ||
649 | Then, 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 | |||
661 | If 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 | |||
664 | You have to specify @code{--with-exchange=/usr/local} and/or | ||
665 | @code{--with-gnunet=/usr/local} if you installed the exchange and/or | ||
666 | GNUnet to @code{/usr/local} in the previous steps. | ||
667 | |||
668 | Depending on the prefixes you specified for the installation and the | ||
669 | distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding | ||
670 | lines 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 | ||
672 | run @code{ldconfig}. Without this step, it is possible that the linker may not | ||
673 | find the installed libraries and launching the Anastasis backend would | ||
674 | then 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 | |||
681 | The following steps assume at least the GNUnet and Gtk+ dependencies are installed. | ||
682 | |||
683 | First, unpack the gnunet-gtk tarball and change into the resulting directory. | ||
684 | Then, 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 | |||
695 | It is highly recommended to use the same prefix ($PFX) for gnunet-gtk that was | ||
696 | used for GNUnet ($GNUNETPFX). If you did not specify a prefix, gnunet-gtk | ||
697 | will be installed to @code{/usr/local}, which requires you to run the last step | ||
698 | as @code{root}. | ||
699 | |||
700 | You have to specify @code{--with-gnunet=/usr/local} if you installed | ||
701 | GNUnet to @code{/usr/local} in the previous steps. | ||
702 | |||
703 | Depending on the prefixes you specified for the installation and the | ||
704 | distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding | ||
705 | lines for @code{$GNUNETPFX/lib/} and @code{$PFX/lib/} (replace the prefixes with the | ||
706 | actual paths you used). Afterwards, you should run @code{ldconfig}. Without this | ||
707 | step, it is possible that the linker may not find the installed libraries and | ||
708 | launching 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 | |||
715 | The following steps assume at least the GNUnet, gnunet-gtk and Anastasis | ||
716 | dependencies are installed. | ||
717 | |||
718 | First, unpack the anastasis-gtk tarball and change into the resulting | ||
719 | directory. Then, use the following commands to build and install | ||
720 | anastasis-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 | |||
733 | If 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 | |||
736 | You 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 | ||
738 | GNUnet to @code{/usr/local} in the previous steps. | ||
739 | |||
740 | Depending on the prefixes you specified for the installation and the | ||
741 | distribution you are using, you may have to edit @code{/etc/ld.so.conf}, adding | ||
742 | lines 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 | ||
744 | run @code{ldconfig}. Without this step, it is possible that the linker may not | ||
745 | find 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 | |||
752 | To install the GNU Taler Debian packages, first ensure that you have | ||
753 | the right Debian distribution. At this time, the packages are built for | ||
754 | Sid, which means you should use a system which at least includes | ||
755 | unstable packages in its source list. We recommend using APT pinning | ||
756 | to limit unstable packages to those explicitly requested. To do this, | ||
757 | set your @code{/etc/apt/preferences} as follows: | ||
758 | |||
759 | @example | ||
760 | Package: * | ||
761 | Pin: release a=stable | ||
762 | Pin-Priority: 700 | ||
763 | |||
764 | Package: * | ||
765 | Pin: release a=testing | ||
766 | Pin-Priority: 650 | ||
767 | |||
768 | Package: * | ||
769 | Pin: release a=unstable | ||
770 | Pin-Priority: 600 | ||
771 | |||
772 | Package: * | ||
773 | Pin: release l=Debian-Security | ||
774 | Pin-Priority: 1000 | ||
775 | @end example | ||
776 | |||
777 | A typical @code{/etc/apt/sources.list} file for this setup | ||
778 | which combines Debian stable with more recent packages | ||
779 | from testing and unstable would look like this: | ||
780 | |||
781 | @example | ||
782 | deb http://ftp.ch.debian.org/debian/ buster main | ||
783 | deb http://security.debian.org/debian-security buster/updates main | ||
784 | deb http://ftp.ch.debian.org/debian/ testing main | ||
785 | deb http://ftp.ch.debian.org/debian/ unstable main | ||
786 | @end example | ||
787 | |||
788 | Naturally, you may want to use different mirrors depending on your region. | ||
789 | Additionally, you must add a file to import the GNU Taler packages. Typically, | ||
790 | this is done by adding a file @code{/etc/apt/sources.list.d/taler.list} that | ||
791 | looks like this: | ||
792 | |||
793 | @example | ||
794 | deb https://deb.taler.net/apt/debian sid main | ||
795 | @end example | ||
796 | |||
797 | Next, you must import the Taler Systems SA public package signing key | ||
798 | into 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 | ||
807 | You may want to verify the correctness of the Taler Systems key out-of-band. | ||
808 | @end quotation | ||
809 | @end cartouche | ||
810 | |||
811 | Now your system is ready to install the official GNU Taler binary packages | ||
812 | using 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 | |||
825 | To install the Anastasis Gtk+ frontend, you can simply run: | ||
826 | |||
827 | @example | ||
828 | # apt install anastasis-gtk | ||
829 | @end example | ||
830 | |||
831 | To 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 | |||
842 | If you want to install the Anastasis backend-end (which normal users do not | ||
843 | need), you should run: | ||
844 | |||
845 | @example | ||
846 | # apt install -t sid anastasis-httpd | ||
847 | @end example | ||
848 | |||
849 | Note that the latter package does not perform all of the configuration work. | ||
850 | It does setup the user users and the systemd service scripts, but you still | ||
851 | must configure the database backup, HTTP reverse proxy (typically with TLS | ||
852 | certificates), Taler merchant backend for payments, authentication services, | ||
853 | prices and the terms of service. | ||
854 | |||
855 | Sample configuration files for the HTTP reverse proxy can be found in | ||
856 | @code{/etc/anastasis.conf}. | ||
857 | |||
858 | Note that the package does not complete the integration of the backend | ||
859 | with the HTTP reverse proxy (typically with TLS certificates). A | ||
860 | configuration fragment for Nginx or Apache will be placed in | ||
861 | @code{/etc/@{apache,nginx@}/conf-available/anastasis.conf}. | ||
862 | |||
863 | To operate an Anastasis backend with payments, you additionally | ||
864 | need 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 | |||
875 | To install the GNU Taler Ubuntu packages, first ensure that you have | ||
876 | the right Ubuntu distribution. At this time, the packages are built for | ||
877 | Ubuntu 20.04 LTS (Focal Fossa). | ||
878 | |||
879 | A typical @code{/etc/apt/sources.list.d/taler.list} file for this setup | ||
880 | would look like this: | ||
881 | |||
882 | @example | ||
883 | deb https://deb.taler.net/apt/ubuntu/ focal-fossa main | ||
884 | @end example | ||
885 | |||
886 | The last line is crucial, as it adds the GNU Taler packages. | ||
887 | |||
888 | Next, you must import the Taler Systems SA public package signing key | ||
889 | into 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 | ||
898 | You may want to verify the correctness of the Taler Systems key out-of-band. | ||
899 | @end quotation | ||
900 | @end cartouche | ||
901 | |||
902 | Now your system is ready to install the official GNU Taler binary packages | ||
903 | using 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 | |||
916 | To 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 | |||
922 | To 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 | |||
933 | If you want to install the Anastasis backend-end (which normal users do not | ||
934 | need), you should run: | ||
935 | |||
936 | @example | ||
937 | # apt install -t focal-fossa anastasis-httpd | ||
938 | @end example | ||
939 | |||
940 | Note that the latter package does not perform all of the configuration work. | ||
941 | It does setup the user users and the systemd service scripts, but you still | ||
942 | must configure the database backup, HTTP reverse proxy (typically with TLS | ||
943 | certificates), Taler merchant backend for payments, authentication services, | ||
944 | prices and the terms of service. | ||
945 | |||
946 | Sample configuration files for the HTTP reverse proxy can be found in | ||
947 | @code{/etc/anastasis.conf}. | ||
948 | |||
949 | To operate an Anastasis backend with payments, you additionally | ||
950 | need 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 | |||
979 | Details about the contents of the configuration file are describe in | ||
980 | the @code{anastasis.conf(5)} chapter. This chapter only describes the | ||
981 | configuration 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 | |||
994 | In Taler realm, any component obeys to the same pattern to get | ||
995 | configuration values. According to this pattern, once the component has | ||
996 | been installed, the installation deploys default values in | ||
997 | $@{prefix@}/share/taler/config.d/, in .conf files. In order to override | ||
998 | these defaults, the user can write a custom .conf file and either pass | ||
999 | it to the component at execution time, or name it taler.conf and place | ||
1000 | it under $HOME/.config/. | ||
1001 | |||
1002 | A config file is a text file containing sections, and each section | ||
1003 | contains its values. The right format follows: | ||
1004 | |||
1005 | @example | ||
1006 | [section1] | ||
1007 | value1 = string | ||
1008 | value2 = 23 | ||
1009 | |||
1010 | [section2] | ||
1011 | value21 = string | ||
1012 | value22 = /path22 | ||
1013 | @end example | ||
1014 | |||
1015 | Throughout any configuration file, it is possible to use @code{$}-prefixed | ||
1016 | variables, like @code{$VAR}, especially when they represent filesystem | ||
1017 | paths. It is also possible to provide defaults values for those | ||
1018 | variables 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 | |||
1022 | by defining them under a @code{[paths]} section, see example below, | ||
1023 | |||
1024 | @example | ||
1025 | [paths] | ||
1026 | TALER_DEPLOYMENT_SHARED = $@{HOME@}/shared-data | ||
1027 | .. | ||
1028 | [section-x] | ||
1029 | path-x = $@{TALER_DEPLOYMENT_SHARED@}/x | ||
1030 | @end example | ||
1031 | |||
1032 | or by setting them in the environment: | ||
1033 | |||
1034 | @example | ||
1035 | $ export VAR=/x | ||
1036 | @end example | ||
1037 | |||
1038 | The configuration loader will give precedence to variables set under | ||
1039 | @code{[path]}, though. | ||
1040 | |||
1041 | The utility @code{taler-config}, which gets installed along with the | ||
1042 | exchange, serves to get and set configuration values without directly | ||
1043 | editing the .conf. The option @code{-f} is particularly useful to resolve | ||
1044 | pathnames, when they use several levels of @code{$}-expanded variables. See | ||
1045 | @code{taler-config --help}. | ||
1046 | |||
1047 | Note that, in this stage of development, the file | ||
1048 | @code{$HOME/.config/taler.conf} can contain sections for @emph{all} the | ||
1049 | component. For example, both an exchange and a bank can read values from | ||
1050 | it. | ||
1051 | |||
1052 | The repository @code{git://taler.net/deployment} contains examples of | ||
1053 | configuration file used in our demos. See under @code{deployment/config}. | ||
1054 | |||
1055 | @quotation | ||
1056 | |||
1057 | @strong{Note} | ||
1058 | |||
1059 | Expectably, some components will not work just by using default | ||
1060 | values, as their work is often interdependent. For example, a | ||
1061 | merchant 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 | |||
1069 | The tool @code{anastasis-config} can be used to extract or manipulate | ||
1070 | configuration values; however, the configuration use the well-known INI | ||
1071 | file format and can also be edited by hand. | ||
1072 | |||
1073 | Run | ||
1074 | |||
1075 | @example | ||
1076 | $ anastasis-config -s $SECTION | ||
1077 | @end example | ||
1078 | |||
1079 | to list all of the configuration values in section @code{$SECTION}. | ||
1080 | |||
1081 | Run | ||
1082 | |||
1083 | @example | ||
1084 | $ anastasis-config -s $section -o $option | ||
1085 | @end example | ||
1086 | |||
1087 | to extract the respective configuration value for option @code{$option} in | ||
1088 | section @code{$section}. | ||
1089 | |||
1090 | Finally, to change a setting, run | ||
1091 | |||
1092 | @example | ||
1093 | $ anastasis-config -s $section -o $option -V $value | ||
1094 | @end example | ||
1095 | |||
1096 | to set the respective configuration value to @code{$value}. Note that you | ||
1097 | have to manually restart the Taler backend after you change the | ||
1098 | configuration to make the new configuration go into effect. | ||
1099 | |||
1100 | Some default options will use $-variables, such as @code{$DATADIR} within | ||
1101 | their value. To expand the @code{$DATADIR} or other $-variables in the | ||
1102 | configuration, pass the @code{-f} option to @code{anastasis-config}. For example, | ||
1103 | compare: | ||
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 | |||
1112 | While the configuration file is typically located at | ||
1113 | @code{$HOME/.config/taler.conf}, an alternative location can be specified | ||
1114 | to @code{taler-merchant-httpd} and @code{anastasis-config} using the @code{-c} | ||
1115 | option. | ||
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 | |||
1140 | When a user needs to interact with Anastasis, the system first derives some key | ||
1141 | material, but not the master secret, from the user’s @strong{identifier} using | ||
1142 | different HKDFs. These HKDFs are salted using the respective escrow | ||
1143 | provider’s @strong{server salt}, which ensures that the accounts for the same user | ||
1144 | cannot be easily correlated across the various Anastasis servers. | ||
1145 | |||
1146 | Each Anastasis server uses an EdDSA @strong{account key} to identify the account of | ||
1147 | the user. The account private key is derived from the user’s @strong{identifier} using | ||
1148 | a computationally expensive cryptographic hash function. Using an | ||
1149 | expensive hash algorithm is assumed to make it infeasible for a weak adversary to | ||
1150 | determine account keys by brute force (without knowing the user’s identifier). | ||
1151 | However, it is assumed that a strong adversary performing a targeted attack can | ||
1152 | compute the account key pair. | ||
1153 | |||
1154 | The public account key is Crockford base32-encoded in the URI to identify the | ||
1155 | account, and used to sign requests. These signatures are also provided in | ||
1156 | base32-encoding and transmitted using the HTTP header | ||
1157 | @code{Anastasis-Account-Signature}. | ||
1158 | |||
1159 | When confidential data is uploaded to an Anastasis server, the respective | ||
1160 | payload is encrypted using AES-GCM with a symmetric key and initialization | ||
1161 | vector derived from the @strong{identifier} and a high-entropy @strong{nonce}. The | ||
1162 | nonce and the GCM tag are prepended to the ciphertext before being uploaded to | ||
1163 | the Anastasis server. This is done whenever confidential data is stored with | ||
1164 | the server. | ||
1165 | |||
1166 | The @strong{core secret} of the user is (AES) encrypted using a symmetric @strong{master | ||
1167 | key}. 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 | ||
1169 | the user to a @strong{key share}. Combining those key shares (by hashing) allows | ||
1170 | the user to obtain a @strong{policy key}, which can be used to decrypt the @strong{master | ||
1171 | key}. There can be many policies, satisfying any of these will allow the | ||
1172 | user to recover the master key. A @strong{recovery document} contains the | ||
1173 | encrypted @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 | |||
1187 | EdDSA and ECDHE public keys are always points on Curve25519 and represented | ||
1188 | using the standard 256 bit Ed25519 compact format. The binary representation | ||
1189 | is converted to Crockford Base32 when transmitted inside JSON or as part of | ||
1190 | URLs. | ||
1191 | |||
1192 | To start, a user provides their private, unique and unforgettable | ||
1193 | @strong{identifier} as a seed to identify their account. For example, this could | ||
1194 | be a social security number together with their full name. Specifics may | ||
1195 | depend on the cultural context, in this document we will simply refer to this | ||
1196 | information as the @strong{identifier}. | ||
1197 | |||
1198 | This identifier will be first hashed with Argon2, to provide a @strong{kdf_id} | ||
1199 | which will be used to derive other keys later. The Hash must also include the | ||
1200 | respective @strong{server_salt}. This also ensures that the @strong{kdf_id} is different | ||
1201 | on each server. The use of Argon2 and the respective @strong{server_salt} is intended | ||
1202 | to make it difficult to brute-force @strong{kdf_id} values and help protect the user’s | ||
1203 | privacy. Also this ensures that the @strong{kdf_id}s on every server differs. However, | ||
1204 | we do not assume that the @strong{identifier} or the @strong{kdf_id} cannot be | ||
1205 | determined 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 | ||
1207 | likely also be available to other actors. | ||
1208 | |||
1209 | @example | ||
1210 | kdf_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 | |||
1230 | For users to authorize “policy” operations we need an EdDSA key pair. As we | ||
1231 | cannot assure that the corresponding private key is truly secret, such policy | ||
1232 | operations must never be destructive: Should an adversary learn the private | ||
1233 | key, they could access (and with the @strong{kdf_id}, decrypt) the user’s policy (but | ||
1234 | not the core secret), or upload a new version of the | ||
1235 | @strong{encrypted recovery document} (but not delete an existing version). | ||
1236 | |||
1237 | For the generation of the private key we use the @strong{kdf_id} as the entropy source, | ||
1238 | hash it to derive a base secret which will then be processed to fit the | ||
1239 | requirements for EdDSA private keys. From the private key we can then | ||
1240 | generate the corresponding public key. Here, “ver” is used as a salt for the | ||
1241 | HKDF to ensure that the result differs from other cases where we hash | ||
1242 | @strong{kdf_id}. | ||
1243 | |||
1244 | @example | ||
1245 | ver_secret := HKDF(kdf_id, "ver", keysize) | ||
1246 | eddsa_priv := eddsa_d_to_a(ver_secret) | ||
1247 | eddsa_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 | ||
1261 | digest[0] = (digest[0] & 0x7f) | 0x40; | ||
1262 | digest[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 | |||
1274 | For symmetric encryption of data we use AES256-GCM. For this we need a | ||
1275 | symmetric key and an initialization vector (IV). To ensure that the | ||
1276 | symmetric key changes for each encryption operation, we compute the | ||
1277 | key 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 | ||
1294 | avoid 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 | |||
1305 | The keys we have generated are then used to encrypt the @strong{recovery document} and | ||
1306 | the @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 | |||
1319 | Before every encryption a 32-byte nonce is generated. | ||
1320 | From this the symmetric key is computed as described above. | ||
1321 | We use AES256-GCM for the encryption of the @strong{recovery document} and | ||
1322 | the @strong{key_share}. To ensure that the key derivation for the encryption | ||
1323 | of the @strong{recovery document} differs fundamentally from that of an | ||
1324 | individual @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 | ||
1334 | and 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}. | ||
1337 | Nonce 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. | ||
1342 | Here, @strong{i} must be a positive number used to iterate over the various @strong{key shares} used for the various @strong{escrow methods} | ||
1343 | at 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 | ||
1346 | the same number as specified above for @emph{encrypted_key_share_i}. Nonce must contain the string “EKS” plus the according @emph{i}. | ||
1347 | |||
1348 | As 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 | ||
1350 | of the answer to the security question as an additional way to make the key share | ||
1351 | inaccessible to those who do not have the answer: | ||
1352 | |||
1353 | @example | ||
1354 | powh := POW_HASH (qsalt, answer) | ||
1355 | ekss := 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 | |||
1376 | The EdDSA keys are used to sign the data sent from the client to the | ||
1377 | server. Everything the client sends to server is signed. The following | ||
1378 | algorithm is equivalent for @strong{Anastasis-Policy-Signature}. | ||
1379 | |||
1380 | @example | ||
1381 | (anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv) | ||
1382 | ver_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 | |||
1391 | When requesting policy downloads, the client must also provide a signature: | ||
1392 | |||
1393 | @example | ||
1394 | (anastasis-account-signature) := eddsa_sign(version, eddsa_priv) | ||
1395 | ver_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 | |||
1409 | Anastasis considers two main threats against availability. First, the | ||
1410 | Anastasis server operators must be protected against denial-of-service attacks | ||
1411 | where an adversary attempts to exhaust the operator’s resources. The API protects | ||
1412 | against these attacks by allowing operators to set fees for all | ||
1413 | operations. Furthermore, all data stored comes with an expiration logic, so an | ||
1414 | attacker cannot force servers to store data indefinitely. | ||
1415 | |||
1416 | A second availability issue arises from strong adversaries that may be able to | ||
1417 | compute the account keys of some user. While we assume that such an adversary | ||
1418 | cannot successfully authenticate against the truth, the account key does | ||
1419 | inherently enable these adversaries to upload a new policy for the account. | ||
1420 | This cannot be prevented, as the legitimate user must be able to set or change | ||
1421 | a policy using only the account key. To ensure that an adversary cannot | ||
1422 | exploit this, policy uploads first of all never delete existing policies, but | ||
1423 | merely create another version. This way, even if an adversary uploads a | ||
1424 | malicious policy, a user can still retrieve an older version of the policy to | ||
1425 | recover access to their data. This append-only storage for policies still | ||
1426 | leaves a strong adversary with the option of uploading many policies to | ||
1427 | exhaust the Anastasis server’s capacity. We limit this attack by requiring a | ||
1428 | policy upload to include a reference to a @strong{payment identifier} from a payment | ||
1429 | made by the user. Thus, a policy upload requires both knowledge of the | ||
1430 | @strong{identity} and making a payment. This effectively prevents an adversary | ||
1431 | from using the append-only policy storage from exhausting Anastasis server | ||
1432 | capacity. | ||
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 | |||
1486 | Certain response formats are common for all requests. They are documented here | ||
1487 | instead of with each individual request. Furthermore, we note that clients may | ||
1488 | theoretically fail to receive any response. In this case, the client should | ||
1489 | verify that the Internet connection is working properly, and then proceed to | ||
1490 | handle 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 | |||
1497 | Unless specified otherwise, HTTP requests that carry a message body must | ||
1498 | have the content type @code{application/json}. | ||
1499 | |||
1500 | @*Request Headers: | ||
1501 | |||
1502 | @itemize * | ||
1503 | |||
1504 | @item | ||
1505 | Content-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 | ||
1516 | Content-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 | |||
1525 | The request was successful. | ||
1526 | |||
1527 | @item 400 Bad request@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1}: | ||
1528 | |||
1529 | One 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 | |||
1533 | This always indicates some serious internal operational error of the Anastasis | ||
1534 | provider, such as a program bug, database problems, etc., and must not be used for | ||
1535 | client-side problems. When facing an internal server error, clients should | ||
1536 | retry their request after some delay. We recommended initially trying after | ||
1537 | 1s, twice more at randomized times within 1 minute, then the user should be | ||
1538 | informed and another three retries should be scheduled within the next 24h. | ||
1539 | If the error persists, a report should ultimately be made to the auditor, | ||
1540 | although the auditor API for this is not yet specified. However, as internal | ||
1541 | server errors are always reported to the exchange operator, a good operator | ||
1542 | should naturally be able to address them in a timely fashion, especially | ||
1543 | within 24h. | ||
1544 | @end table | ||
1545 | |||
1546 | Unless specified otherwise, all error status codes (4xx and 5xx) have a message | ||
1547 | body with an @ref{29,,ErrorDetail} JSON object. | ||
1548 | |||
1549 | @strong{Details:} | ||
1550 | |||
1551 | @example | ||
1552 | interface 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 | |||
1571 | Anastasis services expose the range of API versions they support. Clients in | ||
1572 | turn have an API version range they support. These version ranges are written | ||
1573 | down in the libtool version format@footnote{https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html}. | ||
1574 | |||
1575 | A protocol version is a positive, non-zero integer. A protocol version range consists of three components: | ||
1576 | |||
1577 | |||
1578 | @enumerate | ||
1579 | |||
1580 | @item | ||
1581 | The @code{current} version. This is the latest version of the protocol supported by the client or service. | ||
1582 | |||
1583 | @item | ||
1584 | The @code{revision} number. This value should usually not be interpreted by the client/server, but serves | ||
1585 | purely as a comment. Each time a service/client for a protocol is updated while supporting the same | ||
1586 | set of protocol versions, the revision should be increased. | ||
1587 | In rare cases, the revision number can be used to work around unintended breakage in deployed | ||
1588 | versions of a service. This is discouraged and should only be used in exceptional situations. | ||
1589 | |||
1590 | @item | ||
1591 | The @code{age} number. This non-zero integer identifies with how many previous protocol versions this | ||
1592 | implementation is compatible. An @code{age} of 0 implies that the implementation only supports | ||
1593 | the @code{current} protocol version. The @code{age} must be less or equal than the @code{current} protocol version. | ||
1594 | @end enumerate | ||
1595 | |||
1596 | To avoid confusion with semantic versions, the protocol version range is written down in the following format: | ||
1597 | |||
1598 | @example | ||
1599 | current[:revision[:age]] | ||
1600 | @end example | ||
1601 | |||
1602 | The angle brackets mark optional components. If either @code{revision} or @code{age} are omitted, they default to 0. | ||
1603 | |||
1604 | Examples: | ||
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 | ||
1630 | Semantic versions@footnote{https://semver.org/} are not a good tool for this job, as we concisely want to express | ||
1631 | that the client/server supports the last @code{n} versions of the protocol. | ||
1632 | Semantic 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 | ||
1638 | A client doesn’t have one single protocol version range. Instead, it has | ||
1639 | a protocol version range for each type of service it talks to. | ||
1640 | @end quotation | ||
1641 | @end cartouche | ||
1642 | |||
1643 | @cartouche | ||
1644 | @quotation Warning | ||
1645 | For privacy reasons, the protocol version range of a client should not be | ||
1646 | sent to the service. Instead, the client should just use the two version ranges | ||
1647 | to 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 | |||
1656 | This 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 | ||
1684 | type Base32 = string; | ||
1685 | @end example | ||
1686 | |||
1687 | Binary 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 | ||
1689 | but also decodes to “V” to make OCR easy. We will still simply use the JSON | ||
1690 | type “base32” and the term “Crockford Base32” in the text to refer to the | ||
1691 | resulting 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 | |||
1698 | Hash codes are strings representing base32 encoding of the respective | ||
1699 | hashed data. See @ref{2d,,base32}. | ||
1700 | |||
1701 | @example | ||
1702 | // 64-byte hash code. | ||
1703 | type HashCode = string; | ||
1704 | @end example | ||
1705 | |||
1706 | @example | ||
1707 | // 32-byte hash code. | ||
1708 | type 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 | |||
1716 | Large numbers such as 256 bit keys, are transmitted as other binary data in | ||
1717 | Crockford Base32 encoding. | ||
1718 | |||
1719 | @node Timestamps,Integers,Large numbers,Common encodings | ||
1720 | @anchor{rest timestamps}@anchor{31} | ||
1721 | @subsubsection Timestamps | ||
1722 | |||
1723 | |||
1724 | Timestamps are represented by the following structure: | ||
1725 | |||
1726 | @example | ||
1727 | interface 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 | ||
1736 | interface 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. | ||
1750 | type 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. | ||
1760 | type 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`. | ||
1772 | type 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`. | ||
1779 | type 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). | ||
1790 | type 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 | ||
1799 | type Amount = string; | ||
1800 | @end example | ||
1801 | |||
1802 | Amounts of currency are serialized as a string of the format | ||
1803 | @code{<Currency>:<DecimalAmount>}. Taler treats monetary amounts as | ||
1804 | fixed-precision numbers, with 8 decimal places. Unlike floating point numbers, | ||
1805 | this allows accurate representation of monetary amounts. | ||
1806 | |||
1807 | The following constrains apply for a valid amount: | ||
1808 | |||
1809 | |||
1810 | @enumerate | ||
1811 | |||
1812 | @item | ||
1813 | The @code{<Currency>} part must be at most 11 characters long and may only consist | ||
1814 | of ASCII letters (@code{a-zA-Z}). | ||
1815 | |||
1816 | @item | ||
1817 | The integer part of @code{<DecimalAmount>} may be at most 2^52. | ||
1818 | |||
1819 | @item | ||
1820 | The 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 | |||
1829 | An amount that is prefixed with a @code{+} or @code{-} character is also used in certain contexts. | ||
1830 | When 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 | |||
1837 | In signed messages, time is represented using 64-bit big-endian values, | ||
1838 | denoting microseconds since the UNIX Epoch. @code{UINT64_MAX} represents “never”. | ||
1839 | |||
1840 | @example | ||
1841 | struct GNUNET_TIME_Absolute @{ | ||
1842 | uint64_t timestamp_us; | ||
1843 | @}; | ||
1844 | struct 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 | |||
1854 | All elliptic curve operations are on Curve25519. Public and private keys are | ||
1855 | thus 32 bytes, and signatures 64 bytes. For hashing, including HKDFs, Taler | ||
1856 | uses 512-bit hash codes (64 bytes). | ||
1857 | |||
1858 | @example | ||
1859 | struct GNUNET_HashCode @{ | ||
1860 | uint8_t hash[64]; // usually SHA-512 | ||
1861 | @}; | ||
1862 | @end example | ||
1863 | @anchor{rest taler-ecdhephemeralpublickeyp}@anchor{3c} | ||
1864 | @example | ||
1865 | struct TALER_EcdhEphemeralPublicKeyP @{ | ||
1866 | uint8_t ecdh_pub[32]; | ||
1867 | @}; | ||
1868 | @end example | ||
1869 | |||
1870 | @example | ||
1871 | struct 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 | |||
1881 | Any piece of signed data, complies to the abstract data structure given below. | ||
1882 | |||
1883 | @example | ||
1884 | struct Data @{ | ||
1885 | struct GNUNET_CRYPTO_EccSignaturePurpose purpose; | ||
1886 | type1_t payload1; | ||
1887 | type2_t payload2; | ||
1888 | ... | ||
1889 | @}; | ||
1890 | |||
1891 | /*From gnunet_crypto_lib.h*/ | ||
1892 | struct 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 | |||
1920 | Obtain the configuration details of the escrow provider. | ||
1921 | |||
1922 | @strong{Response:} | ||
1923 | |||
1924 | Returns an @ref{43,,EscrowConfigurationResponse}. | ||
1925 | @anchor{rest escrowconfigurationresponse}@anchor{43} | ||
1926 | @example | ||
1927 | interface 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 | ||
1969 | interface 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 | |||
1988 | Obtain the terms of service provided by the escrow provider. | ||
1989 | |||
1990 | @strong{Response:} | ||
1991 | |||
1992 | Returns the terms of service of the provider, in the best language | ||
1993 | and 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 | |||
1999 | Obtain the privacy policy of the service provided by the escrow provider. | ||
2000 | |||
2001 | @strong{Response:} | ||
2002 | |||
2003 | Returns the privacy policy of the provider, in the best language | ||
2004 | and 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 | |||
2012 | This API is used by the Anastasis client to deposit or request encrypted | ||
2013 | recovery documents with the escrow provider. Generally, a client will deposit | ||
2014 | the same encrypted recovery document with each escrow provider, but provide | ||
2015 | a different truth to each escrow provider. | ||
2016 | |||
2017 | Operations by the client are identified and authorized by @code{$ACCOUNT_PUB}, which | ||
2018 | should be kept secret from third parties. @code{$ACCOUNT_PUB} should be an account | ||
2019 | public key using the Crockford base32-encoding. | ||
2020 | |||
2021 | In 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 | |||
2026 | Get the customer’s encrypted recovery document. If @code{version} | ||
2027 | is 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 | ||
2030 | an AES-GCM tag and continue with the ciphertext. Once decrypted, the | ||
2031 | plaintext is expected to contain: | ||
2032 | |||
2033 | |||
2034 | @itemize * | ||
2035 | |||
2036 | @item | ||
2037 | the escrow policy | ||
2038 | |||
2039 | @item | ||
2040 | the separately encrypted master public key | ||
2041 | @end itemize | ||
2042 | |||
2043 | Note that the key shares required to decrypt the master public key are | ||
2044 | not included, as for this the client needs to obtain authorization. | ||
2045 | The policy does provide sufficient information for the client to determine | ||
2046 | how to authorize requests for @strong{truth}. | ||
2047 | |||
2048 | The client MAY provide an @code{If-None-Match} header with an Etag. | ||
2049 | In that case, the server MUST additionally respond with an @code{304} status | ||
2050 | code 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 | |||
2059 | The 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 | |||
2063 | The 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 | |||
2067 | The @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 | |||
2071 | The account’s balance is too low for the specified operation. | ||
2072 | See 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 | |||
2076 | The 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 | |||
2080 | The 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. | ||
2084 | If the client specified a version number in the header of the request, the server must return that version. If the client | ||
2085 | did 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. | ||
2090 | The 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 | |||
2098 | Upload a new version of the customer’s encrypted recovery document. | ||
2099 | While the document’s structure is described in JSON below, the upload | ||
2100 | should just be the bytestream of the raw data (i.e. 32-byte nonce followed | ||
2101 | by 16-byte tag followed by the encrypted document). | ||
2102 | If the request has been seen before, the server should do nothing, and otherwise store the new version. | ||
2103 | The body must begin with a nonce, an AES-GCM tag and continue with the ciphertext. The format | ||
2104 | is the same as specified for the response of the GET method. The | ||
2105 | Anastasis server cannot fully validate the format, but MAY impose | ||
2106 | minimum 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 | ||
2116 | store the recovery document? Defaults to 0 (that is, do | ||
2117 | not extend / prolong existing storage contract). | ||
2118 | The server will respond with a @code{402 Payment required}, but only | ||
2119 | if the rest of the request is well-formed (account | ||
2120 | signature must match). Clients that do not actually | ||
2121 | intend to make a new upload but that only want to pay | ||
2122 | may attempt to upload the latest backup again, as this | ||
2123 | option will be checked before the @code{304 Not modified} | ||
2124 | case. | ||
2125 | |||
2126 | @item | ||
2127 | @code{timeout_ms=NUMBER} – @emph{Optional.} If specified, the Anastasis server will | ||
2128 | wait up to @code{timeout_ms} milliseconds for completion of the payment before | ||
2129 | sending the HTTP response. A client must never rely on this behavior, as the | ||
2130 | backend 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. | ||
2135 | The client SHOULD also set the @code{Expect: 100-Continue} header and wait for @code{100 continue} | ||
2136 | before uploading the body. The server MUST | ||
2137 | use the Etag to check whether it already knows the encrypted recovery document that is about to be uploaded. | ||
2138 | The server MUST refuse the upload with a @code{304} status code if the Etag matches | ||
2139 | the 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 | |||
2152 | The encrypted recovery document was accepted and stored. @code{Anastasis-Version} and @code{Anastasis-UUID} headers | ||
2153 | indicate 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 | |||
2157 | The same encrypted recovery document was previously accepted and stored. @code{Anastasis-Version} header | ||
2158 | indicates 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 | |||
2162 | The @code{$ACCOUNT_PUB} is not an EdDSA public key or mandatory headers are missing. | ||
2163 | The 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 | |||
2167 | The account’s balance is too low for the specified operation. | ||
2168 | See the Taler payment protocol specification for how to pay. | ||
2169 | The 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 | |||
2173 | The 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 | |||
2177 | The 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 | ||
2183 | interface 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 | ||
2201 | interface 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 | ||
2219 | interface 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 | ||
2251 | interface 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 | |||
2273 | This API is used by the Anastasis client to deposit @strong{truth} or request a (encrypted) @strong{key share} with | ||
2274 | the escrow provider. | ||
2275 | |||
2276 | An @strong{escrow method} specifies an Anastasis provider and how the user should | ||
2277 | authorize themself. The @strong{truth} API allows the user to provide the | ||
2278 | (encrypted) key share to the respective escrow provider, as well as auxiliary | ||
2279 | data required for such a respective escrow method. | ||
2280 | |||
2281 | An Anastasis-server may store truth for free for a certain time period, or | ||
2282 | charge per truth operation using GNU Taler. | ||
2283 | |||
2284 | @anchor{rest post--truth-$UUID}@anchor{53} | ||
2285 | @deffn {HTTP Post} POST /truth/$UUID | ||
2286 | |||
2287 | Upload a @ref{54,,TruthUploadRequest}-Object according to the policy the client created before (see @ref{4e,,RecoveryDocument}). | ||
2288 | If 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 | ||
2298 | wait up to @code{timeout_ms} milliseconds for completion of the payment before | ||
2299 | sending the HTTP response. A client must never rely on this behavior, as the | ||
2300 | backend 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 | |||
2311 | Truth stored successfully. | ||
2312 | |||
2313 | @item 304 Not modified@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5}: | ||
2314 | |||
2315 | The same truth was previously accepted and stored under this UUID. The | ||
2316 | Anastasis server must still update the expiration time for the truth when returning | ||
2317 | this response code. | ||
2318 | |||
2319 | @item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}: | ||
2320 | |||
2321 | This server requires payment to store truth per item. | ||
2322 | See the Taler payment protocol specification for how to pay. | ||
2323 | The 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 | |||
2327 | The server already has some truth stored under this UUID. The client should check that it | ||
2328 | is 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 | |||
2332 | The selected authentication method is not supported on this provider. | ||
2333 | @end table | ||
2334 | |||
2335 | @strong{Details:} | ||
2336 | @anchor{rest truthuploadrequest}@anchor{54} | ||
2337 | @example | ||
2338 | interface 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 | |||
2376 | Get the stored encrypted key share. If @code{$H_RESPONSE} is specified by the client, the server checks | ||
2377 | if @code{$H_RESPONSE} matches the expected response specified before within the @ref{54,,TruthUploadRequest} (see @code{encrypted_truth}). | ||
2378 | Also, the user has to provide the correct @emph{truth_encryption_key} with every get request (see below). | ||
2379 | When @code{$H_RESPONSE} is correct, the server responds with the encrypted key share. | ||
2380 | The 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 | |||
2393 | The escrow provider will respond out-of-band (i.e. SMS). | ||
2394 | The body may contain human-readable instructions on next steps. | ||
2395 | |||
2396 | @item >>208 Already Reported<<: | ||
2397 | |||
2398 | An authentication challenge was recently send, client should | ||
2399 | simply 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 | |||
2403 | The provider redirects for authentication (i.e. video identification/WebRTC). | ||
2404 | If the client is not a browser, it should launch a browser at the URL | ||
2405 | given in the @code{Location} header and allow the user to re-try the operation | ||
2406 | after successful authorization. | ||
2407 | |||
2408 | @item 402 Payment required@footnote{http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3}: | ||
2409 | |||
2410 | The service requires payment for access to truth. | ||
2411 | See the Taler payment protocol specification for how to pay. | ||
2412 | The 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 | |||
2416 | The 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 | |||
2420 | The 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 | |||
2424 | The server has not (recently) issued a challenge under the given UUID, | ||
2425 | but 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 | |||
2429 | The decrypted @code{truth} does not match the expectations of the authentication | ||
2430 | backend, i.e. a phone number for sending an SMS is not a number, or | ||
2431 | an 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 | |||
2435 | Server 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 | ||
2439 | the according @ref{4f,,EscrowMethod}. The server needs this key to get the info out of @ref{54,,TruthUploadRequest} needed to verify the @code{$RESPONSE}. | ||
2440 | |||
2441 | @strong{Details:} | ||
2442 | @anchor{rest encryptedkeyshare}@anchor{56} | ||
2443 | @example | ||
2444 | interface 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 | ||
2468 | interface 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 | |||
2503 | This section describes the Anastasis Reducer API which is used by client applications | ||
2504 | to store or load the different states the client application can have. | ||
2505 | The reducer takes a @ref{5a,,state} in JSON syntax and returns the new state in JSON syntax. | ||
2506 | |||
2507 | For 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 | |||
2519 | The new state depends on the previous one and on the transition @ref{5b,,action} with its | ||
2520 | arguments 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 | |||
2528 | The new state returned by the reducer with the state and transition argument defined | ||
2529 | above 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 | |||
2584 | Overall, 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 | |||
2597 | this 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 | |||
2606 | so 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 | |||
2615 | so that we can determine appropriate attributes, currencies and Anastasis | ||
2616 | providers. | ||
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 | |||
2625 | attributes. | ||
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 | |||
2634 | during 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 | |||
2649 | with 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 | |||
2664 | the 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 | |||
2673 | proceed 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 | |||
2687 | State names: | ||
2688 | |||
2689 | @quotation | ||
2690 | |||
2691 | |||
2692 | @itemize - | ||
2693 | |||
2694 | @item | ||
2695 | In SELECTING-states, the user has to choose one value out of a predefined set of values (for example a continent out of a set of continents). | ||
2696 | |||
2697 | @item | ||
2698 | In COLLECTING-states, the user has to give certain values. | ||
2699 | |||
2700 | @item | ||
2701 | In EDITING-states, the user is free to choose which values he wants to give. | ||
2702 | |||
2703 | @item | ||
2704 | In REVEIWING-states, the user may make a few choices, but primarily is expected to affirm something. | ||
2705 | |||
2706 | @item | ||
2707 | in PAYING-states, the user must make a payment. | ||
2708 | |||
2709 | @item | ||
2710 | in 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 | |||
2729 | The illustration above shows the different states the reducer can have during a backup | ||
2730 | process. | ||
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 | |||
2747 | The illustration above shows the different states the reducer can have during a recovery | ||
2748 | process. | ||
2749 | |||
2750 | @node Reducer transitions,,Recovery Reducer,Reducer API | ||
2751 | @anchor{reducer reducer-transitions}@anchor{5f} | ||
2752 | @subsection Reducer transitions | ||
2753 | |||
2754 | |||
2755 | In the following, the individual transitions will be specified in more detail. | ||
2756 | Note that we only show fields added by the reducer, typically the previous | ||
2757 | state 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 | |||
2772 | The 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 | |||
2798 | Here, “continents” is an array of English strings with the names of the | ||
2799 | continents which contain countries for which Anastasis could function (based | ||
2800 | on having providers that are known to operate and rules being provided for | ||
2801 | user attributes from those countries). | ||
2802 | |||
2803 | For internationalization, another field @code{continents_i18n} may be present. | ||
2804 | This field would be a map of language names to arrays of translated | ||
2805 | continent 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 | |||
2828 | Translations 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 | |||
2837 | Here the user specifies the continent they live on. Arguments (example): | ||
2838 | |||
2839 | @example | ||
2840 | @{ | ||
2841 | "continent": "Europe" | ||
2842 | @} | ||
2843 | @end example | ||
2844 | |||
2845 | The continent must be given using the English name from the @code{continents} array. | ||
2846 | Using a translated continent name is invalid and may result in failure. | ||
2847 | |||
2848 | The reducer returns an updated state with a list of countries to choose from, | ||
2849 | for 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 | |||
2887 | Here @code{countries} is an array of countries on the @code{selected_continent}. For | ||
2888 | each 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 | ||
2890 | information is redundant and will always match @code{selected_continent}. The | ||
2891 | @code{name} is the name of the country in English, internationalizations of the | ||
2892 | name may be provided in @code{name_i18n}. The @code{currency} is @strong{an} official | ||
2893 | currency of the country, if a country has multiple currencies, it may appear | ||
2894 | multiple times in the list. In this case, the user should select the entry | ||
2895 | with the currency they intend to pay with. It is also possible for users | ||
2896 | to select a currency that does not match their country, but user interfaces | ||
2897 | should by default try to use currencies that match the user’s residence. | ||
2898 | |||
2899 | @strong{select_country:} | ||
2900 | |||
2901 | Selects the country (via the country code) and specifies the currency. | ||
2902 | The latter is needed as some countries have more than one currency, | ||
2903 | and some use-cases may also involve users insisting on paying with | ||
2904 | foreign currency. | ||
2905 | |||
2906 | Arguments (example): | ||
2907 | |||
2908 | @example | ||
2909 | @{ | ||
2910 | "country_code": "de", | ||
2911 | "currency": "EUR" | ||
2912 | @} | ||
2913 | @end example | ||
2914 | |||
2915 | The @code{country_code} must be an ISO 3166-1 alpha-2 country code from | ||
2916 | the array of @code{countries} of the reducer’s state. The @code{currency} | ||
2917 | field must be a valid currency accepted by the Taler payment system. | ||
2918 | |||
2919 | The reducer returns a new state with the list of attributes the | ||
2920 | user is expected to provide, as well as possible authentication | ||
2921 | providers 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 | |||
3024 | The array of @code{required_attributes} contains attributes about the user | ||
3025 | that 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 | ||
3034 | supported. | ||
3035 | |||
3036 | @item | ||
3037 | @strong{name}: The name of the attribute, this is the key under which the | ||
3038 | attribute 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. | ||
3042 | Translated descriptions may be provided under @strong{label_i18n}. | ||
3043 | |||
3044 | @item | ||
3045 | @strong{uuid}: A UUID that uniquely identifies identical attributes across | ||
3046 | different countries. Useful to preserve values should the user enter | ||
3047 | some attributes, and then switch to another country. Note that | ||
3048 | attributes must not be preserved if they merely have the same @strong{name}, | ||
3049 | only 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 | ||
3053 | the attribute entry in user interfaces where named widgets are | ||
3054 | supported. | ||
3055 | |||
3056 | @item | ||
3057 | @strong{validation-regex}: An optional extended POSIX regular expression | ||
3058 | that is to be used to validate (string) inputs to ensure they are | ||
3059 | well-formed. | ||
3060 | |||
3061 | @item | ||
3062 | @strong{validation-logic}: Optional name of a function that should be called | ||
3063 | to validate the input. If the function is not known to the particular | ||
3064 | client, the respective validation can be skipped (at the expense of | ||
3065 | typos by users not being detected, possibly rendering secrets | ||
3066 | irrecoverable). | ||
3067 | |||
3068 | @item | ||
3069 | @strong{optional}: Optional boolean field that, if @code{true}, indicates that | ||
3070 | this attribute is not actually required but optional and users MAY leave | ||
3071 | it blank in case they do not have the requested information. Used for | ||
3072 | common fields that apply to some large part of the population but are | ||
3073 | not sufficiently universal to be actually required. | ||
3074 | @end itemize | ||
3075 | @end quotation | ||
3076 | |||
3077 | The authentication providers are listed under a key that is the | ||
3078 | base URL of the service. For each provider, the following | ||
3079 | information 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 | ||
3091 | provider. Includes the @strong{type} of the authentication method | ||
3092 | and the @strong{usage_fee} (how much the user must pay for authorization | ||
3093 | using this method during recovery). | ||
3094 | |||
3095 | @item | ||
3096 | @strong{annual_fee}: Fee the provider charges to store the recovery | ||
3097 | policy 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 | ||
3104 | case a key share or recovery document cannot be recovered due to | ||
3105 | provider failures. | ||
3106 | |||
3107 | @item | ||
3108 | @strong{currency}: Currency in which the provider wants to be paid, | ||
3109 | will match all of the fees. | ||
3110 | |||
3111 | @item | ||
3112 | @strong{storage_limit_in_megabytes}: Maximum size of an upload (for | ||
3113 | both 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 | ||
3120 | user’s identity at this provider. Should be unique per provider, | ||
3121 | and must never change for a given provider. The salt is | ||
3122 | base32 encoded. | ||
3123 | @end itemize | ||
3124 | @end quotation | ||
3125 | |||
3126 | If 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 | ||
3135 | we 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 | |||
3144 | This operation can be performed in state @code{USER_ATTRIBUTES_COLLECTING}. It | ||
3145 | adds one or more Anastasis providers to the list of providers the reducer | ||
3146 | should henceforth consider. Note that removing providers is not possible at | ||
3147 | this time. | ||
3148 | |||
3149 | Here, the client must provide an array with the base URLs of the | ||
3150 | providers to add, for example: | ||
3151 | |||
3152 | @example | ||
3153 | @{ | ||
3154 | "urls": [ | ||
3155 | "http://localhost:8888/", | ||
3156 | "http://localhost:8089/" | ||
3157 | ] | ||
3158 | @} | ||
3159 | @end example | ||
3160 | |||
3161 | Note that existing providers will remain in the state. The following is an | ||
3162 | example for an expected new state where the service on port 8089 is | ||
3163 | unreachable, the service on port 8088 was previously known, and service on | ||
3164 | port 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 | |||
3218 | This transition provides the user’s personal attributes. The specific set of | ||
3219 | attributes required depends on the country of residence of the user. Some | ||
3220 | attributes 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 | ||
3222 | arguments 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 | |||
3235 | Note that at this stage, the state machines between backup and | ||
3236 | recovery diverge and the @code{recovery_state} will begin to look | ||
3237 | very different from the @code{backup_state}. | ||
3238 | |||
3239 | For backups, if all required attributes are present, the reducer will | ||
3240 | transition to an @code{AUTHENTICATIONS_EDITING} state with the attributes added | ||
3241 | to 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 | |||
3255 | If required attributes are missing, do not match the required regular | ||
3256 | expression, or fail the custom validation logic, the reducer SHOULD transition | ||
3257 | to an error state indicating what was wrong about the input. A reducer that | ||
3258 | does not support some specific validation logic MAY accept the invalid input | ||
3259 | and proceed anyway. The error state will include a Taler error code that | ||
3260 | is 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 | |||
3271 | Clients may safely repeat this transition to validate the user’s inputs | ||
3272 | until they satisfy all of the constraints. This way, the user interface | ||
3273 | does not have to perform the input validation directly. | ||
3274 | |||
3275 | @strong{add_authentication}: | ||
3276 | |||
3277 | This transition adds an authentication method. The method must be supported | ||
3278 | by one or more providers that are included in the current state. Adding an | ||
3279 | authentication method requires specifying the @code{type} and @code{instructions} to | ||
3280 | be given to the user. The @code{challenge} is encrypted and stored at the | ||
3281 | Anastasis 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), | ||
3283 | an e-mail address (to send a PIN code to) or the answer to a security | ||
3284 | question. Note that these challenge values will still be encrypted (and | ||
3285 | possibly hashed) before being given to the Anastasis providers. | ||
3286 | |||
3287 | Note that the @code{challenge} must be given in Crockford Base32 encoding, as it | ||
3288 | MAY include binary data (such as a photograph of the user). In the latter | ||
3289 | case, the optional @code{mime_type} field must be provided to give the MIME type | ||
3290 | of 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 | |||
3304 | If the information provided is valid, the reducer will add the new | ||
3305 | authentication 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 | |||
3328 | This transition can be used to remove an authentication method from the | ||
3329 | array of authentication methods. It simply requires the index of the | ||
3330 | authentication method to remove. Note that the array is 0-indexed: | ||
3331 | |||
3332 | @example | ||
3333 | @{ | ||
3334 | "authentication_method": 1 | ||
3335 | @} | ||
3336 | @end example | ||
3337 | |||
3338 | Assuming we begin with the state from the example above, this would | ||
3339 | remove the @code{email} authentication method, resulting in the following | ||
3340 | response: | ||
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 | |||
3356 | If the index is invalid, the reducer will instead | ||
3357 | transition into an @code{ERROR} state. | ||
3358 | |||
3359 | @strong{next} (from @code{AUTHENTICATIONS_EDITING}): | ||
3360 | |||
3361 | This transition confirms that the user has finished adding (or removing) | ||
3362 | authentication methods, and that the system should now automatically compute | ||
3363 | a set of reasonable recovery policies. | ||
3364 | |||
3365 | This transition does not take any mandatory arguments. Optional arguments can | ||
3366 | be provided to upload the recovery document only to a specific subset of the | ||
3367 | providers: | ||
3368 | |||
3369 | @example | ||
3370 | @{ | ||
3371 | "providers": [ | ||
3372 | "http://localhost:8088/", | ||
3373 | "http://localhost:8089/" | ||
3374 | ] | ||
3375 | @} | ||
3376 | @end example | ||
3377 | |||
3378 | The resulting state provides the suggested recovery policies in a way suitable | ||
3379 | for 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 | |||
3425 | For each recovery policy, the state includes the specific details of which | ||
3426 | authentication @code{methods} must be solved to recovery the secret using this | ||
3427 | policy. The @code{methods} array specifies the index of the | ||
3428 | @code{authentication_method} in the @code{authentication_methods} array, as well as | ||
3429 | the provider that was selected to supervise this authentication. | ||
3430 | |||
3431 | If 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 | |||
3436 | Using this transition, the user can add an additional recovery policy to the | ||
3437 | state. The argument format is the same that is used in the existing state. | ||
3438 | An 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 | |||
3455 | Note that the specified providers must already be in the | ||
3456 | @code{authentication_providers} of the state. You cannot add new providers at | ||
3457 | this stage. The reducer will simply attempt to append the suggested policy to | ||
3458 | the “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 | |||
3516 | If the new policy is invalid, for example because it adds an unknown | ||
3517 | authentication method, or the selected provider does not support the type of | ||
3518 | authentication, the reducer will transition into an @code{ERROR} state instead of | ||
3519 | adding the new policy. | ||
3520 | |||
3521 | @strong{update_policy}: | ||
3522 | |||
3523 | Using this transition, the user can modify an existing recovery policy | ||
3524 | in the state. | ||
3525 | The argument format is the same that is used in @strong{add_policy}, | ||
3526 | except there is an additional key @code{policy_index} which | ||
3527 | identifies the policy to modify. | ||
3528 | An 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 | |||
3546 | If the new policy is invalid, for example because it adds an unknown | ||
3547 | authentication method, or the selected provider does not support the type of | ||
3548 | authentication, the reducer will transition into an @code{ERROR} state instead of | ||
3549 | modifying the policy. | ||
3550 | |||
3551 | @strong{delete_policy:} | ||
3552 | |||
3553 | This transition allows the deletion of a recovery policy. The argument | ||
3554 | simply specifies the index of the policy to delete, for example: | ||
3555 | |||
3556 | @example | ||
3557 | @{ | ||
3558 | "policy_index": 3 | ||
3559 | @} | ||
3560 | @end example | ||
3561 | |||
3562 | Given as input the state from the example above, the expected new state would | ||
3563 | be: | ||
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 | |||
3609 | If the index given is invalid, the reducer will transition into an @code{ERROR} state | ||
3610 | instead of deleting a policy. | ||
3611 | |||
3612 | @strong{delete_challenge:} | ||
3613 | |||
3614 | This transition allows the deletion of an individual | ||
3615 | challenge from a recovery policy. The argument | ||
3616 | simply specifies the index of the policy and challenge | ||
3617 | to delete, for example: | ||
3618 | |||
3619 | @example | ||
3620 | @{ | ||
3621 | "policy_index": 1, | ||
3622 | "challenge_index" : 1 | ||
3623 | @} | ||
3624 | @end example | ||
3625 | |||
3626 | Given as input the state from the example above, the expected new state would | ||
3627 | be: | ||
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 | |||
3669 | If the index given is invalid, the reducer will transition into an @code{ERROR} state | ||
3670 | instead of deleting a challenge. | ||
3671 | |||
3672 | @strong{next} (from @code{POLICIES_REVIEWING}): | ||
3673 | |||
3674 | Using this transition, the user confirms that the policies in the current | ||
3675 | state are acceptable. The transition does not take any arguments. | ||
3676 | |||
3677 | The 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 | |||
3687 | Here, @code{upload_fees} is an array of applicable upload fees for the | ||
3688 | given policy expiration time. This is an array because fees could | ||
3689 | be in different currencies. The final cost may be lower if the | ||
3690 | user already paid for some of the time. | ||
3691 | |||
3692 | If the array of @code{policies} is currently empty, the reducer will transition | ||
3693 | into an @code{ERROR} state instead of allowing the user to continue. | ||
3694 | |||
3695 | @strong{enter_secret:} | ||
3696 | |||
3697 | This transition provides the reducer with the actual core @code{secret} of the user | ||
3698 | that Anastasis is supposed to backup (and possibly recover). The argument is | ||
3699 | simply the Crockford-Base32 encoded @code{value} together with its @code{mime} type, or a @code{text} field with a human-readable secret text. | ||
3700 | For 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 | |||
3712 | If the application is unaware of the format, it set the @code{mime} field to @code{null}. | ||
3713 | The @code{expiration} field is optional. | ||
3714 | |||
3715 | The reducer remains in the @code{SECRET_EDITING} state, but now the secret and | ||
3716 | updated expiration time are part of the state and the cost calculations will | ||
3717 | be 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 | |||
3733 | This transition removes the core secret from the state. It is simply a | ||
3734 | convenience function to undo @code{enter_secret} without providing a new value | ||
3735 | immediately. The transition takes no arguments. The resuting state will no | ||
3736 | longer 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 | |||
3741 | This transition provides the reducer with a name for the core @code{secret} of the user. This name will be given to the user as a hint when seleting a recovery policy document during recovery, prior to satisfying any of the challenges. The argument simply contains the name for the secret. | ||
3742 | Applications that have built-in support for Anastasis MUST prefix the | ||
3743 | secret name with an underscore and an application-specific identifier | ||
3744 | registered in GANA so that they can use recognize their own backups. | ||
3745 | An example argument would be: | ||
3746 | |||
3747 | @example | ||
3748 | @{ | ||
3749 | "name": "_TALERWALLET_MyPinePhone", | ||
3750 | @} | ||
3751 | @end example | ||
3752 | |||
3753 | Here, @code{MyPinePhone} might be chosen by the user to identify the | ||
3754 | device that was being backed up. | ||
3755 | |||
3756 | The reducer remains in the @code{SECRET_EDITING} state, but now the | ||
3757 | secret name is updated: | ||
3758 | |||
3759 | @example | ||
3760 | @{ | ||
3761 | "secret_name" : "_TALERWALLET_MyPinePhone" | ||
3762 | @} | ||
3763 | @end example | ||
3764 | |||
3765 | @strong{update_expiration:} | ||
3766 | |||
3767 | This transition asks the reducer to change the desired expiration time | ||
3768 | and to update the associated cost. For example: | ||
3769 | |||
3770 | @example | ||
3771 | @{ | ||
3772 | "expiration" : @{ "t_ms" : 1245362362 @} | ||
3773 | @} | ||
3774 | @end example | ||
3775 | |||
3776 | The reducer remains in the @code{SECRET_EDITING} state, but the | ||
3777 | expiration 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 | |||
3789 | Using this transition, the user confirms that the secret and expiration | ||
3790 | settings in the current state are acceptable. The transition does not take any | ||
3791 | arguments. | ||
3792 | |||
3793 | If the secret is currently empty, the reducer will transition into an | ||
3794 | @code{ERROR} state instead of allowing the user to continue. | ||
3795 | |||
3796 | After adding a secret, the reducer may transition into different states | ||
3797 | depending 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 | ||
3799 | should be careful when persisting the resulting state, as the @code{core_secret} | ||
3800 | is not protected in the @code{PAYING} states. The @code{PAYING} states only differ | ||
3801 | in terms of what the payments are for (key shares or the recovery document), | ||
3802 | in all cases the state simply includes an array of Taler URIs that refer to | ||
3803 | payments that need to be made with the Taler wallet. | ||
3804 | |||
3805 | If 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 | ||
3807 | additional safety measure. | ||
3808 | |||
3809 | Example 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 | |||
3843 | This transition suggests to the reducer that a payment may have been made or | ||
3844 | is immanent, and that the reducer should check with the Anastasis service | ||
3845 | provider to see if the operation is now possible. The operation takes one | ||
3846 | optional argument, which is a @code{timeout} value that specifies how long the | ||
3847 | reducer may wait (in long polling) for the payment to complete: | ||
3848 | |||
3849 | @example | ||
3850 | @{ | ||
3851 | "timeout": @{ "d_ms" : 5000 @}, | ||
3852 | @} | ||
3853 | @end example | ||
3854 | |||
3855 | The specified timeout is passed on to the Anastasis service provider(s), which | ||
3856 | will wait this long before giving up. If no timeout is given, the check is | ||
3857 | done as quickly as possible without additional delays. The reducer will continue | ||
3858 | to 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 | ||
3860 | finished), or into an @code{ERROR} state in case there was an irrecoverable error, | ||
3861 | indicating the specific provider and how it failed. An example for this | ||
3862 | final 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 | |||
3873 | Here, 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 | |||
3891 | In the above example, 52 would thus imply that the Anastasis provider failed to | ||
3892 | store 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 | |||
3901 | This transition provides the user’s personal attributes. The specific set of | ||
3902 | attributes required depends on the country of residence of the user. Some | ||
3903 | attributes 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 | ||
3905 | arguments are identical to the @strong{enter_user_attributes} transition from | ||
3906 | the 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 | |||
3919 | However, in contrast to the backup process, the reducer will attempt to | ||
3920 | retrieve the latest recovery document from all known providers for the | ||
3921 | selected currency given the above inputs. If a recovery document was found | ||
3922 | by any provider, the reducer will attempt to load it and transition to | ||
3923 | a 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 | |||
3962 | The @code{recovery_document} is an internal representation of the recovery | ||
3963 | information and of no concern to the user interface. The pertinent information | ||
3964 | is in the @code{recovery_information}. Here, the @code{challenges} array is a list | ||
3965 | of possible challenges the user could attempt to solve next, while @code{policies} | ||
3966 | is an array of policies, with each policy being an array of challenges. | ||
3967 | Satisfying all of the challenges of one of the policies will enable the secret | ||
3968 | to be recovered. The @code{provider_url} from where the recovery document was | ||
3969 | obtained and its @code{version} are also provided. Each challenge comes with | ||
3970 | four 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 | ||
3979 | UUIDs in the policies array refer to, but also this UUID may be | ||
3980 | included in messages sent to the user. They allow the user to | ||
3981 | distinguish different PIN/TANs should say the same phone number be | ||
3982 | used for SMS-authentication with different providers. | ||
3983 | |||
3984 | @item | ||
3985 | @strong{cost}: This is the amount the Anastasis provider will charge | ||
3986 | to 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 | ||
3993 | to allow the user to satisfy the challenge. It typically includes | ||
3994 | an abbreviated form of the contact information or the security | ||
3995 | question. Details depend on @code{type}. | ||
3996 | @end itemize | ||
3997 | @end quotation | ||
3998 | |||
3999 | If a recovery document was not found, either the user never performed | ||
4000 | a backup, entered incorrect attributes, or used a provider not yet in | ||
4001 | the list of Anastasis providers. Hence, the user must now either | ||
4002 | select a different provider, or go @code{back} and update the identity | ||
4003 | attributes. In the case a recovery document was not found, the | ||
4004 | transition fails, returning the error code and a human-readable error | ||
4005 | message 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 | |||
4015 | Here, the @code{error_code} is from the @code{enum ANASTASIS_RecoveryStatus} | ||
4016 | and describes precisely what failed about the download, while the | ||
4017 | @code{error_message} is a human-readable (English) explanation of the code. | ||
4018 | Applications may want to translate the message using GNU gettext; | ||
4019 | translations should be available in the @code{anastasis} text domain. | ||
4020 | However, in general it should be sufficient to display the slightly | ||
4021 | more generic Taler error code that is returned with the new state. | ||
4022 | |||
4023 | @strong{change_version:} | ||
4024 | |||
4025 | Even if a recovery document was found, it is possible that the user | ||
4026 | intended to recover a different version, or recover a backup where | ||
4027 | the recovery document is stored at a different provider. Thus, the | ||
4028 | reducer allows the user to explicitly switch to a different provider | ||
4029 | or recovery document version using the @code{change_version} transition, | ||
4030 | which 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 | |||
4039 | Note that using a version of 0 implies fetching “the latest version”. The | ||
4040 | resulting states are the same as those of the @code{enter_user_attributes} | ||
4041 | transition, except that the recovery document version is not necessarily the | ||
4042 | latest available version at the provider. | ||
4043 | |||
4044 | @strong{select_challenge:} | ||
4045 | |||
4046 | Selecting a challenge takes different, depending on the state of the payment. | ||
4047 | A 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 | |||
4057 | The @code{uuid} field is mandatory and specifies the selected challenge. | ||
4058 | The other fields are optional, and are needed in case the user has | ||
4059 | previously been requested to pay for the challenge. In this case, | ||
4060 | the @code{payment_secret} identifies the previous payment request, and | ||
4061 | @code{timeout} says how long the Anastasis service should wait for the | ||
4062 | payment to be completed before giving up (long polling). | ||
4063 | |||
4064 | Depending on the type of the challenge and the need for payment, the | ||
4065 | reducer may transition into @code{CHALLENGE_SOLVING} or @code{CHALLENGE_PAYING} | ||
4066 | states. In @code{CHALLENGE_SOLVING}, the new state will primarily specify | ||
4067 | the selected challenge: | ||
4068 | |||
4069 | @example | ||
4070 | @{ | ||
4071 | "backup_state": "CHALLENGE_SOLVING", | ||
4072 | "selected_challenge_uuid": "80H646H5ZBR453C02Y5RT55VQSJZGM5REWFXVY0SWXY1TNE8CT30" | ||
4073 | @} | ||
4074 | @end example | ||
4075 | |||
4076 | In @code{CHALLENGE_PAYING}, the new state will include instructions for payment | ||
4077 | in the @code{challenge_feedback}. In general, @code{challenge_feedback} includes | ||
4078 | information 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 | |||
4094 | Challenges feedback for a challenge can have many different @code{state} values | ||
4095 | that 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 | ||
4128 | how to solve the challenge, but the reducer could not parse | ||
4129 | them into a known format. A mime-type may be provided and may | ||
4130 | help 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 | ||
4152 | how to solve the challenge. Note that the @code{hint} provided this | ||
4153 | time is from the Anastasis provider and may differ from the @code{instructions} | ||
4154 | for 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 | ||
4175 | related 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 | ||
4206 | Web 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 | ||
4233 | a failure and recovery using this challenge cannot proceed at this time. | ||
4234 | Examples for failures might be that the provider is unable to send SMS | ||
4235 | messages at this time due to an outage. The body includes details about | ||
4236 | the 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 | ||
4261 | the specified challenge. This is typically a permanent failure, and user | ||
4262 | interfaces 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 | |||