summaryrefslogtreecommitdiff
path: root/crypto-anastasis.rst
blob: 9b154a9237a69d3fb250d7ab5d5c9c8aa091a298 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
..
  This file is part of GNU TALER.
  Copyright (C) 2019 Taler Systems SA

  TALER is free software; you can redistribute it and/or modify it under the
  terms of the GNU General Public License as published by the Free Software
  Foundation; either version 2.1, or (at your option) any later version.

  TALER is distributed in the hope that it will be useful, but WITHOUT ANY
  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License along with
  TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>

  @author Christian Grothoff
  @author Dominik Meister
  @author Dennis Neufeld


==========================================
Specification of Cryptography in Anastasis
==========================================
This document specifies the Crypto used in Anastasis.

---------------
Key derivations
---------------

EdDSA and ECDHE public keys are always points on Curve25519 and represented
using the standard 256 bit Ed25519 compact format.  The binary representation
is converted to Crockford Base32 when transmitted inside JSON or as part of
URLs.

To start, a user provides their private, unique and unforgettable
**identifier** as a seed to identify their account.  For example, this could
be a social security number together with their full name.  Specifics may
depend on the cultural context, in this document we will simply refer to this
information as the **user_identifier**.

This user_identifier will be first hashed with SCrypt, to provide a **kdf_id**
which will be used to derive other keys later. The Hash must also include the
respective **server_salt**. This also ensures that the **kdf_id** is different
on each server. The use of SCrypt and the respective server_salt is intended
to make it difficult to brute-force **kdf_id** values and help protect user's
privacy. Also this ensures that the kdf_ids on every server differs. However,
we do not assume that the **user_identifier** or the **kdf_id** cannot be
determined by an adversary performing a targeted attack, as a user's
**user_identifier** is likely to always be known to state actors and may
likely also be available to other actors.


.. code-block:: tsref

    kdf_id := SCrypt( user_identifier, server_salt, keysize )

**user_identifier**: The secret defined from the user beforehand.

**server_salt**: The salt from the Server

**keysize**: The desired output size of the KDF, here 32 bytes.


Verification
^^^^^^^^^^^^

For users to authorize **policy** operations we need an EdDSA key pair.  As we
cannot assure that the corresponding private key is truly secret, such policy
operations must never be destructive: Should an adversary learn the private
key, they could access (and with the kdf_id decrypt) the user's policy (but
not the core secret), or upload a new version of the policy (but not delete an
existing version).

For the generation of the private key we use the kdf_id as the entropy source,
hash it to derive a base secret which will then be processed to fit the
requirements for EdDSA private keys.  From the private key we can then
generate the corresponding public key.  Here, "ver" is used as a salt for the
HKDF to ensure that the result differs from other cases where we hash
kdf_id.

.. code-block:: tsref

    ver_secret:= HKDF(kdf_id, "ver", keysize)
    eddsa_priv := eddsa_d_to_a(ver_secret)
    eddsa_pub := get_EdDSA_Pub(eddsa_priv)


**HKDF()**: The HKDF-function uses to phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.

**kdf_id**: Hashed user_identifier.

**key_size**: Size of the output, here 32 bytes.

**ver_secret**: Derived key from the kdf_id, serves as intermediate step for the generation of the private key

**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:

.. code-block:: tsref

   digest[0] = (digest[0] & 0x7f) | 0x40;
   digest[31] &= 0xf8;

**eddsa_priv**: The generated EdDSA private key.

**eddsa_pub**: The generated EdDSA public key.


Encryption
^^^^^^^^^^

For symmetric encryption of data we use AES256-GCM. For this we need a
symmetric key and an initialization vector (IV).  To ensure that the
symmetric key changes for each encryption operation, we compute the
key material using an HKDF over a nonce and the kdf_id.

.. code-block:: tsref

    (iv,key) := HKDF(kdf_id, nonce, keysize + ivsize)

**HKDF()**: The HKDF-function uses to phases: First we use HMAC-SHA512 for the extraction phase, then HMAC-SHA256 is used for expansion phase.

**kdf_id**: Hashed user_identifier

**keysize**: Size of the AES symmetric key, here 32 bytes

**ivsize**: Size of the AES GCM IV, here 12 bytes

**prekey**: Original key material.

**nonce**: 32-byte nonce, must never match "ver" (which it cannot as the length is different).

**key**: Symmetric key which is later used to encrypt the documents with AES256-GCM.

**iv**: IV which will be used for AES-GCM

----------------------------
Key Usage
----------------------------

The keys we have generated, are now used to encrypt the recovery_document and
the key_share of the user.


Encryption
^^^^^^^^^^

Before every encryption a 32-byte nonce is generated.
From this the symmetric key is computed as described above.
We use AES256-GCM for the encryption of the recovery_document and
key_share.

.. code-block:: tsref

    (encrypted_recovery_document, aes_gcm_tag) = AES256_GCM(recovery_document, key, iv)
    (encrypted_key_share, aes_gcm_tag) = AES256_GCM(key_share, key, iv)

**encrypted_recovery_document**: The encrypted RecoveryDocument (recovery_document) which contains the policies.

**encrypted_key_share**: The encrypted KeyShare (key_share).

Signatures
^^^^^^^^^^

The EdDSA keys are used to sign the data sent from the client to the
server. Everything the client sends to server is signed. The following algorithm is equivalent for **Anastasis-Policy-Signature**.

.. code-block:: tsref

    (anastasis-account-signature) = eddsa_sign(h_body, eddsa_priv)
    ver_res = eddsa_verifiy(h_body, anastasis-account-signature, eddsa_pub)

**anastasis-account-signature**: Signature over the hash of body.

**h_body**: The hashed body.

**ver_res**: A boolean value. True: Verification passed, False: Verification failed.