If you want to avoid storing sensitive DB data (like passport numbers) as plain text, Laravel can encrypt it in Eloquent Models by simply casting it as encrypted
. Let's see how it works.
It looks something like this:
We don't want our user passport numbers stored in plain text in our database, so encryption is a great way to protect it. This can encrypt any data in your models, not just user data.
Database Setup
Our database does not need anything special here. You must ensure that the column you want to encrypt is a string
/text
column (based on the data amount), even if the original value contains only numbers, like passport numbers in our case.
Model Setup
In our model, we need to add the protected $casts
property and the column we want to encrypt. In our case, it is passport_number
:
// ... protected function casts(): array{ return [ 'passport_number' => 'encrypted', ];} // ...
That's it! Now, whenever you save the passport number on your user model - it will be encrypted, and on retrieval, it will get decrypted. How cool is that?
IMPORTANT WARNING: Protect Your App Key
The encryption algorithm mentioned above is based on your application's APP_KEY
value. In your .env
file, you should have something like this:
APP_KEY=base64:QikAJAlo0evYLq2RYFxGv/PRrSIfJcNDj2qiFRp1oUs=
When talking about encryption, you must keep your APP_KEY
safe. If someone gets access to it - they can decrypt all your encrypted data. So please keep it safe and don't share it with anyone.
What Happens If You Change Your App Key?
Your APP_KEY
is re-generated whenever you run php artisan key:generate
. But what happens to your encrypted data if you change your APP_KEY
?
The encrypted data is lost
That's right. If you change your APP_KEY
- all your encrypted data will be lost. This is because this key is used for the encryption/decryption, and changing it - messes up the decryption process. Just look at this example:
And if we change the key:
So the main idea is this: DO NOT RUN key:generate ON PRODUCTION SERVER.
Be careful with your APP_KEY
and don't lose it. It's a good idea to keep a backup of it somewhere safe.
I have a belief that when attacker got access to the data stored in DB, it DOES mean that it has an access to the file system as well. Thus, in my opinion, encrypting data stored in DB is not the all-in-one solution. Better stick to improving overall security of your application, like preventing data leaks via sql injections, remote code execution, check your file permissions as well
There is couple of things to unravel here, so let's do it:
Overall, you are right on the part that you need to improve overall security of the application. But this was not targeted at that. This was targeted at compliance and hiding the data in the database. That's all it does.
Yeah, you are right. However, I meant a standard Laravel application where both DB & files stored on the same server, usually on a shared hosting server. In the best case scenario, it is correct - DB on the remote server makes encrypted data useless for an attacker unless he has a key AND this key is stored securely.
Never thought about this package from the GDPR-alike compliance side, though 🤔
Well, this is where our standards differ I would say. For me a standard setup is:
VPS server with files + db -> insensitive data
VPS server with files + separate VPS server for database -> sensitive data
As for shared servers... I never recommend them to anyone and they should be left in the past IMHO :)
these do not differ. I am just taking into account most publicly available Laravel apps, but my course of action for any my Laravel peoject would be the same as your :)