Data security isn’t a bolt‑on feature; it’s a first‑class requirement. Laravel 12 ships with a polished OpenSSL‑powered encrypter (AES‑256‑CBC by default) and several developer‑friendly APIs that make it almost effortless to protect sensitive information. All encrypted payloads are signed with a message‑authentication code (MAC), so any tampering is detected during decryption.
APP_KEY
Laravel will refuse to encrypt or decrypt anything until a valid 32‑byte base‑64 key is present in .env
:
php artisan key:generate # populates APP_KEY
Commit only .env.example
; keep real keys in a secret manager. If the key leaks, rotate it immediately.
Laravel 12 lets you list old keys in APP_PREVIOUS_KEYS
so legacy data continues to decrypt while new data uses the fresh key:
APP_KEY="base64:NEW_KEY_HERE"
APP_PREVIOUS_KEYS="base64:OLD_KEY1,base64:OLD_KEY2"
Laravel tries the current key first, then each previous key in order.
Crypt
facade & global helpersWhen you just need to protect a string or small blob:
use Illuminate\Support\Facades\Crypt;
// Facade
$token = $request->input('token');
$encrypted = Crypt::encryptString($token);
$plain = Crypt::decryptString($encrypted);
// Global helpers (identical behaviour)
$encrypted = encrypt($token);
$plain = decrypt($encrypted);
Everything is AES‑encrypted and MAC‑signed under the hood.
Str
(Laravel 12.18+)You can now chain encryption directly on a Str
instance:
use Illuminate\Support\Str;
$encrypted = Str::of('super‑secret')->encrypt();
$plain = Str::of($encrypted)->decrypt();
Great for one‑liners and pipelines.
encrypted
castsAttribute casting keeps your models tidy while Laravel handles encryption transparently:
<?php
// app/Models/Article.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Enums\ArticleStatus;
class Article extends Model
{
protected $fillable = ['content', 'status', 'published_at'];
protected $casts = [
'content' => 'array', // JSON → array
'status' => ArticleStatus::class, // Enum cast
'published_at' => 'encrypted', // Encrypted datetime
];
}
Other variations: encrypted:array
, encrypted:object
, encrypted:collection
.
Need a different cipher, or want to mix encryption with other logic? Create a custom cast:
php artisan make:cast EncryptAsHex
Implement get
/ set
and call Crypt::encryptString
internally, or use Attribute::encryptUsing()
inside an accessor.
php artisan env:encrypt # creates .env.encrypted and prints key
php artisan env:decrypt --key=... # reverses the process
Options like --cipher
and --force
let you tweak the workflow for multi‑env setups.
Every cookie generated by Laravel is encrypted and signed by the EncryptCookies
middleware. Read them with $request->cookie('name')
; there’s nothing extra to do.
Certain regulations require that data leave the browser encrypted. A typical pattern:
Use the Web Crypto API (crypto.subtle.encrypt
) in your Vue/React SPA.
Send the ciphertext to the server; Laravel stores it verbatim.
Decrypt in a secure back‑office service (or on demand) with the shared key.
Because keys must live in the browser, evaluate the threat model carefully.
public function test_published_at_is_encrypted()
{
$article = Article::factory()->create([
'published_at' => encrypt(now()),
]);
$this->assertNotEquals(
now()->toDateTimeString(),
$article->getRawOriginal('published_at')
);
$this->assertEquals(
now()->toDateTimeString(),
decrypt($article->published_at)
);
}
✔️ Step | 🛡️ Why It Matters | 🔧 Action |
---|---|---|
🔐 Key hygiene | A leaked key breaks all encryption | Store |
🔄 Key rotation | Limits the blast radius of a leak | Use |
🗄️ Encrypt at rest | Protects database dumps & backups | Apply |
📁 Secure env files | Stops config secrets from leaking |
|
🍪 Encrypted cookies | Prevents client‑side tampering | Rely on default |
🧪 Write tests | Guards against accidental plaintext | Assert raw DB values ≠ decrypted values |
🗑️ Zero discard | Remove plaintext logs, debug dumps | Use |
Laravel 12 offers multiple layers of encryption:
Quick secrets → Crypt
facade / encrypt()
helper
Fluent pipes → Str::encrypt()
/ decrypt()
Column‑level → encrypted
casts
Config secrets → env:encrypt
command
Transport → HTTPS (TLS)
Combine these with disciplined key management and you’ll keep user data safe—even if an attacker gets a database dump or environment file.