diff options
Diffstat (limited to 'doc/sphinx/cryptography.rst')
-rw-r--r-- | doc/sphinx/cryptography.rst | 298 |
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 | ------------ | ||
21 | Cryptography | ||
22 | ------------ | ||
23 | |||
24 | When a user needs to interact with Anastasis, the system first derives some key | ||
25 | material, but not the master secret, from the user's **identifier** using | ||
26 | different HKDFs. These HKDFs are salted using the respective escrow | ||
27 | provider's **server salt**, which ensures that the accounts for the same user | ||
28 | cannot be easily correlated across the various Anastasis servers. | ||
29 | |||
30 | Each Anastasis server uses an EdDSA **account key** to identify the account of | ||
31 | the user. The account private key is derived from the user's **identifier** using | ||
32 | a computationally expensive cryptographic hash function. Using an | ||
33 | expensive hash algorithm is assumed to make it infeasible for a weak adversary to | ||
34 | determine account keys by brute force (without knowing the user's identifier). | ||
35 | However, it is assumed that a strong adversary performing a targeted attack can | ||
36 | compute the account key pair. | ||
37 | |||
38 | The public account key is Crockford base32-encoded in the URI to identify the | ||
39 | account, and used to sign requests. These signatures are also provided in | ||
40 | base32-encoding and transmitted using the HTTP header | ||
41 | ``Anastasis-Account-Signature``. | ||
42 | |||
43 | When confidential data is uploaded to an Anastasis server, the respective | ||
44 | payload is encrypted using AES-GCM with a symmetric key and initialization | ||
45 | vector derived from the **identifier** and a high-entropy **nonce**. The | ||
46 | nonce and the GCM tag are prepended to the ciphertext before being uploaded to | ||
47 | the Anastasis server. This is done whenever confidential data is stored with | ||
48 | the server. | ||
49 | |||
50 | The **core secret** of the user is (AES) encrypted using a symmetric **master | ||
51 | key**. Recovering this master key requires the user to satisfy a particular | ||
52 | **policy**. Policies specify a set of **escrow methods**, each of which leads | ||
53 | the user to a **key share**. Combining those key shares (by hashing) allows | ||
54 | the user to obtain a **policy key**, which can be used to decrypt the **master | ||
55 | key**. There can be many policies, satisfying any of these will allow the | ||
56 | user to recover the master key. A **recovery document** contains the | ||
57 | encrypted **core secret**, a set of escrow methods and a set of policies. | ||
58 | |||
59 | |||
60 | |||
61 | |||
62 | Key derivations | ||
63 | ^^^^^^^^^^^^^^^ | ||
64 | |||
65 | EdDSA and ECDHE public keys are always points on Curve25519 and represented | ||
66 | using the standard 256 bit Ed25519 compact format. The binary representation | ||
67 | is converted to Crockford Base32 when transmitted inside JSON or as part of | ||
68 | URLs. | ||
69 | |||
70 | To start, a user provides their private, unique and unforgettable | ||
71 | **identifier** as a seed to identify their account. For example, this could | ||
72 | be a social security number together with their full name. Specifics may | ||
73 | depend on the cultural context, in this document we will simply refer to this | ||
74 | information as the **identifier**. | ||
75 | |||
76 | This identifier will be first hashed with Argon2, to provide a **kdf_id** | ||
77 | which will be used to derive other keys later. The Hash must also include the | ||
78 | respective **server_salt**. This also ensures that the **kdf_id** is different | ||
79 | on each server. The use of Argon2 and the respective **server_salt** is intended | ||
80 | to make it difficult to brute-force **kdf_id** values and help protect the user's | ||
81 | privacy. Also this ensures that the **kdf_id**\ s on every server differs. However, | ||
82 | we do not assume that the **identifier** or the **kdf_id** cannot be | ||
83 | determined by an adversary performing a targeted attack, as a user's | ||
84 | **identifier** is likely to always be known to state actors and may | ||
85 | likely 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 | |||
99 | Verification | ||
100 | ------------ | ||
101 | |||
102 | For users to authorize "policy" operations we need an EdDSA key pair. As we | ||
103 | cannot assure that the corresponding private key is truly secret, such policy | ||
104 | operations must never be destructive: Should an adversary learn the private | ||
105 | key, they could access (and with the **kdf_id**, decrypt) the user's policy (but | ||
106 | not the core secret), or upload a new version of the | ||
107 | **encrypted recovery document** (but not delete an existing version). | ||
108 | |||
109 | For the generation of the private key we use the **kdf_id** as the entropy source, | ||
110 | hash it to derive a base secret which will then be processed to fit the | ||
111 | requirements for EdDSA private keys. From the private key we can then | ||
112 | generate the corresponding public key. Here, "ver" is used as a salt for the | ||
113 | HKDF 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 | |||
143 | Encryption | ||
144 | ---------- | ||
145 | |||
146 | For symmetric encryption of data we use AES256-GCM. For this we need a | ||
147 | symmetric key and an initialization vector (IV). To ensure that the | ||
148 | symmetric key changes for each encryption operation, we compute the | ||
149 | key 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 | ||
166 | avoid 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 | |||
174 | Key Usage | ||
175 | ^^^^^^^^^ | ||
176 | |||
177 | The keys we have generated are then used to encrypt the **recovery document** and | ||
178 | the **key_share** of the user. | ||
179 | |||
180 | |||
181 | Encryption | ||
182 | ---------- | ||
183 | |||
184 | Before every encryption a 32-byte nonce is generated. | ||
185 | From this the symmetric key is computed as described above. | ||
186 | We use AES256-GCM for the encryption of the **recovery document** and | ||
187 | the **key_share**. To ensure that the key derivation for the encryption | ||
188 | of the **recovery document** differs fundamentally from that of an | ||
189 | individual **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 | ||
199 | and 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*. | ||
202 | Nonce 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. | ||
207 | Here, **i** must be a positive number used to iterate over the various **key shares** used for the various **escrow methods** | ||
208 | at 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 | ||
211 | the same number as specified above for *encrypted_key_share_i*. Nonce must contain the string "EKS" plus the according *i*. | ||
212 | |||
213 | As 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 | ||
215 | of the answer to the security question as an additional way to make the key share | ||
216 | inaccessible 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 | |||
238 | Signatures | ||
239 | ---------- | ||
240 | |||
241 | The EdDSA keys are used to sign the data sent from the client to the | ||
242 | server. Everything the client sends to server is signed. The following | ||
243 | algorithm 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 | |||
257 | When 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 | |||
272 | Availability Considerations | ||
273 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
274 | |||
275 | Anastasis considers two main threats against availability. First, the | ||
276 | Anastasis server operators must be protected against denial-of-service attacks | ||
277 | where an adversary attempts to exhaust the operator's resources. The API protects | ||
278 | against these attacks by allowing operators to set fees for all | ||
279 | operations. Furthermore, all data stored comes with an expiration logic, so an | ||
280 | attacker cannot force servers to store data indefinitely. | ||
281 | |||
282 | A second availability issue arises from strong adversaries that may be able to | ||
283 | compute the account keys of some user. While we assume that such an adversary | ||
284 | cannot successfully authenticate against the truth, the account key does | ||
285 | inherently enable these adversaries to upload a new policy for the account. | ||
286 | This cannot be prevented, as the legitimate user must be able to set or change | ||
287 | a policy using only the account key. To ensure that an adversary cannot | ||
288 | exploit this, policy uploads first of all never delete existing policies, but | ||
289 | merely create another version. This way, even if an adversary uploads a | ||
290 | malicious policy, a user can still retrieve an older version of the policy to | ||
291 | recover access to their data. This append-only storage for policies still | ||
292 | leaves a strong adversary with the option of uploading many policies to | ||
293 | exhaust the Anastasis server's capacity. We limit this attack by requiring a | ||
294 | policy upload to include a reference to a **payment identifier** from a payment | ||
295 | made by the user. Thus, a policy upload requires both knowledge of the | ||
296 | **identity** and making a payment. This effectively prevents an adversary | ||
297 | from using the append-only policy storage from exhausting Anastasis server | ||
298 | capacity. | ||