Encryption Library
******************

Important:

  DO NOT use this or any other *encryption* library for user password
  storage! Passwords must be *hashed* instead, and you should do that
  via PHP’s own Password Hashing extension.

The Encryption Library provides two-way data encryption. To do so in a
cryptographically secure way, it utilizes PHP extensions that are
unfortunately not always available on all systems. You must meet one
of the following dependencies in order to use this library:

* OpenSSL

* MCrypt (and *MCRYPT_DEV_URANDOM* availability)

If neither of the above dependencies is met, we simply cannot offer
you a good enough implementation to meet the high standards required
for proper cryptography.

* Using the Encryption Library

  * Initializing the Class

  * Default behavior

  * Setting your encryption_key

  * Supported encryption ciphers and modes

    * Portable ciphers

    * Driver-specific ciphers

    * Encryption modes

  * Message Length

  * Configuring the library

  * Encrypting and decrypting data

    * How it works

    * Using custom parameters

    * Supported HMAC authentication algorithms

* Class Reference


Using the Encryption Library
============================


Initializing the Class
----------------------

Like most other classes in CodeIgniter, the Encryption library is
initialized in your controller using the "$this->load->library()"
method:

   $this->load->library('encryption');

Once loaded, the Encryption library object will be available using:

   $this->encryption


Default behavior
----------------

By default, the Encryption Library will use the AES-128 cipher in CBC
mode, using your configured *encryption_key* and SHA512 HMAC
authentication.

Note:

  AES-128 is chosen both because it is proven to be strong and because
  of its wide availability across different cryptographic software and
  programming languages’ APIs.

However, the *encryption_key* is not used as is.

If you are somewhat familiar with cryptography, you should already
know that a HMAC also requires a secret key and using the same key for
both encryption and authentication is a bad practice.

Because of that, two separate keys are derived from your already
configured *encryption_key*: one for encryption and one for
authentication. This is done via a technique called HMAC-based Key
Derivation Function (HKDF).


Setting your encryption_key
---------------------------

An *encryption key* is a piece of information that controls the
cryptographic process and permits a plain-text string to be encrypted,
and afterwards - decrypted. It is the secret “ingredient” in the whole
process that allows you to be the only one who is able to decrypt data
that you’ve decided to hide from the eyes of the public. After one key
is used to encrypt data, that same key provides the **only** means to
decrypt it, so not only must you chose one carefully, but you must not
lose it or you will also lose access to the data.

It must be noted that to ensure maximum security, such key *should*
not only be as strong as possible, but also often changed. Such
behavior however is rarely practical or possible to implement, and
that is why CodeIgniter gives you the ability to configure a single
key that is to be used (almost) every time.

It goes without saying that you should guard your key carefully.
Should someone gain access to your key, the data will be easily
decrypted. If your server is not totally under your control it’s
impossible to ensure key security so you may want to think carefully
before using it for anything that requires high security, like storing
credit card numbers.

Your encryption key **must** be as long as the encyption algorithm in
use allows. For AES-128, that’s 128 bits or 16 bytes (charcters) long.
You will find a table below that shows the supported key lengths of
different ciphers.

The key should be as random as possible and it **must not** be a
regular text string, nor the output of a hashing function, etc. In
order to create a proper key, you must use the Encryption library’s
"create_key()" method

   // $key will be assigned a 16-byte (128-bit) random key
   $key = $this->encryption->create_key(16);

The key can be either stored in your *application/config/config.php*,
or you can design your own storage mechanism and pass the key
dynamically when encrypting/decrypting.

To save your key to your *application/config/config.php*, open the
file and set:

   $config['encryption_key'] = 'YOUR KEY';

You’ll notice that the "create_key()" method outputs binary data,
which is hard to deal with (i.e. a copy-paste may damage it), so you
may use "bin2hex()", "hex2bin()" or Base64-encoding to work with the
key in a more friendly manner. For example:

   // Get a hex-encoded representation of the key:
   $key = bin2hex($this->encryption->create_key(16));

   // Put the same value in your config with hex2bin(),
   // so that it is still passed as binary to the library:
   $config['encryption_key'] = hex2bin(<your hex-encoded key>);


Supported encryption ciphers and modes
--------------------------------------

Note:

  The terms ‘cipher’ and ‘encryption algorithm’ are interchangeable.


Portable ciphers
~~~~~~~~~~~~~~~~

Because MCrypt and OpenSSL (also called drivers throughout this
document) each support different sets of encryption algorithms and
often implement them in different ways, our Encryption library is
designed to use them in a portable fashion, or in other words - it
enables you to use them interchangeably, at least for the ciphers
supported by both drivers.

It is also implemented in a way that aims to match the standard
implementations in other programming languages and libraries.

Here’s a list of the so called “portable” ciphers, where “CodeIgniter
name” is the string value that you’d have to pass to the Encryption
library to use that cipher:

+--------------------------+--------------------+------------------------------+---------------------------------+
| Cipher name              | CodeIgniter name   | Key lengths (bits / bytes)   | Supported modes                 |
|==========================|====================|==============================|=================================|
| AES-128 / Rijndael-128   | aes-128            | 128 / 16                     | CBC, CTR, CFB, CFB8, OFB, ECB   |
+--------------------------+--------------------+------------------------------+---------------------------------+
| AES-192                  | aes-192            | 192 / 24                     | CBC, CTR, CFB, CFB8, OFB, ECB   |
+--------------------------+--------------------+------------------------------+---------------------------------+
| AES-256                  | aes-256            | 256 / 32                     | CBC, CTR, CFB, CFB8, OFB, ECB   |
+--------------------------+--------------------+------------------------------+---------------------------------+
| DES                      | des                | 56 / 7                       | CBC, CFB, CFB8, OFB, ECB        |
+--------------------------+--------------------+------------------------------+---------------------------------+
| TripleDES                | tripledes          | 56 / 7, 112 / 14, 168 / 21   | CBC, CFB, CFB8, OFB             |
+--------------------------+--------------------+------------------------------+---------------------------------+
| Blowfish                 | blowfish           | 128-448 / 16-56              | CBC, CFB, OFB, ECB              |
+--------------------------+--------------------+------------------------------+---------------------------------+
| CAST5 / CAST-128         | cast5              | 88-128 / 11-16               | CBC, CFB, OFB, ECB              |
+--------------------------+--------------------+------------------------------+---------------------------------+
| RC4 / ARCFour            | rc4                | 40-2048 / 5-256              | Stream                          |
+--------------------------+--------------------+------------------------------+---------------------------------+

Important:

  Because of how MCrypt works, if you fail to provide a key with the
  appropriate length, you might end up using a different algorithm
  than the one configured, so be really careful with that!

Note:

  In case it isn’t clear from the above table, Blowfish, CAST5 and RC4
  support variable length keys. That is, any number in the shown
  ranges is valid, although in bit terms that only happens in 8-bit
  increments.

Note:

  Even though CAST5 supports key lengths lower than 128 bits (16
  bytes), in fact they will just be zero-padded to the maximum length,
  as specified in RFC 2144.

Note:

  Blowfish supports key lengths as small as 32 bits (4 bytes), but our
  tests have shown that only lengths of 128 bits (16 bytes) or higher
  are properly supported by both MCrypt and OpenSSL. It is also a bad
  practice to use such low-length keys anyway.


Driver-specific ciphers
~~~~~~~~~~~~~~~~~~~~~~~

As noted above, MCrypt and OpenSSL support different sets of
encryption ciphers. For portability reasons and because we haven’t
tested them properly, we do not advise you to use the ones that are
driver-specific, but regardless, here’s a list of most of them:

+----------------+-----------+--------------------------------+-------------------------------------------+
| Cipher name    | Driver    | Key lengths (bits / bytes)     | Supported modes                           |
|================|===========|================================|===========================================|
| AES-128        | OpenSSL   | 128 / 16                       | CBC, CTR, CFB, CFB8, OFB, ECB, XTS        |
+----------------+-----------+--------------------------------+-------------------------------------------+
| AES-192        | OpenSSL   | 192 / 24                       | CBC, CTR, CFB, CFB8, OFB, ECB, XTS        |
+----------------+-----------+--------------------------------+-------------------------------------------+
| AES-256        | OpenSSL   | 256 / 32                       | CBC, CTR, CFB, CFB8, OFB, ECB, XTS        |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Rijndael-128   | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Rijndael-192   | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Rijndael-256   | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| GOST           | MCrypt    | 256 / 32                       | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Twofish        | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| CAST-128       | MCrypt    | 40-128 / 5-16                  | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| CAST-256       | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Loki97         | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| SaferPlus      | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Serpent        | MCrypt    | 128 / 16, 192 / 24, 256 / 32   | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| XTEA           | MCrypt    | 128 / 16                       | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| RC2            | MCrypt    | 8-1024 / 1-128                 | CBC, CTR, CFB, CFB8, OFB, OFB8, ECB       |
+----------------+-----------+--------------------------------+-------------------------------------------+
| RC2            | OpenSSL   | 8-1024 / 1-128                 | CBC, CFB, OFB, ECB                        |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Camellia-128   | OpenSSL   | 128 / 16                       | CBC, CFB, CFB8, OFB, ECB                  |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Camellia-192   | OpenSSL   | 192 / 24                       | CBC, CFB, CFB8, OFB, ECB                  |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Camellia-256   | OpenSSL   | 256 / 32                       | CBC, CFB, CFB8, OFB, ECB                  |
+----------------+-----------+--------------------------------+-------------------------------------------+
| Seed           | OpenSSL   | 128 / 16                       | CBC, CFB, OFB, ECB                        |
+----------------+-----------+--------------------------------+-------------------------------------------+

Note:

  If you wish to use one of those ciphers, you’d have to pass its name
  in lower-case to the Encryption library.

Note:

  You’ve probably noticed that all AES cipers (and Rijndael-128) are
  also listed in the portable ciphers list. This is because drivers
  support different modes for these ciphers. Also, it is important to
  note that AES-128 and Rijndael-128 are actually the same cipher, but
  **only** when used with a 128-bit key.

Note:

  CAST-128 / CAST-5 is also listed in both the portable and driver-
  specific ciphers list. This is because OpenSSL’s implementation
  doesn’t appear to be working correctly with key sizes of 80 bits and
  lower.

Note:

  RC2 is listed as supported by both MCrypt and OpenSSL. However, both
  drivers implement them differently and they are not portable. It is
  probably worth noting that we only found one obscure source
  confirming that it is MCrypt that is not properly implementing it.


Encryption modes
~~~~~~~~~~~~~~~~

Different modes of encryption have different characteristics and serve
for different purposes. Some are stronger than others, some are faster
and some offer extra features. We are not going in depth into that
here, we’ll leave that to the cryptography experts. The table below is
to provide brief informational reference to our more experienced
users. If you are a beginner, just stick to the CBC mode - it is
widely accepted as strong and secure for general purposes.

+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| Mode name   | CodeIgniter name   | Driver support    | Additional info                                                                                                                                     |
|=============|====================|===================|=====================================================================================================================================================|
| CBC         | cbc                | MCrypt, OpenSSL   | A safe default choice                                                                                                                               |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| CTR         | ctr                | MCrypt, OpenSSL   | Considered as theoretically better than CBC, but not as widely available                                                                            |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| CFB         | cfb                | MCrypt, OpenSSL   | N/A                                                                                                                                                 |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| CFB8        | cfb8               | MCrypt, OpenSSL   | Same as CFB, but operates in 8-bit mode (not recommended).                                                                                          |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| OFB         | ofb                | MCrypt, OpenSSL   | N/A                                                                                                                                                 |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| OFB8        | ofb8               | MCrypt            | Same as OFB, but operates in 8-bit mode (not recommended).                                                                                          |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| ECB         | ecb                | MCrypt, OpenSSL   | Ignores IV (not recommended).                                                                                                                       |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| XTS         | xts                | OpenSSL           | Usually used for encrypting random access data such as RAM or hard- disk storage.                                                                   |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+
| Stream      | 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.   |
+-------------+--------------------+-------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------+


Message Length
--------------

It’s probably important for you to know that an encrypted string is
usually longer than the original, plain-text string (depending on the
cipher).

This is influenced by the cipher algorithm itself, the IV prepended to
the cipher-text and the HMAC authentication message that is also
prepended. Furthermore, the encrypted message is also Base64-encoded
so that it is safe for storage and transmission, regardless of a
possible character set in use.

Keep this information in mind when selecting your data storage
mechanism. Cookies, for example, can only hold 4K of information.


Configuring the library
-----------------------

For usability, performance, but also historical reasons tied to our
old Encrypt Class, the Encryption library is designed to use
repeatedly the same driver, encryption cipher, mode and key.

As noted in the “Default behavior” section above, this means using an
auto-detected driver (OpenSSL has a higher priority), the AES-128
ciper in CBC mode, and your "$config['encryption_key']" value.

If you wish to change that however, you need to use the "initialize()"
method. It accepts an associative array of parameters, all of which
are optional:

+----------+-------------------------------------------------+
| Option   | Possible values                                 |
|==========|=================================================|
| driver   | ‘mcrypt’, ‘openssl’                             |
+----------+-------------------------------------------------+
| cipher   | Cipher name (see Supported encryption ciphers   |
|          | and modes)                                      |
+----------+-------------------------------------------------+
| mode     | Encryption mode (see Encryption modes)          |
+----------+-------------------------------------------------+
| key      | Encryption key                                  |
+----------+-------------------------------------------------+

For example, if you were to change the encryption algorithm and mode
to AES-256 in CTR mode, this is what you should do:

   $this->encryption->initialize(
           array(
                   'cipher' => 'aes-256',
                   'mode' => 'ctr',
                   'key' => '<a 32-character random string>'
           )
   );

Note that we only mentioned that you want to change the ciper and
mode, but we also included a key in the example. As previously noted,
it is important that you choose a key with a proper size for the used
algorithm.

There’s also the ability to change the driver, if for some reason you
have both, but want to use MCrypt instead of OpenSSL:

   // Switch to the MCrypt driver
   $this->encryption->initialize(array('driver' => 'mcrypt'));

   // Switch back to the OpenSSL driver
   $this->encryption->initialize(array('driver' => 'openssl'));


Encrypting and decrypting data
------------------------------

Encrypting and decrypting data with the already configured library
settings is simple. As simple as just passing the string to the
"encrypt()" and/or "decrypt()" methods:

   $plain_text = 'This is a plain-text message!';
   $ciphertext = $this->encryption->encrypt($plain_text);

   // Outputs: This is a plain-text message!
   echo $this->encryption->decrypt($ciphertext);

And that’s it! The Encryption library will do everything necessary for
the whole process to be cryptographically secure out-of-the-box. You
don’t need to worry about it.

Important:

  Both methods will return FALSE in case of an error. While for
  "encrypt()" this can only mean incorrect configuration, you should
  always check the return value of "decrypt()" in production code.


How it works
~~~~~~~~~~~~

If you must know how the process works, here’s what happens under the
hood:

* "$this->encryption->encrypt($plain_text)"

  1. Derive an encryption key and a HMAC key from your configured
     *encryption_key* via HKDF, using the SHA-512 digest algorithm.

  2. Generate a random initialization vector (IV).

  3. Encrypt the data via AES-128 in CBC mode (or another previously
     configured cipher and mode), using the above-mentioned derived
     encryption key and IV.

  4. Prepend said IV to the resulting cipher-text.

  5. Base64-encode the resulting string, so that it can be safely
     stored or transferred without worrying about character sets.

  6. Create a SHA-512 HMAC authentication message using the derived
     HMAC key to ensure data integrity and prepend it to the Base64
     string.

* "$this->encryption->decrypt($ciphertext)"

  1. Derive an encryption key and a HMAC key from your configured
     *encryption_key* via HKDF, using the SHA-512 digest algorithm.
     Because your configured *encryption_key* is the same, this will
     produce the same result as in the "encrypt()" method above -
     otherwise you won’t be able to decrypt it.

  2. Check if the string is long enough, separate the HMAC out of it
     and validate if it is correct (this is done in a way that
     prevents timing attacks against it). Return FALSE if either of
     the checks fails.

  3. Base64-decode the string.

  4. Separate the IV out of the cipher-text and decrypt the said
     cipher-text using that IV and the derived encryption key.


Using custom parameters
~~~~~~~~~~~~~~~~~~~~~~~

Let’s say you have to interact with another system that is out of your
control and uses another method to encrypt data. A method that will
most certainly not match the above-described sequence and probably not
use all of the steps either.

The Encryption library allows you to change how its encryption and
decryption processes work, so that you can easily tailor a custom
solution for such situations.

Note:

  It is possible to use the library in this way, without setting an
  *encryption_key* in your configuration file.

All you have to do is to pass an associative array with a few
parameters to either the "encrypt()" or "decrypt()" method. Here’s an
example:

   // Assume that we have $ciphertext, $key and $hmac_key
   // from on outside source

   $message = $this->encryption->decrypt(
           $ciphertext,
           array(
                   'cipher' => 'blowfish',
                   'mode' => 'cbc',
                   'key' => $key,
                   'hmac_digest' => 'sha256',
                   'hmac_key' => $hmac_key
           )
   );

In the above example, we are decrypting a message that was encrypted
using the Blowfish cipher in CBC mode and authenticated via a SHA-256
HMAC.

Important:

  Note that both ‘key’ and ‘hmac_key’ are used in this example. When
  using custom parameters, encryption and HMAC keys are not derived
  like the default behavior of the library is.

Below is a list of the available options.

However, unless you really need to and you know what you are doing, we
advise you to not change the encryption process as this could impact
security, so please do so with caution.

+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| Option        | Default value   | Mandatory / Optional          | Description                                            |
|===============|=================|===============================|========================================================|
| cipher        | N/A             | Yes                           | Encryption algorithm (see Supported encryption ciphers |
|               |                 |                               | and modes).                                            |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| mode          | N/A             | Yes                           | Encryption mode (see Encryption modes).                |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| key           | N/A             | Yes                           | Encryption key.                                        |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| hmac          | TRUE            | No                            | Whether to use a HMAC. Boolean. If set to FALSE, then  |
|               |                 |                               | *hmac_digest* and *hmac_key* will be ignored.          |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| hmac_digest   | sha512          | No                            | HMAC message digest algorithm (see Supported HMAC      |
|               |                 |                               | authentication algorithms).                            |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| hmac_key      | N/A             | Yes, unless *hmac* is FALSE   | HMAC key.                                              |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+
| raw_data      | FALSE           | No                            | Whether the cipher-text should be raw. Boolean. If set |
|               |                 |                               | to TRUE, then Base64 encoding and decoding will not be |
|               |                 |                               | performed and HMAC will not be a hexadecimal string.   |
+---------------+-----------------+-------------------------------+--------------------------------------------------------+

Important:

  "encrypt()" and "decrypt()" will return FALSE if a mandatory
  parameter is not provided or if a provided value is incorrect. This
  includes *hmac_key*, unless *hmac* is set to FALSE.


Supported HMAC authentication algorithms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

For HMAC message authentication, the Encryption library supports usage
of the SHA-2 family of algorithms:

+-------------+----------------------+------------------------------+
| Algorithm   | Raw length (bytes)   | Hex-encoded length (bytes)   |
|=============|======================|==============================|
| sha512      | 64                   | 128                          |
+-------------+----------------------+------------------------------+
| sha384      | 48                   | 96                           |
+-------------+----------------------+------------------------------+
| sha256      | 32                   | 64                           |
+-------------+----------------------+------------------------------+
| sha224      | 28                   | 56                           |
+-------------+----------------------+------------------------------+

The reason for not including other popular algorithms, such as MD5 or
SHA1 is that they are no longer considered secure enough and as such,
we don’t want to encourage their usage. If you absolutely need to use
them, it is easy to do so via PHP’s native hash_hmac() function.

Stronger algorithms of course will be added in the future as they
appear and become widely available.


Class Reference
===============

class CI_Encryption

   initialize($params)

      Parameters:
         * **$params** ("array") – Configuration parameters

      Returns:
         CI_Encryption instance (method chaining)

      Return type:
         "CI_Encryption"

      Initializes (configures) the library to use a different driver,
      cipher, mode or key.

      Example:

         $this->encryption->initialize(
                 array('mode' => 'ctr')
         );

      Please refer to the Configuring the library section for detailed
      info.

   encrypt($data[, $params = NULL])

      Parameters:
         * **$data** ("string") – Data to encrypt

         * **$params** ("array") – Optional parameters

      Returns:
         Encrypted data or FALSE on failure

      Return type:
         "string"

      Encrypts the input data and returns its ciphertext.

      Example:

         $ciphertext = $this->encryption->encrypt('My secret message');

      Please refer to the Using custom parameters section for
      information on the optional parameters.

   decrypt($data[, $params = NULL])

      Parameters:
         * **$data** ("string") – Data to decrypt

         * **$params** ("array") – Optional parameters

      Returns:
         Decrypted data or FALSE on failure

      Return type:
         "string"

      Decrypts the input data and returns it in plain-text.

      Example:

         echo $this->encryption->decrypt($ciphertext);

      Please refer to the Using custom parameters secrion for
      information on the optional parameters.

   create_key($length)

      Parameters:
         * **$length** ("int") – Output length

      Returns:
         A pseudo-random cryptographic key with the specified length,
         or FALSE on failure

      Return type:
         "string"

      Creates a cryptographic key by fetching random data from the
      operating system’s sources (i.e. /dev/urandom).

   hkdf($key[, $digest = 'sha512'[, $salt = NULL[, $length = NULL[, $info = '']]]])

      Parameters:
         * **$key** ("string") – Input key material

         * **$digest** ("string") – A SHA-2 family digest algorithm

         * **$salt** ("string") – Optional salt

         * **$length** ("int") – Optional output length

         * **$info** ("string") – Optional context/application-
           specific info

      Returns:
         A pseudo-random key or FALSE on failure

      Return type:
         "string"

      Derives a key from another, presumably weaker key.

      This method is used internally to derive an encryption and HMAC
      key from your configured *encryption_key*.

      It is publicly available due to its otherwise general purpose.
      It is described in RFC 5869.

      However, as opposed to the description in RFC 5869, this
      implementation doesn’t support SHA1.

      Example:

         $hmac_key = $this->encryption->hkdf(
                 $key,
                 'sha512',
                 NULL,
                 NULL,
                 'authentication'
         );

         // $hmac_key is a pseudo-random key with a length of 64 bytes
