blob: cedc8d38141cc0131c287a85fb92d0f20cba0322 [file] [log] [blame]
Andrey Andreev4b450652014-02-10 06:59:54 +02001##################
2Encryption Library
3##################
4
5The Encryption Library provides two-way data encryption. To do so in
6a cryptographically secure way, it utilizes PHP extensions that are
7unfortunately not always available on all systems.
8You must meet one of the following dependancies in order to use this
9library:
10
11- `OpenSSL <http://php.net/openssl>`_ (and PHP 5.3.3)
12- `MCrypt <http://php.net/mcrypt>`_ (and `MCRYPT_DEV_URANDOM` availability)
13
14If neither of the above dependancies is met, we simply cannot offer
15you a good enough implementation to meet the high standards required
16for proper cryptography.
17
18.. contents::
19 :local:
20
21.. raw:: html
22
23 <div class="custom-index container"></div>
24
25****************************
26Using the Encryption Library
27****************************
28
29Initializing the Class
30======================
31
32Like most other classes in CodeIgniter, the Encryption library is
33initialized in your controller using the ``$this->load->library()``
34method::
35
36 $this->load->library('encrypt');
37
38Once loaded, the Encryption library object will be available using::
39
40 $this->encrypt
41
42Default behavior
43================
44
45By default, the Encryption Library will use the AES-128 cipher in CBC
46mode, using your configured *encryption_key* and SHA512 HMAC authentication.
47
48.. note:: AES-128 is chosen both because it is proven to be strong and
49 because of its wide availability across different cryptographic
50 software and programming languages' APIs.
51
52However, the *encryption_key* is not used as is.
53
54If you are somewhat familiar with cryptography, you should already know
55that a HMAC also requires a secret key and using the same key for both
56encryption and authentication is a bad practice.
57
58Because of that, two separate keys are derived from your already configured
59*encryption_key*: one for encryption and one for authentication. This is
60done via a technique called `HMAC-based Key Derivation Function
61<http://en.wikipedia.org/wiki/HKDF>`_ (HKDF).
62
63Setting your encryption_key
64===========================
65
66An *encryption key* is a piece of information that controls the
67cryptographic process and permits a plain-text string to be encrypted,
68and afterwards - decrypted. It is the secret "ingredient" in the whole
69process that allows you to be the only one who is able to decrypt data
70that you've decided to hide from the eyes of the public.
71After one key is used to encrypt data, that same key provides the **only**
72means to decrypt it, so not only must you chose one carefully, but you
73must not lose it or you will also use the encrypted data.
74
75It must be noted that to ensure maximum security, such key *should* not
76only be as strong as possible, but also often changed. Such behavior
77however is rarely practical or possible to implement, and that is why
78CodeIgniter gives you the ability to configure a single key that is to be
79used (almost) every time.
80
81It goes without saying that you should guard your key carefully. Should
82someone gain access to your key, the data will be easily decrypted. If
83your server is not totally under your control it's impossible to ensure
84key security so you may want to think carefully before using it for
85anything that requires high security, like storing credit card numbers.
86
87Your encryption key should be as long as the encyption algorithm in use
88allows. For AES-128, that's 128 bits or 16 bytes (charcters) long. The
89key should be as random as possible and it should **not** be a simple
90text string.
91
92You will find a table below that shows the supported key lengths of
93different ciphers.
94
95The key can be either stored in your *application/config/config.php*, or
96you can design your own storage mechanism and pass the key dynamically
97when encrypting/decrypting.
98
99To save your key to your *application/config/config.php*, open the file
100and set::
101
102 $config['encryption_key'] = 'YOUR KEY';
103
104.. _ciphers-and-modes:
105
106Supported encryption ciphers and modes
107======================================
108
109.. note:: The terms 'cipher' and 'encryption algorithm' are interchangeable.
110
111Portable ciphers
112----------------
113
114Because MCrypt and OpenSSL (also called drivers throughout this document)
115each support different sets of encryption algorithms and often implement
116them in different ways, our Encryption library is designed to use them in
117a portable fashion, or in other words - it enables you to use them
118interchangeably, at least for the ciphers supported by both drivers.
119
120It is also implemented in a way that aims to match the standard
121implementations in other programming languages and libraries.
122
123Here's a list of the so called "portable" ciphers, where
124"CodeIgniter name" is the string value that you'd have to pass to the
125Encryption library to use that cipher:
126
127======================== ================== ============================ ===============================
128Cipher name CodeIgniter name Key lengths (bits / bytes) Supported modes
129======================== ================== ============================ ===============================
130AES-128 / Rijndael-128 aes-128 128 / 16 CBC, CTR, CFB, CFB8, OFB, ECB
131AES-192 aes-192 192 / 24 CBC, CTR, CFB, CFB8, OFB, ECB
132AES-256 aes-256 256 / 32 CBC, CTR, CFB, CFB8, OFB, ECB
133DES des 56 / 7 CBC, CFB, CFB8, OFB, ECB
134TripleDES tripledes 56 / 7, 112 / 14, 168 / 21 CBC, CFB, CFB8, OFB
135Blowfish blowfish 128-448 / 16-56 CBC, CFB, OFB, ECB
136CAST5 / CAST-128 cast5 40-128 / 5-16 CBC, CFB, OFB, ECB
137RC4 / ARCFour rc4 40-2048 / 5-256 Stream
138======================== ================== ============================ ===============================
139
140.. important:: Because of how MCrypt works, if you fail to provide a key
141 with the appropriate length, you might end up using a different
142 algorithm than the one configured, so be really careful with that!
143
144.. note:: In case it isn't clear from the above table, Blowfish, CAST5
145 and RC4 support variable length keys. That is, any number in the
146 shown ranges is valid, although in bit terms that only happens
147 in 8-bit increments.
148
149.. note:: Even though CAST5 supports key lengths lower than 128 bits
150 (16 bytes), in fact they will just be zero-padded to the
151 maximum length, as specified in `RFC 2144
152 <http://tools.ietf.org/rfc/rfc2144.txt>`_.
153
154.. note:: Blowfish supports key lengths as small as 32 bits (4 bytes), but
155 our tests have shown that only lengths of 128 bits (16 bytes) or
156 higher are properly supported by both MCrypt and OpenSSL. It is
157 also a bad practice to use such low-length keys anyway.
158
159Driver-specific ciphers
160-----------------------
161
162As noted above, MCrypt and OpenSSL support different sets of encryption
163ciphers. For portability reasons and because we haven't tested them
164properly, we do not advise you to use the ones that are driver-specific,
165but regardless, here's a list of most of them:
166
167
168============== ========= ============================== =========================================
169Cipher name Driver Key lengths (bits / bytes) Supported modes
170============== ========= ============================== =========================================
171AES-128 OpenSSL 128 / 16 CBC, CTR, CFB, CFB8, OFB, ECB, GCM, XTS
172AES-192 OpenSSL 192 / 24 CBC, CTR, CFB, CFB8, OFB, ECB, GCM, XTS
173AES-256 OpenSSL 256 / 32 CBC, CTR, CFB, CFB8, OFB, ECB, GCM, XTS
174Rijndael-128 MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
175Rijndael-192 MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
176Rijndael-256 MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
177GOST MCrypt 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
178Twofish MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
179CAST-256 MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
180Loki97 MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
181SaferPlus MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
182Serpent MCrypt 128 / 16, 192 / 24, 256 / 32 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
183XTEA MCrypt 128 / 16 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
184RC2 MCrypt 8-1024 / 1-128 CBC, CTR, CFB, CFB8, OFB, OFB8, ECB
185RC2 OpenSSL 8-1024 / 1-128 CBC, CFB, OFB, ECB
186Camellia-128 OpenSSL 128 / 16 CBC, CFB, CFB8, OFB, ECB
187Camellia-192 OpenSSL 192 / 24 CBC, CFB, CFB8, OFB, ECB
188Camellia-256 OpenSSL 256 / 32 CBC, CFB, CFB8, OFB, ECB
189Seed OpenSSL 128 / 16 CBC, CFB, OFB, ECB
190============== ========= ============================== =========================================
191
192.. note:: If you wish to use one of those ciphers, you'd have to pass
193 its name in lower-case to the Encryption library.
194
195.. note:: You've probably noticed that all AES cipers (and Rijndael-128)
196 are also listed in the portable ciphers list. This is because
197 drivers support different modes for these ciphers. Also, it is
198 important to note that AES-128 and Rijndael-128 are actually
199 the same cipher, but **only** when used with a 128-bit key.
200
201.. note:: RC2 is listed as supported by both MCrypt and OpenSSL.
202 However, both drivers implement them differently and they
203 are not portable. It is probably worth noting that we only
204 found one obscure source confirming that it is MCrypt that
205 is not properly implementing it.
206
207.. _encryption-modes:
208
209Encryption modes
210----------------
211
212Different modes of encryption have different characteristics and serve
213for different purposes. Some are stronger than others, some are faster
214and some offer extra features.
215We are not going in depth into that here, we'll leave that to the
216cryptography experts. The table below is to provide brief informational
217reference to our more experienced users. If you are a beginner, just
218stick to the CBC mode - it is widely accepted as strong and secure for
219general purposes.
220
221=========== ================== ================= ===================================================================================================================================================
222Mode name CodeIgniter name Driver support Additional info
223=========== ================== ================= ===================================================================================================================================================
224CBC cbc MCrypt, OpenSSL A safe default choice
225CTR ctr MCrypt, OpenSSL Considered as theoretically better than CBC, but not as widely available
226CFB cfb MCrypt, OpenSSL N/A
227CFB8 cfb8 MCrypt, OpenSSL Same as CFB, but operates in 8-bit mode (not recommended).
228OFB ofb MCrypt, OpenSSL N/A
229OFB8 ofb8 MCrypt Same as OFB, but operates in 8-bit mode (not recommended).
230ECB ecb MCrypt, OpenSSL Ignores IV (not recommended).
231GCM gcm OpenSSL Provides authentication and therefore doesn't need a HMAC.
232XTS xts OpenSSL Usually used for encrypting random access data such as RAM or hard-disk storage.
233Stream stream MCrypt, OpenSSL This is not actually a mode, it just says that a stream cipher is being used. Required because of the general cipher+mode initialization process.
234=========== ================== ================= ===================================================================================================================================================
235
236Message Length
237==============
238
239It's probably important for you to know that an encrypted string is usually
240longer than the original, plain-text string (depending on the cipher).
241
242This is influenced by the cipher algorithm itself, the IV prepended to the
243cipher-text and (unless you are using GCM mode) the HMAC authentication
244message that is also prepended. Furthermore, the encrypted message is also
245Base64-encoded so that it is safe for storage and transmission, regardless
246of a possible character set in use.
247
248Keep this information in mind when selecting your data storage mechanism.
249Cookies, for example, can only hold 4K of information.
250
251.. _configuration:
252
253Configuring the library
254=======================
255
256For usability, performance, but also historical reasons tied to our old
257:doc:`Encrypt Class <encrypt>`, the Encryption library is designed to
258use repeatedly the same driver, encryption cipher, mode and key.
259
260As noted in the "Default behavior" section above, this means using an
261auto-detected driver (OpenSSL has a higher priority), the AES-128 ciper
262in CBC mode, and your ``$config['encryption_key']`` value.
263
264If you wish to change that however, you need to use the ``initialize()``
265method. It accepts an associative array of parameters, all of which are
266optional:
267
268======== ===============================================
269Option Possible values
270======== ===============================================
271driver 'mcrypt', 'openssl'
272cipher Cipher name (see :ref:`ciphers-and-modes`)
273mode Encryption mode (see :ref:`encryption-modes`)
274key Encryption key
275======== ===============================================
276
277For example, if you were to change the encryption algorithm and
278mode to AES-256 in CTR mode, this is what you should do::
279
280 $this->encryption->initialize(
281 array(
282 'cipher' => 'aes-256',
283 'mode' => 'ctr',
284 'key' => '<a 32-character random string>'
285 )
286 );
287
288Note that we only mentioned that you want to change the ciper and mode,
289but we also included a key in the example. As previously noted, it is
290important that you choose a key with a proper size for the used algorithm.
291
292There's also the ability to change the driver, if for some reason you
293have both, but want to use MCrypt instead of OpenSSL::
294
295 // Switch to the MCrypt driver
296 $this->encryption->initialize(array('driver' => 'mcrypt'));
297
298 // Switch back to the OpenSSL driver
299 $this->encryption->initialize(array('driver' => 'openssl'));
300
301Encrypting and decrypting data
302==============================
303
304Encrypting and decrypting data with the already configured library
305settings is simple. As simple as just passing the string to the
306``encrypt()`` and/or ``decrypt()`` methods::
307
308 $plain_text = 'This is a plain-text message!';
309 $ciphertext = $this->encryption->encrypt($plain_text);
310
311 // Outputs: This is a plain-text message!
312 echo $this->encryption->decrypt($ciphertext);
313
314And that's it! The Encryption library will do everything necessary
315for the whole process to be cryptographically secure out-of-the-box.
316You don't need to worry about it.
317
318.. important:: Both methods will return FALSE in case of an error.
319 While for ``encrypt()`` this can only mean incorrect
320 configuration, you should always check the return value
321 of ``decrypt()`` in production code.
322
323How it works
324------------
325
326If you must know how the process works, here's what happens under
327the hood:
328
329- ``$this->encryption->encrypt($plain_text)``
330
331 #. Derive an encryption key and a HMAC key from your configured
332 *encryption_key* via HKDF, using the SHA-512 digest algorithm.
333
334 #. Generate a random initialization vector (IV).
335
336 #. Encrypt the data via AES-128 in CBC mode (or another previously
337 configured cipher and mode), using the above-mentioned derived
338 encryption key and IV.
339
340 #. Prepend said IV to the resulting cipher-text.
341
342 #. Base64-encode the resulting string, so that it can be safely
343 stored or transferred without worrying about character sets.
344
345 #. Create a SHA-512 HMAC authentication message using the derived
346 HMAC key to ensure data integrity and prepend it to the Base64
347 string.
348
349- ``$this->encryption->decrypt($ciphertext)``
350
351 #. Derive an encryption key and a HMAC key from your configured
352 *encryption_key* via HKDF, using the SHA-512 digest algorithm.
353 Because your configured *encryption_key* is the same, this
354 will produce the same result as in the ``encrypt()`` method
355 above - otherwise you won't be able to decrypt it.
356
357 #. Check if the string is long enough, separate the HMAC out of
358 it and validate if it is correct (this is done in a way that
359 prevents timing attacks agains it). Return FALSE if either of
360 the checks fails.
361
362 #. Base64-decode the string.
363
364 #. Separate the IV out of the cipher-text and decrypt the said
365 cipher-text using that IV and the derived encryption key.
366
367.. _custom-parameters:
368
369Using custom parameters
370-----------------------
371
372Let's say you have to interact with another system that is out
373of your control and uses another method to encrypt data. A
374method that will most certainly not match the above-described
375sequence and probably not use all of the steps either.
376
377The Encryption library allows you to change how its encryption
378and decryption processes work, so that you can easily tailor a
379custom solution for such situations.
380
381.. note:: It is possible to use the library in this way, without
382 setting an *encryption_key* in your configuration file.
383
384All you have to do is to pass an associative array with a few
385parameters to either the ``encrypt()`` or ``decrypt()`` method.
386Here's an example::
387
388 // Assume that we have $ciphertext, $key and $hmac_key
389 // from on outside source
390
391 $message = $this->encryption->decrypt(
392 $ciphertext,
393 array(
394 'cipher' => 'blowfish',
395 'mode' => 'cbc',
396 'key' => $key,
397 'hmac_digest' => 'sha256',
398 'hmac_key' => $hmac_key
399 )
400 );
401
402In the above example, we are decrypting a message that was encrypted
403using the Blowfish cipher in CBC mode and authenticated via a SHA-256
404HMAC.
405
406.. important:: Note that both 'key' and 'hmac_key' are used in this
407 example. When using custom parameters, encryption and HMAC keys
408 are not derived like the default behavior of the library is.
409
410Below is a list of the available options.
411
412However, unless you really need to and you know what you are doing,
413we advise you to not change the encryption process as this could
414impact security, so please do so with caution.
415
416============= =============== ============================= ======================================================
417Option Default value Mandatory / Optional Description
418============= =============== ============================= ======================================================
419cipher N/A Yes Encryption algorithm (see :ref:`ciphers-and-modes`).
420mode N/A Yes Encryption mode (see :ref:`encryption-modes`).
421key N/A Yes Encryption key.
422iv N/A No Initialization vector (IV).
423 If not provided it will be automatically generated
424 during encryption and looked for during decryption.
425hmac TRUE No Whether to use a HMAC.
426 Boolean. If set to FALSE, then *hmac_digest* and
427 *hmac_key* will be ignored.
428hmac_digest sha512 No HMAC message digest algorithm (see :ref:`digests`).
429hmac_key N/A Yes, unless *hmac* is FALSE HMAC key.
430raw_data FALSE No Whether the cipher-text should be raw.
431 Boolean. If set to TRUE, then Base64 encoding and
432 decoding will not be performed and HMAC will not
433 be a hexadecimal string.
434============= =============== ============================= ======================================================
435
436.. important:: ``encrypt()`` and ``decrypt()`` will return FALSE if
437 a mandatory parameter is not provided or if a provided
438 value is incorrect. This includes *hmac_key*, unless *hmac*
439 is set to FALSE.
440
441.. note:: If GCM mode is used, *hmac* will always be FALSE. This is
442 because GCM mode itself provides authentication.
443
444.. _digests:
445
446Supported HMAC authentication algorithms
447----------------------------------------
448
449For HMAC message authentication, the Encryption library supports
450usage of the SHA-2 family of algorithms:
451
452=========== ==================== ============================
453Algorithm Raw length (bytes) Hex-encoded length (bytes)
454=========== ==================== ============================
455sha512 64 128
456sha384 48 96
457sha256 32 64
458sha224 28 56
459=========== ==================== ============================
460
461The reason for not including other popular algorithms, such as
462MD5 or SHA1 is that they are no longer considered secure enough
463and as such, we don't want to encourage their usage.
464If you absolutely need to use them, it is easy to do so via PHP's
465native `hash_hmac() <http://php.net/hash_hmac()>`_ function.
466
467Stronger algorithms of course will be added in the future as they
468appear and become widely available.
469
470***************
471Class Reference
472***************
473
474.. class:: CI_Encryption
475
476 .. method:: initialize($params)
477
478 :param array $params: Configuration parameters
479 :returns: CI_Encryption instance (method chaining)
480 :rtype: CI_Encryption
481
482 Initializes (configures) the library to use a different
483 driver, cipher, mode or key.
484
485 Example::
486
487 $this->encryption->initialize(
488 array('mode' => 'ctr')
489 );
490
491 Please refer to the :ref:`configuration` section for detailed info.
492
493 .. method:: encrypt($data[, $params = NULL])
494
495 :param string $data: Data to encrypt
496 :param array $params: Optional parameters
497 :returns: Encrypted data or FALSE on failure
498 :rtype: string
499
500 Encrypts the input data and returns its ciphertext.
501
502 Example::
503
504 $ciphertext = $this->encryption->encrypt('My secret message');
505
506 Please refer to the :ref:`custom-parameters` section for information
507 on the optional parameters.
508
509 .. method:: decrypt($data[, $params = NULL])
510
511 :param string $data: Data to decrypt
512 :param array $params: Optional parameters
513 :returns: Decrypted data or FALSE on failure
514 :rtype: string
515
516 Decrypts the input data and returns it in plain-text.
517
518 Example::
519
520 echo $this->encryption->decrypt($ciphertext);
521
522 Please refer to the :ref:`custom-parameters` secrion for information
523 on the optional parameters.
524
525 .. method:: hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])
526
527 :param string $key: Input key material
528 :param string $digest: A SHA-2 family digest algorithm
529 :param string $salt: Optional salt
530 :param int $length: Optional output length
531 :param string $info: Optional context/application-specific info
532 :returns: A pseudo-random key or FALSE on failure
533
534 Derives a key from another, presumably weaker key.
535
536 This method is used internally to derive an encryption and HMAC key
537 from your configured *encryption_key*.
538
539 It is publicly available due to its otherwise general purpose. It is
540 described in `RFC 5869 <https://tools.ietf.org/rfc/rfc5869.txt>`_.
541
542 However, as opposed to the description in RFC 5869, this implementation
543 doesn't support SHA1.
544
545 Example::
546
547 $hmac_key = $this->encryption->hkdf(
548 $key,
549 'sha512',
550 NULL,
551 NULL,
552 'authentication'
553 );
554
555 // $hmac_key is a pseudo-random key with a length of 64 bytes