aboutsummaryrefslogtreecommitdiff
path: root/doc/sphinx/cryptography.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/sphinx/cryptography.rst')
-rw-r--r--doc/sphinx/cryptography.rst298
1 files changed, 298 insertions, 0 deletions
diff --git a/doc/sphinx/cryptography.rst b/doc/sphinx/cryptography.rst
new file mode 100644
index 0000000..6e8c29b
--- /dev/null
+++ b/doc/sphinx/cryptography.rst
@@ -0,0 +1,298 @@
1..
2 This file is part of Anastasis
3 Copyright (C) 2019-2021 Anastasis SARL
4
5 Anastasis is free software; you can redistribute it and/or modify it under the
6 terms of the GNU Affero General Public License as published by the Free Software
7 Foundation; either version 2.1, or (at your option) any later version.
8
9 Anastasis is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
12
13 You should have received a copy of the GNU Affero General Public License along with
14 Anastasis; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15
16 @author Christian Grothoff
17 @author Dominik Meister
18 @author Dennis Neufeld
19
20------------
21Cryptography
22------------
23
24When a user needs to interact with Anastasis, the system first derives some key
25material, but not the master secret, from the user's **identifier** using
26different HKDFs. These HKDFs are salted using the respective escrow
27provider's **server salt**, which ensures that the accounts for the same user
28cannot be easily correlated across the various Anastasis servers.
29
30Each Anastasis server uses an EdDSA **account key** to identify the account of
31the user. The account private key is derived from the user's **identifier** using
32a computationally expensive cryptographic hash function. Using an
33expensive hash algorithm is assumed to make it infeasible for a weak adversary to
34determine account keys by brute force (without knowing the user's identifier).
35However, it is assumed that a strong adversary performing a targeted attack can
36compute the account key pair.
37
38The public account key is Crockford base32-encoded in the URI to identify the
39account, and used to sign requests. These signatures are also provided in
40base32-encoding and transmitted using the HTTP header
41``Anastasis-Account-Signature``.
42
43When confidential data is uploaded to an Anastasis server, the respective
44payload is encrypted using AES-GCM with a symmetric key and initialization
45vector derived from the **identifier** and a high-entropy **nonce**. The
46nonce and the GCM tag are prepended to the ciphertext before being uploaded to
47the Anastasis server. This is done whenever confidential data is stored with
48the server.
49
50The **core secret** of the user is (AES) encrypted using a symmetric **master
51key**. Recovering this master key requires the user to satisfy a particular
52**policy**. Policies specify a set of **escrow methods**, each of which leads
53the user to a **key share**. Combining those key shares (by hashing) allows
54the user to obtain a **policy key**, which can be used to decrypt the **master
55key**. There can be many policies, satisfying any of these will allow the
56user to recover the master key. A **recovery document** contains the
57encrypted **core secret**, a set of escrow methods and a set of policies.
58
59
60
61
62Key derivations
63^^^^^^^^^^^^^^^
64
65EdDSA and ECDHE public keys are always points on Curve25519 and represented
66using the standard 256 bit Ed25519 compact format. The binary representation
67is converted to Crockford Base32 when transmitted inside JSON or as part of
68URLs.
69
70To start, a user provides their private, unique and unforgettable
71**identifier** as a seed to identify their account. For example, this could
72be a social security number together with their full name. Specifics may
73depend on the cultural context, in this document we will simply refer to this
74information as the **identifier**.
75
76This identifier will be first hashed with Argon2, to provide a **kdf_id**
77which will be used to derive other keys later. The Hash must also include the
78respective **server_salt**. This also ensures that the **kdf_id** is different
79on each server. The use of Argon2 and the respective **server_salt** is intended
80to make it difficult to brute-force **kdf_id** values and help protect the user's
81privacy. Also this ensures that the **kdf_id**\ s on every server differs. However,
82we do not assume that the **identifier** or the **kdf_id** cannot be
83determined by an adversary performing a targeted attack, as a user's
84**identifier** is likely to always be known to state actors and may
85likely also be available to other actors.
86
87
88.. code-block:: none
89
90 kdf_id := Argon2( identifier, server_salt, keysize )
91
92**identifier**: The secret defined from the user beforehand.
93
94**server_salt**: The salt from the Server.
95
96**keysize**: The desired output size of the KDF, here 32 bytes.
97
98
99Verification
100------------
101
102For users to authorize "policy" operations we need an EdDSA key pair. As we
103cannot assure that the corresponding private key is truly secret, such policy
104operations must never be destructive: Should an adversary learn the private
105key, they could access (and with the **kdf_id**, decrypt) the user's policy (but
106not the core secret), or upload a new version of the
107**encrypted recovery document** (but not delete an existing version).
108
109For the generation of the private key we use the **kdf_id** as the entropy source,
110hash it to derive a base secret which will then be processed to fit the
111requirements for EdDSA private keys. From the private key we can then
112generate the corresponding public key. Here, "ver" is used as a salt for the
113HKDF to ensure that the result differs from other cases where we hash
114**kdf_id**.
115
116.. code-block:: none
117
118 ver_secret := HKDF(kdf_id, "ver", keysize)
119 eddsa_priv := eddsa_d_to_a(ver_secret)
120 eddsa_pub := get_EdDSA_Pub(eddsa_priv)
121
122
123**HKDF()**: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
124
125**kdf_id**: Hashed identifier.
126
127**key_size**: Size of the output, here 32 bytes.
128
129**ver_secret**: Derived key from the ``kdf_id``, serves as intermediate step for the generation of the private key.
130
131**eddsa_d_to_a()**: Function which converts the ver_key to a valid EdDSA private key. Specifically, assuming the value ``eddsa_priv`` is in a 32-byte array "digest", the function clears and sets certain bits as follows:
132
133.. code-block:: c
134
135 digest[0] = (digest[0] & 0x7f) | 0x40;
136 digest[31] &= 0xf8;
137
138**eddsa_priv**: The generated EdDSA private key.
139
140**eddsa_pub**: The generated EdDSA public key.
141
142
143Encryption
144----------
145
146For symmetric encryption of data we use AES256-GCM. For this we need a
147symmetric key and an initialization vector (IV). To ensure that the
148symmetric key changes for each encryption operation, we compute the
149key material using an HKDF over a ``nonce`` and the ``kdf_id``.
150
151.. code-block:: none
152
153 (iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)
154
155**HKDF()**: The HKDF-function uses two phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.
156
157**kdf_id**: Hashed identifier.
158
159**keysize**: Size of the AES symmetric key, here 32 bytes.
160
161**ivsize**: Size of the AES GCM IV, here 12 bytes.
162
163**prekey**: Original key material.
164
165**nonce**: 32-byte nonce, must never match "ver" (which it cannot as the length is different). Of course, we must
166avoid key reuse. So, we have to use different nonces to get different keys and IVs (see below).
167
168**key**: Symmetric key which is later used to encrypt the documents with AES256-GCM.
169
170**iv**: IV which will be used for AES-GCM.
171
172
173
174Key Usage
175^^^^^^^^^
176
177The keys we have generated are then used to encrypt the **recovery document** and
178the **key_share** of the user.
179
180
181Encryption
182----------
183
184Before every encryption a 32-byte nonce is generated.
185From this the symmetric key is computed as described above.
186We use AES256-GCM for the encryption of the **recovery document** and
187the **key_share**. To ensure that the key derivation for the encryption
188of the **recovery document** differs fundamentally from that of an
189individual **key share**, we use different salts ("erd" and "eks", respectively).
190
191.. code-block:: none
192
193 (iv0, key0) := HKDF(key_id, nonce0, "erd", keysize + ivsize)
194 (encrypted_recovery_document, aes_gcm_tag) := AES256_GCM(recovery_document, key0, iv0)
195 (iv_i, key_i) := HKDF(key_id, nonce_i, "eks", [optional data], keysize + ivsize)
196 (encrypted_key_share_i, aes_gcm_tag_i) := AES256_GCM(key_share_i, key_i, iv_i)
197
198**encrypted_recovery_document**: The encrypted **recovery document** which contains the escrow methods, policies
199and the encrypted **core secret**.
200
201**nonce0**: Nonce which is used to generate *key0* and *iv0* which are used for the encryption of the *recovery document*.
202Nonce must contain the string "ERD".
203
204**optional data**: Key material that optionally is contributed from the authentication method to further obfuscate the key share from the escrow provider.
205
206**encrypted_key_share_i**: The encrypted **key_share** which the escrow provider must release upon successful authentication.
207Here, **i** must be a positive number used to iterate over the various **key shares** used for the various **escrow methods**
208at the various providers.
209
210**nonce_i**: Nonce which is used to generate *key_i* and *iv_i* which are used for the encryption of the **key share**. **i** must be
211the same number as specified above for *encrypted_key_share_i*. Nonce must contain the string "EKS" plus the according *i*.
212
213As a special rule, when a **security question** is used to authorize access to an
214**encrypted_key_share_i**, then the salt "eks" is replaced with an (expensive) hash
215of the answer to the security question as an additional way to make the key share
216inaccessible to those who do not have the answer:
217
218.. code-block:: none
219
220 powh := POW_HASH (qsalt, answer)
221 ekss := HKDF("Anastasis-secure-question-uuid-salting",
222 powh,
223 uuid);
224 (iv_i, key_i) := HKDF(key_id, nonce_i, ekss, [optional data], keysize + ivsize)
225
226
227**qsalt**: Salt value used to hash answer to satisfy the challenge to prevent the provider from determining the answer via guessing.
228
229**answer**: Answer to the security question, in UTF-8, as entered by the user.
230
231**powh**: Result of the (expensive, proof-of-work) hash algorithm.
232
233**uuid**: UUID of the challenge associated with the security question and the encrypted key share.
234
235**ekss**: Replacement salt to be used instead of "eks" when deriving the key to encrypt/decrypt the key share.
236
237
238Signatures
239----------
240
241The EdDSA keys are used to sign the data sent from the client to the
242server. Everything the client sends to server is signed. The following
243algorithm is equivalent for **Anastasis-Policy-Signature**.
244
245.. code-block:: none
246
247 (anastasis-account-signature) := eddsa_sign(h_body, eddsa_priv)
248 ver_res := eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)
249
250**anastasis-account-signature**: Signature over the SHA-512 hash of the body using the purpose code ``TALER_SIGNATURE_ANASTASIS_POLICY_UPLOAD`` (1400) (see GNUnet EdDSA signature API for the use of purpose).
251
252**h_body**: The hashed body.
253
254**ver_res**: A boolean value. True: Signature verification passed, False: Signature verification failed.
255
256
257When requesting policy downloads, the client must also provide a signature:
258
259.. code-block:: none
260
261 (anastasis-account-signature) := eddsa_sign(version, eddsa_priv)
262 ver_res := eddsa_verifiy(version, anastasis-account-signature, eddsa_pub)
263
264**anastasis-account-signature**: Signature over the SHA-512 hash of the body using the purpose code ``TALER_SIGNATURE_ANASTASIS_POLICY_DOWNLOAD`` (1401) (see GNUnet EdDSA signature API for the use of purpose).
265
266**version**: The version requested as a 64-bit integer, 2^64-1 for the "latest version".
267
268**ver_res**: A boolean value. True: Signature verification passed, False: Signature verification failed.
269
270
271
272Availability Considerations
273^^^^^^^^^^^^^^^^^^^^^^^^^^^
274
275Anastasis considers two main threats against availability. First, the
276Anastasis server operators must be protected against denial-of-service attacks
277where an adversary attempts to exhaust the operator's resources. The API protects
278against these attacks by allowing operators to set fees for all
279operations. Furthermore, all data stored comes with an expiration logic, so an
280attacker cannot force servers to store data indefinitely.
281
282A second availability issue arises from strong adversaries that may be able to
283compute the account keys of some user. While we assume that such an adversary
284cannot successfully authenticate against the truth, the account key does
285inherently enable these adversaries to upload a new policy for the account.
286This cannot be prevented, as the legitimate user must be able to set or change
287a policy using only the account key. To ensure that an adversary cannot
288exploit this, policy uploads first of all never delete existing policies, but
289merely create another version. This way, even if an adversary uploads a
290malicious policy, a user can still retrieve an older version of the policy to
291recover access to their data. This append-only storage for policies still
292leaves a strong adversary with the option of uploading many policies to
293exhaust the Anastasis server's capacity. We limit this attack by requiring a
294policy upload to include a reference to a **payment identifier** from a payment
295made by the user. Thus, a policy upload requires both knowledge of the
296**identity** and making a payment. This effectively prevents an adversary
297from using the append-only policy storage from exhausting Anastasis server
298capacity.