Security Tip: Custom Encryption Keys for Cast Model Attributes
[Tip#1] A simple but quite important tip, how to use a custom encryption key for encrypted casting within Models.
Laravel allows you to cast model attributes as encrypted strings, when storing them in the database. This gives you added security for any values that are sensitive (such as Personally identifiable information, PII), including complex structures such as arrays, collections, and even objects.
class User extends Model
{
protected $casts = ['secrets' => 'encrypted:array'];
}
The downside is, Laravel uses the default application encryption key to encrypt the value. This opens up the potential risk of a hacker being able to encrypt a specially crafted payload and then retrieve the encrypted value somehow.
The solution is quite easy though, we can use the Model::encryptUsing()
method, which was added to Laravel by Illia Sakovich. It allows us to define a custom Encrypter for use by the Model when encrypting data, which lets us use a different encryption key.
First, generate a new encryption key and add it into .env
:
php artisan key:generate --show
Next, load that into your application config - something like database.encryption_key
might make sense, given it’s for the database model encryption.
Finally, update your AppServiceProvider
to load the new encryption key into the model:
namespace App\Providers;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Encryption\Encrypter;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
$key = $this->databaseEncryptionKey();
$cipher = config('app.cipher');
Model::encryptUsing(new Encrypter($key, $cipher));
}
protected function databaseEncryptionKey(): ?string
{
$key = config('database.encryption_key');
return base64_decode(Str::after($key, 'base64:'));
}
}
You can find all the code in this Gist: https://gist.github.com/valorin/ce58cf55dedaf759b3aa7fcfb2fcf613.
That should do it.
Your encrypted casts should now use a custom key, keeping your application key safe.
Found this security tip helpful? Don't forget to subscribe to receive new Security Tips each week, and upgrade to a premium subscription to receive monthly In Depth articles, or toss a coin in the tip jar.
You can follow Stephen on Twitter, Fediverse, LinkedIn, Pinkary, Bluesky, and Threads, and reach out if you're looking for a Laravel Security Audit and Penetration Test or a budget-friendly Security Review.
Finally, to learn more about security through a series of interactive challenges, check out Stephen's new course: Practical Laravel Security.