Tilly The Coder
Tilly The Coder
Encrypting Values in Laravel 12 — A Complete, Modern Guide
Tilly The Coder

Encrypting Values in Laravel 12 — A Complete, Modern Guide

Tilly The Coder
4 mins
This is the estimated time it takes to read the article.

Reconstructed guide, written September 26, 2026. This replaces the lost article with new material based on the Laravel 12 documentation. Its original URL is retained for existing links.

Begin with the reason a value needs to be recoverable. An application may need to send a stored provider token back to that provider, so encryption is appropriate. A login password should be verified without recovering the original password. Decide that distinction before adding a cast or choosing a database column.

Laravel documents its reversible encryption API in the Laravel 12 encryption guide. Crypt::encryptString() and decryptString() operate on strings; invalid ciphertext raises DecryptException. The application encryption key comes from configuration, normally APP_KEY.

Encrypt a string at an explicit boundary

use Illuminate\Support\Facades\Crypt;

$token = 'example-token-for-a-local-test';
$ciphertext = Crypt::encryptString($token);
$recovered = Crypt::decryptString($ciphertext);

if (! hash_equals($token, $recovered)) {
    throw new RuntimeException('Encryption round trip failed.');
}

This example exercises the API without printing either value. In application code, perform the operation inside the action that stores or uses the credential. Keep credentials out of request logs, exception context, debug dumps, and analytics payloads. Encryption at rest does not prevent a later line of application code from exposing plaintext.

Use an encrypted cast for model-owned data

The encrypted-casting documentation supports encrypted strings and structured variants such as encrypted:array. Use a TEXT column or larger because ciphertext length grows. Encrypted attributes cannot be searched as ordinary database values.

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

final class ProviderConnection extends Model
{
    protected $hidden = ['access_token'];

    /** @return array<string, string> */
    protected function casts(): array
    {
        return ['access_token' => 'encrypted'];
    }
}

Create the matching access_token column through a migration before using the model. Assign plaintext through the cast and let Eloquent encrypt it. Encrypting the same value manually before assigning it would create two encryption layers and complicate every reader.

The hidden property reduces accidental exposure during model serialization. Explicit API resources should still select the public fields the client needs. Authorization must run before returning any sensitive data or using a saved credential on a user’s behalf.

Treat a decryption error as an incident to investigate

A failed decrypt can mean the wrong key, a damaged value, or data that was never encrypted using the expected format. Preserve the original ciphertext while investigating. Do not substitute an empty token, save that value, and turn a configuration problem into permanent data loss.

Report a safe error containing a record identifier and operation name. Keep the secret and full ciphertext out of the message. If the user needs to reconnect an integration, show that explicit state only after the application has identified the cause and the required recovery path.

Plan key rotation with the data lifecycle

Laravel 12 accepts a comma-separated APP_PREVIOUS_KEYS list. New encryption uses the current key; decryption can try configured previous keys. This allows a transition period, but it does not automatically rewrite every stored value.

Before rotation, identify encrypted columns, long-lived tokens, encrypted cookies, and retained backups. Test recovery from a backup in an isolated environment with its required keys. Keep keys in the approved secret store and make access auditable. A database backup without the matching encryption material may not be recoverable.

If the goal is to retire an old key, use an explicit, resumable re-encryption process with verified counts and failure handling. Account for older backups before deleting key material. Schedule this as a controlled data operation rather than a routine deployment command.

Keep password verification separate

Use Laravel’s Hash facade and password-hashing facilities for login passwords. Review tests for successful verification, rejected credentials, encrypted-value round trips, and tampered ciphertext. The test suite should exercise the failure paths that would otherwise only appear during a restore.