π‘ I included the link to the example repository at the conclusion of this tutorial.
Encryption is the process of converting data into a format that is unreadable to unauthorized users. This ensures the confidentiality and security of the data. Encrypted data can only be decrypted and read by someone who has the proper decryption key. Data encryption protects sensitive information such as user passwords, personal data, and financial information.
Laravel provides built-in support for encryption to help developers easily secure their applications. Laravel’s encryption services are based on the OpenSSL library and offer a straightforward way to encrypt and decrypt data.
Notes Regarding Encryption in Laravel
There are several notes that we should pay attention to regarding data encryption in Laravel:
- Make sure the column you want to encrypt is a
string
/text
column, even though all the data values ββyou want to encrypt are numbers. - All encrypted values are encrypted using OpenSSL and the AES-256-CBC cipher and signed with a Message Authentication Code (MAC).
- The encryption algorithm is based on your application’s
APP_KEY
value in your.env
file. You must keep yourAPP_KEY
secure. If someone gets access to it, they can decrypt all your encrypted data. - If you lose your
APP_KEY
, you cannot decrypt your data. This is because this key is used for encryption and decryption. - Your
APP_KEY
is regenerated every time you runphp artisan key:generate
. So don’t runkey:generate
unless you want your keys changed (like key rotation). - If you change your application’s encryption key, all authenticated user sessions will be logged out of your application. This is because every cookie, including session cookies, is encrypted by Laravel.
- If you need to rotate your application’s encryption key, you need to manually re-encrypt the encrypted attributes using the new key. But if you don’t want to re-encrypt the data yet, you can include the previous encryption key in your app’s
APP_PREVIOUS_KEYS
environment variable. When you set this environment variable, Laravel will always use the “current” encryption key when encrypting values. However, when decrypting a value, Laravel will try the current key first, and if decryption fails using the current key, Laravel will try all previous keys until one of the keys is able to decrypt the value. TheAPP_PREVIOUS_KEYS
may contain a comma-separated list of all your previous encryption keys:
APP_KEY="base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY="
APP_PREVIOUS_KEYS="base64:2nLsGFGzyoae2ax3EF2Lyq/hH6QghBGLIq5uL+Gp8/w="
- Since the value is encrypted, we will not be able to query or search for it in the database using its raw value, unless, we decrypt all the values ββin the database one by one and check if any of the results match what we are looking for.
Read also:
How to Encrypt and Decrypt Data in Laravel
We can utilize encryptString
method provided by the Crypt
(Illuminate\Support\Facades\Crypt) facade or using the encrypt
helper to encrypt a string.
use Illuminate\Support\Facades\Crypt;
Crypt::encryptString($request->token),
// or using the global helper
encrypt($value)
To decrypt the encrypted value, we can use the decryptString
method provided by the same facade or using the decrypt
helper.
Crypt::decryptString($encryptedValue);
// or using the global helper
decrypt($encryptedValue)
If the value cannot be decrypted, such as when the value is not an encrypted value, DecryptException
(Illuminate\Contracts\Encryption\DecryptException) will be thrown.
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;
try {
$decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
// ...
}
Encrypted Casting
In our model, we can add the column we want to encrypt in the $casts
property so that its value can be automatically encrypted when we store the value and also automatically decrypted when we retrieve it. No need to manually encryptString
and decryptString
the value.
// put it in your model, like User model, or UserDetail model, etc.
protected function casts(): array
{
// for example, I have these columns on my users table:
// $table->string('id_card_number');
// $table->string('driving_license_number');
return [
'id_card_number' => 'encrypted',
'driving_license_number' => 'encrypted',
];
}
Search The Encrypted Data Using Its Raw Values
Using this implementation, you can’t. But as I said, as a workaround, you can decrypt all the values ββin the table one by one and check if they match the value you are looking for.
User::all()->first(fn ($user) => $user->id_card_number === '8274819283712381')
// or using chunk
$user = null;
User::chunk(500, function ($users) use (&$user) {
$user = $users->first(fn ($user) => $user->id_card_number === '8274819283712381');
if ($user) return true;
});
$user;
= App\Models\User {#5081
id: 1002,
name: "Shanel Hintz",
email: "fredrick17@example.com",
email_verified_at: "2024-07-10 20:28:01",
#password: "$2y$12$T.hODmB8zvpIrKWpcLQOWO3kVX4Nc.afPlFow3B3f/QEZyPipJGqK",
id_card_number: "eyJpdiI6IkI4aVR0MVIwNXMvQkhSR1BZWUpWZFE9PSIsInZhbHVlIjoid0Eva0hlVjVyaExwcnZhYTNMVFZIQT09IiwibWFjIjoiMTNkOTI0ODkxNGFhNzJhMmQ5ZjU2ODY0ZGZmYTMyNGQyYmEyOWI2Y2Y0YTRmMGFjMWNhYmRiZTU5ZjlhYjhlZSIsInRhZyI6IiJ9",
driving_license_number: "eyJpdiI6IlNFTjZDcDI4QlhWQVlEbUpYdXFmSEE9PSIsInZhbHVlIjoiNDR3Mk9QanNrUEdWNXp4a210RlNpZz09IiwibWFjIjoiYTU0NWM3MTNjOWEwZDJiYzAxNTgzNjM4ZTk3NjRkYTZjMWE1ZWNkNjRkOGMzMWY5OWQ5Yjg0MDFlNzVlZDg3MCIsInRhZyI6IiJ9",
#remember_token: "QRevtXPcuC",
created_at: "2024-07-10 20:28:03",
updated_at: "2024-07-10 20:28:03",
}
Read also:
In the next article, I’ll introduce a more effective approach for encrypting data while enabling seamless search functionality.
π‘ Check out the article Search and Encrypt Data in Laravel with CipherSweet to learn how to encrypt and search data securely in Laravel.
Conclusion
In this article, we’ve explored the basics of encryption in Laravel, highlighting the importance of data encryption and how Laravel’s built-in support simplifies this process. We’ve seen how to configure and use Laravel’s encryption functions, including encrypting and decrypting data using the Crypt
facade and leveraging encrypted transmission in the model for automatic encryption and decryption.
Additionally, we cover key considerations for encryption in Laravel, such as the importance of keeping your APP_KEY
secure, the implications of changing your encryption key, and the challenges associated with querying encrypted data.
By following these practices, you can improve the security of your Laravel applications and ensure that sensitive information remains protected.
π» The repository for this example can be found at fajarwz/blog-laravel-encrypt.