]> git.mxchange.org Git - friendica.git/blob - vendor/defuse/php-encryption/docs/Tutorial.md
Add defuse/php-encryption 2.0 to Composer dependencies
[friendica.git] / vendor / defuse / php-encryption / docs / Tutorial.md
1 Tutorial
2 =========
3
4 Hello! If you're reading this file, it's because you want to add encryption to
5 one of your PHP projects. My job, as the person writing this documentation, is
6 to help you make sure you're doing the right thing and then show you how to use
7 this library to do it. To help me help you, please read the documentation
8 *carefully* and *deliberately*.
9
10 A Word of Caution
11 ------------------
12
13 Encryption is not magic dust you can sprinkle on a system to make it more
14 secure. The way encryption is integrated into a system's design needs to be
15 carefully thought out. Sometimes, encryption is the wrong thing to use. Other
16 times, encryption needs to be used in a very specific way in order for it to
17 work as intended. Even if you are sure of what you are doing, we strongly
18 recommend seeking advice from an expert.
19
20 The first step is to think about your application's threat model. Ask yourself
21 the following questions. Who will want to attack my application, and what will
22 they get out of it? Are they trying to steal some information? Trying to alter
23 or destroy some information? Or just trying to make the system go down so people
24 can't access it? Then ask yourself how encryption can help combat those threats.
25 If you're going to add encryption to your application, you should have a very
26 clear idea of exactly which kinds of attacks it's helping to secure your
27 application against. Once you have your threat model, think about what kinds of
28 attacks it *does not* cover, and whether or not you should improve your threat
29 model to include those attacks.
30
31 **This isn't for storing user login passwords:** The most common use of
32 cryptography in web applications is to protect the users' login passwords. If
33 you're trying to use this library to "encrypt" your users' passwords, you're in
34 the wrong place. Passwords shouldn't be *encrypted*, they should be *hashed*
35 with a slow computation-heavy function that makes password guessing attacks more
36 expensive. See [How to Safely Store Your Users' Passwords in
37 2016](https://paragonie.com/blog/2016/02/how-safely-store-password-in-2016).
38
39 **This isn't for encrypting network communication:** Likewise, if you're trying
40 to encrypt messages sent between two parties over the Internet, you don't want
41 to be using this library. For that, set up a TLS connection between the two
42 points, or, if it's a chat app, use the [Signal
43 Protocol](https://whispersystems.org/blog/advanced-ratcheting/).
44
45 What this library provides is symmetric encryption for "data at rest." This
46 means it is not suitable for use in building protocols where "data is in motion"
47 (i.e. moving over a network) except in limited set of cases.
48
49 Getting the Code
50 -----------------
51
52 There are several different ways to obtain this library's code and to add it to
53 your project. Even if you've already cloned the code from GitHub, you should
54 take steps to verify the cryptographic signatures to make sure the code you got
55 was not intercepted and modified by an attacker.
56
57 Please head over to the [**Installing and
58 Verifying**](InstallingAndVerifying.md) documentation to get the code, and then
59 come back here to continue the tutorial.
60
61 Using the Library
62 ------------------
63
64 I'm going to assume you know what symmetric encryption is, and the difference
65 between symmetric and asymmetric encryption. If you don't, I recommend taking
66 [Dan Boneh's Cryptography I course](https://www.coursera.org/learn/crypto/) on
67 Coursera.
68
69 To give you a quick introduction to the library, I'm going to explain how it
70 would be used in two sterotypical scenarios. Hopefully, one of these sterotypes
71 is close enough to what you want to do that you'll be able to figure out what
72 needs to be different on your own.
73
74 ### Formal Documentation
75
76 While this tutorial should get you up and running fast, it's important to
77 understand how this library behaves. Please make sure to read the formal
78 documentation of all of the functions you're using, since there are some
79 important security warnings there.
80
81 The following classes are available for you to use:
82
83 - [Crypto](classes/Crypto.md): Encrypting and decrypting strings.
84 - [File](classes/File.md): Encrypting and decrypting files.
85 - [Key](classes/Key.md): Represents a secret encryption key.
86 - [KeyProtectedByPassword](classes/KeyProtectedByPassword.md): Represents
87   a secret encryption key that needs to be "unlocked" by a password before it
88   can be used.
89
90 ### Scenario #1: Keep data secret from the database administrator
91
92 In this scenario, our threat model is as follows. Alice is a server
93 administrator responsible for managing a trusted web server. Eve is a database
94 administrator responsible for managing a database server. Dave is a web
95 developer working on code that will eventually run on the trusted web server.
96
97 Let's say Alice and Dave trust each other, and Alice is going to host Dave's
98 application on her server. But both Alice and Dave don't trust Eve. They know
99 Eve is a good database administrator, but she might have incentive to steal the
100 data from the database. They want to keep some of the web application's data
101 secret from Eve.
102
103 In order to do that, Alice will use the included `generate-defuse-key` script
104 which generates a random encryption key and prints it to standard output:
105
106 ```sh
107 $ composer require defuse/php-encryption
108 $ vendor/bin/generate-defuse-key
109 ```
110
111 Alice will run this script once and save the output to a configuration file, say
112 in `/etc/daveapp-secret-key.txt` and set the file permissions so that only the
113 user that the website PHP scripts run as can access it.
114
115 Dave will write his code to load the key from the configuration file:
116
117 ```php
118 <?php
119 use Defuse\Crypto\Key;
120
121 function loadEncryptionKeyFromConfig()
122 {
123     $keyAscii = // ... load the contents of /etc/daveapp-secret-key.txt
124     return Key::loadFromAsciiSafeString($keyAscii);
125 }
126 ```
127
128 Then, whenever Dave wants to save a secret value to the database, he will first
129 encrypt it:
130
131 ```php
132 <?php
133 use Defuse\Crypto\Crypto;
134
135 // ...
136 $key = loadEncryptionKeyFromConfig();
137 // ...
138 $ciphertext = Crypto::encrypt($secret_data, $key);
139 // ... save $ciphertext into the database ...
140 ```
141
142 Whenever Dave wants to get the value back from the database, he must decrypt it
143 using the same key:
144
145 ```php
146 <?php
147 use Defuse\Crypto\Crypto;
148
149 // ...
150 $key = loadEncryptionKeyFromConfig();
151 // ...
152 $ciphertext = // ... load $ciphertext from the database
153 try {
154     $secret_data = Crypto::decrypt($ciphertext, $key);
155 } catch (\Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
156     // An attack! Either the wrong key was loaded, or the ciphertext has
157     // changed since it was created -- either corrupted in the database or
158     // intentionally modified by Eve trying to carry out an attack.
159
160     // ... handle this case in a way that's suitable to your application ...
161 }
162 ```
163
164 Note that if anyone ever steals the key from Alice's server, they can decrypt
165 all of the ciphertexts that are stored in the database. As part of our threat
166 model, we are assuming Alice's server administration skills and Dave's secure
167 coding skills are good enough to stop Eve from being able to steal the key.
168 Under those assumptions, this solution will prevent Eve from seeing data that's
169 stored in the database.
170
171 However, notice that our threat model says nothing about what could happen if
172 Eve wants to *modify* the data. With this solution, Eve will not be able to
173 alter any individual ciphertext (because each ciphertext has its own
174 cryptographic integrity check), but Eve *will* be able to swap ciphertexts for
175 one another, and revert ciphertexts to what they used to be at previous times.
176 If we needed to defend against such attacks, we would have to re-design our
177 threat model and come up with a different solution.
178
179 ### Scenario #2: Encrypting account data with the user's login password
180
181 This scenario is like Scenario 1, but subtly different. The threat model is as
182 follows. We have Alice, a server administrator, and Dave, the developer. Alice
183 and Dave trust each other, and Alice wants to host Dave's web application,
184 including its database, on her server. Alice is worried about her server getting
185 hacked. The application will store the users' credit card numbers, and Alice
186 wants to protect them in case the server gets hacked.
187
188 We can model the situation like this: after the server gets hacked, the attacker
189 will have read and write access to all data on it until the attack is detected
190 and Alice rebuilds the server. We'll call the time the attacker has access to
191 the server the *exposure window.* One idea to minimize loss is to encrypt the
192 users' credit card numbers using a key made from their login password. Then, as
193 long as the users all have strong passwords, and they are never logged in during
194 the exposure window, their credit cards will be protected from the attacker.
195
196 To implement this, Dave will use the `KeyProtectedByPassword` class. When a new
197 user account is created, Dave will save a new key to their account, one that's
198 protected by their login password:
199
200 ```php
201 <?php
202 use Defuse\Crypto\KeyProtectedByPassword;
203
204 function CreateUserAccount($username, $password)
205 {
206     // ... other user account creation stuff, including password hashing
207
208     $protected_key = KeyProtectedByPassword::createRandomPasswordProtectedKey($password);
209     $protected_key_encoded = $protected_key->saveToAsciiSafeString();
210     // ... save $protected_key_encoded into the user's account record
211 }
212 ```
213
214 Then, when the user logs in, Dave's code will load the protected key from the
215 user's account record, unlock it to get a `Key` object, and save the `Key`
216 object somewhere safe (like temporary memory-backed session storage). Note that
217 wherever Dave's code saves the key, it must be destroyed once the user logs out,
218 or else the attacker might be able to find users' keys even if they were never
219 logged in during the attack.
220
221 ```php
222 <?php
223 use Defuse\Crypto\KeyProtectedByPassword;
224
225 // ... authenticate the user using a good password hashing scheme
226 // keep the user's password in $password
227
228 $protected_key_encoded = // ... load it from the user's account record
229 $protected_key = KeyProtectedByPassword::loadFromAsciiSafeString($protected_key_encoded);
230 $user_key = $protected_key->unlockKey($password);
231 $user_key_encoded = $user_key->saveToAsciiSafeString();
232 // ... save $user_key_encoded in the session
233 ```
234
235 ```php
236 <?php
237 // ... when the user is logging out ...
238 // ... securely wipe the saved $user_key_encoded from the system ...
239 ```
240
241 When a user adds their credit card number, Dave's code will get the key from the
242 session and use it to encrypt the credit card number:
243
244 ```php
245 <?php
246 use Defuse\Crypto\Crypto;
247 use Defuse\Crypto\Key;
248
249 // ...
250
251 $user_key_encoded = // ... get it out of the session ...
252 $user_key = Key::loadFromAsciiSafeString($user_key_encoded);
253
254 // ...
255
256 $credit_card_number = // ... get credit card number from the user
257 $encrypted_card_number = Crypto::encrypt($credit_card_number, $user_key);
258 // ... save $encrypted_card_number in the database
259 ```
260
261 When the application needs to use the credit card number, it will decrypt it:
262
263 ```php
264 <?php
265 use Defuse\Crypto\Crypto;
266 use Defuse\Crypto\Key;
267
268 // ...
269
270 $user_key_encoded = // ... get it out of the session
271 $user_key = Key::loadFromAsciiSafeString($user_key_encoded);
272
273 // ...
274
275 $encrypted_card_number = // ... load it from the database ...
276 try {
277     $credit_card_number = Crypto::decrypt($encrypted_card_number, $user_key);
278 } catch (Defuse\Crypto\Exception\WrongKeyOrModifiedCiphertextException $ex) {
279     // Either there's a bug in our code, we're trying to decrypt with the
280     // wrong key, or the encrypted credit card number was corrupted in the
281     // database.
282
283     // ... handle this case ...
284 }
285 ```
286
287 With all caveats carefully heeded, this solution limits credit card number
288 exposure in the case where Alice's server gets hacked for a short amount of
289 time. Remember to think about the attacks that *aren't* included in our threat
290 model. The attacker is still free to do all sorts of harmful things like
291 modifying the server's data which may go undetected if Alice doesn't have secure
292 backups to compare against.
293
294 Getting Help
295 -------------
296
297 If you're having difficulty using the library, see if your problem is already
298 solved by an answer in the [FAQ](FAQ.md).