Saltar al contenido principal

¿Qué es la fachada Crypt?

El servicio de cifrado de Laravel ofrece una interfaz sencilla para cifrar y descifrar valores usando el cifrado AES-256-CBC (o AES-128-CBC) de OpenSSL. Todos los valores cifrados por Laravel se firman con un código de autenticación de mensaje (MAC). Con esto, si el valor cifrado se altera, ya no se puede descifrar.

Configuración

Generación de APP_KEY

Antes de usar el cifrado, la clave key en config/app.php debe estar configurada. Este valor se lee de la variable de entorno APP_KEY. Genera una clave segura con el comando php artisan key:generate. Usa el generador de números aleatorios seguros de PHP para producir una clave criptográficamente segura.
php artisan key:generate
Suele generarse automáticamente al instalar Laravel. La clave generada se guarda en el archivo .env.
APP_KEY=base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY=
Nunca hagas pública APP_KEY. Si se filtra, todos los datos cifrados podrían ser descifrados.

Rotación de la clave de cifrado

Cambiar la clave de cifrado hace que se desconecten todas las sesiones de usuario autenticadas. Es porque Laravel cifra todas las cookies, incluidas las de sesión. Además, los datos cifrados con la clave anterior no podrán descifrarse. Para mitigar este problema, puedes listar claves antiguas separadas por comas en APP_PREVIOUS_KEYS.
APP_KEY="base64:J63qRTDLub5NuZvP+kb8YIorGS6qFYHKVo6u7179stY="
APP_PREVIOUS_KEYS="base64:2nLsGFGzyoae2ax3EF2Lyq/hH6QghBGLIq5uL+Gp8/w="
Para cifrar, Laravel siempre usa la clave actual; para descifrar, si falla con la clave actual, prueba las claves antiguas en orden. Así los usuarios pueden seguir usando la aplicación durante la rotación de claves.

Cifrado

Cifra un valor con el método encryptString de la fachada Crypt. El valor se cifra con OpenSSL y AES-256-CBC, y se firma con MAC.
<?php

namespace App\Http\Controllers;

use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;

class DigitalOceanTokenController extends Controller
{
    /**
     * Guarda el API token del usuario
     */
    public function store(Request $request): RedirectResponse
    {
        $request->user()->fill([
            'token' => Crypt::encryptString($request->token),
        ])->save();

        return redirect('/secrets');
    }
}
encryptString cifra la cadena sin serializarla. Si necesitas cifrar objetos o arrays, usa encrypt.
MétodoUso
Crypt::encryptString($value)Cifra el string tal cual
Crypt::encrypt($value)Serializa el valor antes de cifrarlo (admite arrays y objetos)

Descifrado

Descifra un valor con decryptString de la fachada Crypt. Si no se puede descifrar correctamente (por ejemplo, MAC no válido), se lanza una DecryptException.
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Support\Facades\Crypt;

try {
    $decrypted = Crypt::decryptString($encryptedValue);
} catch (DecryptException $e) {
    // Manejo del fallo de descifrado
    abort(400, 'Datos no válidos.');
}
MétodoUso
Crypt::decryptString($value)Descifra como string
Crypt::decrypt($value)Descifra y deserializa (admite arrays y objetos)

Casts en modelos

Usando el cast encrypted en un modelo Eloquent, el cifrado y descifrado del atributo son automáticos.
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    protected function casts(): array
    {
        return [
            'secret_note'    => 'encrypted',           // Cifrado de string
            'profile_data'   => 'encrypted:array',     // Cifra un array
            'preferences'    => 'encrypted:collection',// Cifra una colección
            'metadata'       => 'encrypted:object',    // Cifra un objeto
            'settings'       => 'encrypted:json',      // Cifra como JSON
        ];
    }
}
Con el cast configurado, la asignación y la lectura del atributo cifran y descifran automáticamente.
// Se cifra automáticamente al guardarse en la BD
$user->secret_note = 'Nota secreta';
$user->save();

// Se descifra automáticamente al leer
echo $user->secret_note; // 'Nota secreta'
Los casts encrypted:* usan internamente Crypt::encrypt y Crypt::decrypt. Se recomienda usar el tipo de columna text o longText en la base de datos.

Ejemplo práctico: almacenamiento cifrado de datos personales

Patrón típico para guardar datos personales (número de identificación, tarjeta de crédito, etc.) de forma segura.

Migración

Schema::create('profiles', function (Blueprint $table) {
    $table->id();
    $table->foreignId('user_id')->constrained();
    $table->text('my_number')->nullable();     // El valor cifrado se guarda como text
    $table->text('bank_account')->nullable();
    $table->timestamps();
});

Modelo

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Profile extends Model
{
    protected $fillable = ['user_id', 'my_number', 'bank_account'];

    protected function casts(): array
    {
        return [
            'my_number'    => 'encrypted',
            'bank_account' => 'encrypted',
        ];
    }
}

Controlador

use App\Models\Profile;
use Illuminate\Http\Request;

class ProfileController extends Controller
{
    public function store(Request $request)
    {
        $request->validate([
            'my_number'    => ['required', 'string'],
            'bank_account' => ['required', 'string'],
        ]);

        // El modelo cifra automáticamente al guardar
        Profile::create([
            'user_id'      => $request->user()->id,
            'my_number'    => $request->my_number,
            'bank_account' => $request->bank_account,
        ]);

        return redirect('/profile');
    }

    public function show(Request $request)
    {
        $profile = $request->user()->profile;

        // El modelo descifra automáticamente al leer
        return view('profile.show', ['profile' => $profile]);
    }
}

Resumen

ObjetivoMétodo
Generar APP_KEYphp artisan key:generate
Cifrar un stringCrypt::encryptString($value)
Descifrar un stringCrypt::decryptString($value)
Cifrar array u objetoCrypt::encrypt($value)
Cifrar atributos de modelo automáticamenteCast 'column' => 'encrypted'
Rotar claveListar claves antiguas en APP_PREVIOUS_KEYS

Próximos pasos

Hashing

Aprende a hashear y verificar contraseñas de forma segura.

Autorización

Descubre el control de acceso con políticas y gates.
Última modificación el 13 de julio de 2026