November 30, 2016 —John Koster
Laravel provides support for AES encryption, a symmetric key encryption scheme, right out of the box. Laravel also automatically signs all encrypted values with a message authentication code (MAC) so that any modifications to the encrypted data can be detected. Laravel internally accomplishes this through various methods built around PHP's hash_hmac
function. SHA256 is used as the hashing function when calculating the MAC hash.
Laravel provides a very simple API for interacting with the encryption services. It defines a Illuminate\Contracts\Encryption\Encrypter
interface, which all encryption classes must implement. The Encrypter
interface defines two methods[^supportedStaticMethod] that be implemented: encrypt($value)
, which is used to encrypt a value and decrypt($payload)
, which is used to decrypt a previously encrypted value.
[^supportedStaticMethod]: All of the default implementations of Encrypter
also define a public static method supported($key, $cipher)
which is used by the Illuminate\Encryption\EncryptionServiceProvider
to determine if the Encrypter
implementation supports the $key
and $cipher
configured for the current application (either in the config/app.php
configuration file, or though the .env
file).
There are two implementations of Encrypter
shipped with Laravel. The first one is the Illuminate\Encryption\Encrypter
implementation, which uses OpenSSL to perform the encryption and decryption. Laravel attempts to use this implementation first. If the key and cipher are not supported by this implementation Laravel then checks to see if the key and cipher are supported by Illuminate\Encryption\McryptEncrypter
, which uses the PHP mcrypt extension to perform the encryption and decryption operations.
The key and cipher for encryption must be set and configured. The cipher is set in the config/app.php
configuration file by changing the value of cipher
. The following table lists the supported ciphers and the Encrypter
(all Encrypter
implementations are relative to the Illuminate\Encryption\
namespace) implementation that will handle them, and the order that they are checked:
Cipher | Encrypter Implementation |
---|---|
AES-128-CBC |
Encrypter |
AES-256-CBC |
Encrypter |
MCRYPT_RIJNDAEL_128 |
McryptEncrypter |
MCRYPT_RIJNDAEL_256 |
McryptEncrypter |
An encryption key must also be configured. Typically this is done by running the following artisan command:
1php artisan key:generate
The key:generate
command will update the application's environment file with the key that is generated during command execution. Encryption keys must be a random, thirty-two character long string. Encryption keys are stored in base 64 encoding for easier storage and retrieval.
It is important to note that if the encryption key needs to be regenerated after an application has been in use, any data that was previously encrypted using the old key cannot be decrypted using the new encryption key. While regenerating the encryption key is not recommended, there are some scenarios where it is beneficial, if not absolutely critical to do so.
When these scenarios arise, the problems can be overcome by decrypting the old data and reapplying the encryption using the new encryption key.
As stated earlier, encryption of data is accomplished by calling the encrypt($$value)
method on an Encrypter
implementation and decryption of data is accomplished by calling the decrypt($payload)
on an Encrypter
implementation. The following code examples will assume the that the cipher was:
1AES-256-CBC
and encryption (application) key was the following:
1r3x4NIxNOsWLJFK2opKqA0q9YEWt9y69
It is not recommended to use the encryption key that is used in this article. Any messages encrypted with the provided key can also be decrypted with the provided key. This key should be used for example purposes only, and should be assumed insecure.
The following code example will encrypt and decrypt the string Hello, Universe
:
1<?php2 3// Get an Encrypter implementation from4// the service container.5$encrypter = app('Illuminate\Contracts\Encryption\Encrypter');6 7// Encrypt the string `Hello, Universe`8$encrypted = $encrypter->encrypt('Hello, Universe');
After the above code has executed, the $encrypted
value would be a string and contain a value similar to the following output (the actual output will change each time the code is ran):
1eyJpdiI6ImhNZTN3eEVFTXFsYVBSN3NPNTlRbnc9PSIsInZhbHVlIjoiZ3FOYTV5SmdlUnZ0UHlrbXdxU3NoRDllKzdGTXlTakdEOG9tTHpEMVRJRT0iLCJtYWMiOiJmOWVhZDkzY2NhMTdjMzQzNDE0MTM0MDBlNTFmZGUwMmQ0MGRkYWYxNzFhZTc5ODI1ZWJlNjIxYzk0MzM2YWFkIn0=
It is very easy to decrypt the encrypted message using the decrypt
method:
1<?php 2 3// A hard-coded encrypted value. 4$encryptedValue = 'eyJpdiI6ImhNZTN3eEVFTXFsYVBSN3NPNTlRb'. 5 'nc9PSIsInZhbHVlIjoiZ3FOYTV5SmdlUnZ0UH'. 6 'lrbXdxU3NoRDllKzdGTXlTakdEOG9tTHpEMVR'. 7 'JRT0iLCJtYWMiOiJmOWVhZDkzY2NhMTdjMzQz'. 8 'NDE0MTM0MDBlNTFmZGUwMmQ0MGRkYWYxNzFhZ'. 9 'Tc5ODI1ZWJlNjIxYzk0MzM2YWFkIn0=';10 11// Decrypt the $encrypted variable.12$decryptedDynamic = $encrypter->decrypt($encrypted);13 14// Decrypt the hard-coded encrypted value.15$decryptedHardCoded = $encrypter->decrypt($encryptedValue);
After the above code has ran, the $decryptedDynamic
and $decryptedHardCoded
variables would both be strings and contain the value Hello, Universe
.
Laravel provides many facades to make it easier to quickly build application and test ideas. One such facade is the Illuminate\Support\Facades\Crypt
facade, which provides access to whatever implementation is bound to the Illuminate\Contracts\Encryption\Encrypter
interface within the service container. The following code example demonstrates the basic usage of the Crypt
facade:
1<?php 2 3use Illuminate\Support\Facades\Crypt; 4 5// Encrypt the message 'Hello, Universe'. 6$encrypted = Crypt::encrypt('Hello, Universe'); 7 8 9// Decrypt the $encrypted message.10$message = Crypt::decrypt($encrypted);
∎
The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.