LARAVEL ENCRYPTABLE: CÓMO PROTEGER DATOS SENSIBLES EN LOS MODELOS ELOQUENT

Laravel Encryptable hace referencia al uso de traits o paquetes que automatizan el cifrado y descifrado de atributos en los modelos Eloquent.
En el desarrollo de aplicaciones web, proteger la información sensible como DNI, números de teléfono, direcciones, datos médicos, tokens de API, etc.) es una práctica esencial.

¿Por qué encriptar datos en la base de datos?

  • Cumplir con regulaciones como GDPR, LOPD o HIPAA.
  • Proteger datos en caso de brecha en la base de datos, el atacante solo vería texto cifrado.
  • Evitar que administradores de base de datos o backups expongan información sensible.
La encriptación no sustituye buenas prácticas de seguridad como HTTPS, hashing de contraseñas, etc., pero es una capa adicional excelente.

Solución Nativa de Laravel

Laravel incorpora casts nativos de encriptación. Es la forma oficial y más recomendada en proyectos nuevos.

// app/Models/User.php
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
protected function casts(): array
{
return [
  'phone' => 'encrypted',
  'address'=> 'encrypted',
  'passport'  => 'encrypted',
  'preferences'=> 'encrypted:array', // Encripta + JSON
  'metadata'  => 'encrypted:collection', // Encripta + Collection
  'settings'  => 'encrypted:json',
];
}
}

Ventajas

  • Sin paquetes externos.
  • Soporta array, json, collection y object.
  • Totalmente integrado con Eloquent (mutators, serialization, etc.).
  • Usar el "APP_KEY" de Laravel, por defecto "AES-256-CBC".

Desventajas

  • No permite búsquedas directas en los campos encriptados.
  • Cambiar el "APP_KEY" invalida todos los datos encriptados

Ejemplo de uso con "venturedrake/laravel-encryptable"

  • Instalar el paquete:

    composer require venturedrake/laravel-encryptable
    
  • use Venturedrake\LaravelEncryptable\Traits\Encryptable;
    
    class Client extends Model
    {
    use Encryptable;
    
    protected $encryptable = [
    'dni',
    'phone',
    'email',  // ¡Cuidado con email si lo usas para login!
    'bank_account',
    ];
    }
    
El trait automáticamente:
  • Encripta al guardar ("saving").
  • Desencripta al leer ("getAttribute").

Cómo crear un Trait propio

Si no se quiere depender de paquetes externos:

// app/Traits/Encryptable.php
namespace App\Traits;

use Illuminate\Support\Facades\Crypt;

trait Encryptable
{
public function getAttribute($key)
{
$value = parent::getAttribute($key);

if (in_array($key, $this->encryptable ?? [])) {
  try {
  return $value ? Crypt::decryptString($value) : null;
  } catch (\Exception $e) {
  return $value; // Evita errores si ya estaba encriptado
  }
}

return $value;
}

public function setAttribute($key, $value)
{
if (in_array($key, $this->encryptable ?? []) && $value !== null) {
  $value = Crypt::encryptString($value);
}

return parent::setAttribute($key, $value);
}
}

Consideraciones Importantes

  1. Búsquedas y consultas: No se puede hacer "where('phone', $phone)" directamente. Para eso hay que encriptar también el valor de búsqueda usando "hashing", que es irreversible, para búsquedas t encriptación. También usar paquetes avanzados como Laravel CipherSweet,de Spatie, para encriptación con búsqueda.
  2. Índices y rendimiento Los campos encriptados son más largos y no se pueden indexar eficientemente.
  3. "APP_KEY": No perder ni cambiar el "APP_KEY" sin migrar los datos.
  4. Migraciones: Aumentar el tamaño de las columnas (TEXT o MEDIUMTEXT).
  5. Performance: El cifrado/descifrado añade un pequeño overhead. Usarlo solo en campos realmente sensibles.

Paquetes populares

Aunque la solución nativa es preferible, muchos proyectos legacy usan traits. En la sigujente tabla se muestran los más conocidos:

Paquete Popularidad Última Actividad Recomendado
venturedrake/laravel-encryptable Alta Activo Sí (legacy)
michielkempen/laravel-encryptable Media Reciente Bueno
skyraptor/laravel-encryptable-trait Media Activo Bueno
hihaho/laravel-encryptable-trait Media Activo Bueno
sagalbot/encryptable (antiguo) Baja Laravel 5 No

Recomendaciones según el proyecto

  • Proyecto nuevo: Usa casts encrypted nativos.
  • Proyecto legacy: Migra gradualmente a casts nativos.
  • Si se necesitan búsqueda en campos encriptados: Considerar CipherSweet.
  • Requisitos muy altos de cumplimiento: Evaluar encriptación a nivel de aplicación + Vault (HashiCorp) o soluciones de base de datos.