> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# Hashing (hasheo)

> Explicamos cómo hashear y verificar contraseñas de forma segura con la fachada Hash de Laravel. Cubrimos la configuración y el uso de los algoritmos bcrypt y Argon2.

## ¿Qué es hashear?

Hashear consiste en transformar mediante una función unidireccional un dato en claro (por ejemplo, una contraseña) a una cadena de longitud fija.
La misma entrada produce siempre el mismo hash, pero no es posible recuperar el texto en claro a partir del hash.

La fachada `Hash` de Laravel soporta los algoritmos **bcrypt** y **Argon2** para el almacenamiento seguro de contraseñas.

### Comparación de algoritmos

| Algoritmo    | Características                                                                          | Uso recomendado                             |
| ------------ | ---------------------------------------------------------------------------------------- | ------------------------------------------- |
| **bcrypt**   | Permite ajustar el coste con el work factor (rounds). Por defecto                        | Aplicaciones web habituales                 |
| **argon2i**  | Permite ajustar memoria, tiempo y número de hilos. Resistente a ataques de canal lateral | Escenarios con requisitos de alta seguridad |
| **argon2id** | Híbrido de argon2i y argon2d. Recomendado por PHC                                        | Proyectos nuevos que usen Argon2            |

<Info>
  El "work factor" de bcrypt controla el tiempo que se tarda en generar el hash. Cuanto más lento sea el hash, mayor será la resistencia frente a ataques de fuerza bruta. A medida que el hardware se vuelve más rápido, puedes ir subiendo el work factor para mantener el nivel de seguridad.
</Info>

### Flujo de hasheo y verificación

```mermaid theme={null}
flowchart LR
    A[Contraseña en claro] -->|Hash::make| B["Hash<br>Guardado en BD"]
    C[Entrada en el login] -->|Hash::check| D{¿Coincide?}
    B --> D
    D -->|true| E[Autenticación correcta]
    D -->|false| F[Autenticación fallida]
```

***

## Configuración

Por defecto, Laravel usa el driver `bcrypt`. Puedes cambiarlo con la variable de entorno `HASH_DRIVER`.

```ini theme={null}
# .env
HASH_DRIVER=bcrypt  # bcrypt / argon / argon2id
```

Para personalizar la configuración de hashing, publica el archivo de configuración con `config:publish`.

```shell theme={null}
php artisan config:publish hashing
```

Tras publicarlo, puedes modificar el work factor por defecto y otras opciones en `config/hashing.php`.

***

## Uso básico

### Hashear una contraseña

Al pasar el texto en claro a `Hash::make()` se devuelve el hash. Ese hash es lo que guardas en la base de datos.

```php theme={null}
<?php

namespace App\Http\Controllers;

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

class PasswordController extends Controller
{
    public function update(Request $request): RedirectResponse
    {
        $request->validate([
            'password' => ['required', 'min:8', 'confirmed'],
        ]);

        $request->user()->fill([
            'password' => Hash::make($request->password),
        ])->save();

        return redirect('/profile');
    }
}
```

<Warning>
  Guarda el hash en la base de datos, pero nunca guardes la contraseña en claro.
</Warning>

### Ajustar el work factor de bcrypt

La opción `rounds` ajusta el coste de generar el hash. Cuanto mayor sea el valor, más seguro, pero también más lento.
El valor por defecto (12) es adecuado para la mayoría de aplicaciones.

```php theme={null}
$hashed = Hash::make('plain-text-password', [
    'rounds' => 14,
]);
```

### Ajustar el work factor de Argon2

Con Argon2 puedes ajustar el coste con las opciones `memory`, `time` y `threads`.

```php theme={null}
$hashed = Hash::make('plain-text-password', [
    'memory'  => 65536, // en KiB
    'time'    => 4,
    'threads' => 2,
]);
```

| Opción    | Descripción               | Por defecto |
| --------- | ------------------------- | ----------- |
| `memory`  | Cantidad de memoria (KiB) | 65536       |
| `time`    | Número de iteraciones     | 4           |
| `threads` | Número de hilos           | 1           |

<Tip>
  Para los detalles de las opciones de Argon2, consulta la [documentación oficial de PHP](https://secure.php.net/manual/es/function.password-hash.php).
</Tip>

***

## Verificación de contraseñas

Con `Hash::check()` puedes comprobar si una contraseña en claro coincide con el hash guardado.
Es un uso típico dentro del proceso de login.

```php theme={null}
use Illuminate\Support\Facades\Hash;

if (Hash::check($request->password, $user->password)) {
    // La contraseña coincide
} else {
    // La contraseña no coincide
}
```

Si utilizas `Auth::attempt()`, esto se hace automáticamente y no necesitas llamarlo directamente.
`Hash::check()` es útil cuando quieres comprobar la contraseña actual manualmente.

```php theme={null}
// Ejemplo: comprobar la contraseña actual en un formulario de cambio de contraseña
if (! Hash::check($request->current_password, $request->user()->password)) {
    return back()->withErrors(['current_password' => 'La contraseña actual no es correcta.']);
}
```

***

## Detección de necesidad de rehash

Con `Hash::needsRehash()` puedes comprobar si el work factor con el que se generó el hash es distinto de la configuración actual.
Se usa para actualizar los hashes existentes tras haber cambiado el work factor.

```php theme={null}
use Illuminate\Support\Facades\Hash;

if (Hash::needsRehash($user->password)) {
    $user->update([
        'password' => Hash::make($plainTextPassword),
    ]);
}
```

Ejemplo de rehash al iniciar sesión con éxito:

```mermaid theme={null}
flowchart TD
    A[Login correcto] --> B{¿needsRehash?}
    B -->|true| C[Rehashear con el nuevo work factor<br>y guardar]
    B -->|false| D[Continuar sin cambios]
    C --> D
```

```php theme={null}
// Rehash dentro del proceso de login
if (Auth::attempt($credentials)) {
    if (Hash::needsRehash(Auth::user()->password)) {
        Auth::user()->update([
            'password' => Hash::make($credentials['password']),
        ]);
    }

    return redirect()->intended('/dashboard');
}
```

<Tip>
  Revisa periódicamente el work factor a medida que mejora el hardware para mantener el nivel de seguridad. Usar `needsRehash()` te permite actualizar las contraseñas en el momento natural del login del usuario.
</Tip>

***

## Verificación del algoritmo del hash

Por defecto, `Hash::check()` verifica que el hash se haya generado con el algoritmo configurado actualmente.
Si el algoritmo difiere, se lanza una `RuntimeException`.

Esto ayuda a prevenir ataques por manipulación del algoritmo del hash.

Si estás migrando algoritmos y necesitas soportar varios simultáneamente, puedes desactivar esta verificación estableciendo `HASH_VERIFY` a `false`.

```ini theme={null}
# .env
HASH_VERIFY=false
```

<Warning>
  Con `HASH_VERIFY=false` se desactiva la verificación del algoritmo. Úsalo solo durante el periodo de migración y, cuando termines, vuelve a `true` (valor por defecto).
</Warning>

***

## Resumen

| Objetivo                                | Método                            |
| --------------------------------------- | --------------------------------- |
| Hashear una contraseña                  | `Hash::make($password)`           |
| Verificar un hash                       | `Hash::check($plain, $hash)`      |
| Comprobar si hace falta rehash          | `Hash::needsRehash($hash)`        |
| Cambiar el driver de hash               | Variable de entorno `HASH_DRIVER` |
| Desactivar la verificación de algoritmo | `HASH_VERIFY=false`               |

## Próximos pasos

<Card title="Introducción a la autenticación" icon="lock" href="/es/authentication">
  Aprende una visión general de la autenticación, incluida la implementación del login con `Hash::check()`.
</Card>


## Related topics

- [Cifrado (Encryption)](/es/encryption.md)
- [Laravel Fortify y los starter kits](/es/advanced/fortify.md)
- [Casts personalizados de Eloquent](/es/advanced/eloquent-casts.md)
- [Actualización de Laravel 10 a 11](/es/blog/upgrade-10-to-11.md)
- [Contracts (contratos)](/es/contracts.md)
