Encryption turns readable data into scrambled text that can only be read back with a secret key. Laravel uses AES-256-CBC encryption β one of the strongest encryption standards. It's two-way: you can encrypt data and later decrypt it back to the original value.
Encryption vs Hashing
| Encryption | Hashing | |
|---|---|---|
| Direction | Two-way (encrypt & decrypt) | One-way (cannot reverse) |
| Use for | Data you need to read back (API keys, personal data) | Data you never need to read (passwords) |
| Example | "hello" β "eyJpdiI6..." β "hello" | "hello" β "$2y$12$..." (cannot get "hello" back) |
1. The Encryption Key (APP_KEY)
Laravel uses the APP_KEY in your .env file as the encryption key. This is generated when you create a Laravel project.
Terminal
# Generate a new app key
php artisan key:generate.env
APP_KEY=base64:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxWarning: Never share or expose your APP_KEY. If someone gets it, they can decrypt all your encrypted data. If you change it, all previously encrypted data becomes unreadable.
2. Encrypting & Decrypting
Basic Encryption
use Illuminate\Support\Facades\Crypt;
// Encrypt a value
$encrypted = Crypt::encryptString('my-secret-api-key');
// Result: "eyJpdiI6IkpRb0xLT..." (long scrambled string)
// Decrypt it back
$decrypted = Crypt::decryptString($encrypted);
// Result: "my-secret-api-key"Encrypt any data type (not just strings)
use Illuminate\Support\Facades\Crypt;
// Encrypt arrays, numbers, objects β anything serializable
$encrypted = Crypt::encrypt(['key' => 'value', 'secret' => true]);
$decrypted = Crypt::decrypt($encrypted);
// Result: ['key' => 'value', 'secret' => true]
// Using the helper function
$encrypted = encrypt('my secret');
$decrypted = decrypt($encrypted);3. Handling Decryption Errors
If decryption fails (wrong key, corrupted data), Laravel throws a DecryptException. Always handle this:
Safe decryption
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;
try {
$decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
// Handle the error β data is corrupted or key changed
return response()->json(['error' => 'Unable to decrypt data'], 500);
}4. Auto-Encrypt Model Fields
Use Eloquent's encrypted cast to automatically encrypt/decrypt fields when saving/reading from the database:
app/Models/User.php
class User extends Model
{
protected $casts = [
'ssn' => 'encrypted', // Auto encrypt string
'secret_data' => 'encrypted:array', // Auto encrypt array
'api_key' => 'encrypted',
];
}Usage β automatic, no extra code needed
// Saving β automatically encrypted before storing in DB
$user = User::create([
'name' => 'John',
'ssn' => '123-45-6789', // Stored encrypted in database
'api_key' => 'sk-abc123', // Stored encrypted in database
]);
// Reading β automatically decrypted when accessed
echo $user->ssn; // "123-45-6789" (readable)
echo $user->api_key; // "sk-abc123" (readable)
// In database, it looks like:
// ssn: "eyJpdiI6IkxRb0xLT0..." (encrypted gibberish)Best practice: Use encrypted casts for sensitive data like SSNs, API keys, personal medical data, payment info β anything you need to store but must protect.
5. Practical Example
Storing third-party API credentials securely:
Migration
Schema::create('integrations', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('provider'); // "stripe", "github"
$table->text('access_token'); // Will be encrypted
$table->text('refresh_token'); // Will be encrypted
$table->timestamps();
});app/Models/Integration.php
class Integration extends Model
{
protected $fillable = ['user_id', 'provider', 'access_token', 'refresh_token'];
protected $casts = [
'access_token' => 'encrypted',
'refresh_token' => 'encrypted',
];
}
// Save β tokens are auto-encrypted
Integration::create([
'user_id' => auth()->id(),
'provider' => 'stripe',
'access_token' => 'sk_live_abc123xyz', // Encrypted in DB
'refresh_token' => 'rt_live_def456uvw', // Encrypted in DB
]);
// Read β tokens are auto-decrypted
$integration = Integration::where('provider', 'stripe')->first();
echo $integration->access_token; // "sk_live_abc123xyz" (readable)Summary
- βAES-256-CBC β Laravel uses strong encryption by default
- βAPP_KEY β the secret key that encrypts everything
- βCrypt facade β encrypt() / decrypt() for manual use
- βEncrypted casts β auto-encrypt model fields in database
- βTwo-way β use for data you need to read back (not passwords)