> ## 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

> Learn how to securely hash and verify passwords using Laravel's Hash facade. Covers configuration and use of the bcrypt and Argon2 algorithms.

## What is hashing

Hashing is a process that transforms plaintext data (such as passwords) into a fixed-length string via a one-way transformation.
The same input always produces the same hash, but you cannot recover the original plaintext from the hash.

Laravel's `Hash` facade supports the **bcrypt** and **Argon2** hashing algorithms for securely storing passwords.

### Algorithm comparison

| Algorithm    | Characteristics                                                                 | Recommended use                    |
| ------------ | ------------------------------------------------------------------------------- | ---------------------------------- |
| **bcrypt**   | Compute cost adjustable via work factor (rounds). Default.                      | General web applications           |
| **argon2i**  | Memory, time, and thread count adjustable. Strong against side-channel attacks. | Situations requiring high security |
| **argon2id** | A hybrid of argon2i and argon2d. PHC recommended.                               | When using Argon2 in a new project |

<Info>
  The bcrypt "work factor" controls the time it takes to generate a hash. The slower the hash, the greater the resistance to brute-force attacks. As hardware gets faster, you can maintain security by increasing the work factor.
</Info>

### Hashing and verification flow

```mermaid theme={null}
flowchart LR
    A[Plaintext password] -->|Hash::make| B["Hash value<br>Stored in DB"]
    C[Login input] -->|Hash::check| D{Match?}
    B --> D
    D -->|true| E[Authentication succeeded]
    D -->|false| F[Authentication failed]
```

***

## Configuration

By default, Laravel uses the `bcrypt` driver. You can change it via the `HASH_DRIVER` environment variable.

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

To customize hashing configuration, publish the configuration file with `config:publish`.

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

After publishing, you can change defaults like the work factor in `config/hashing.php`.

***

## Basic usage

### Hashing a password

Passing the plaintext password to `Hash::make()` returns a hash value. Store this hash value in the database.

```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>
  Store the hash value in the database, but never store plaintext passwords.
</Warning>

### Adjusting the bcrypt work factor

You can adjust the compute cost of hash generation via the `rounds` option. A larger value is more secure but also takes longer to process.
The default value (12) is appropriate for most applications.

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

### Adjusting Argon2 parameters

When using Argon2, you can adjust the compute cost via the `memory`, `time`, and `threads` options.

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

| Option    | Description                   | Default |
| --------- | ----------------------------- | ------- |
| `memory`  | Amount of memory to use (KiB) | 65536   |
| `time`    | Number of iterations          | 4       |
| `threads` | Number of threads to use      | 1       |

<Tip>
  For details on Argon2 options, see the [official PHP documentation](https://secure.php.net/manual/en/function.password-hash.php).
</Tip>

***

## Verifying passwords

Use `Hash::check()` to verify whether a plaintext password matches a stored hash.
This is a typical use in login handling.

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

if (Hash::check($request->password, $user->password)) {
    // Passwords match
} else {
    // Passwords do not match
}
```

When you use `Auth::attempt()`, this is done automatically, so you don't need to call it directly.
`Hash::check()` is useful when you need to manually verify the current password.

```php theme={null}
// Example of verifying the current password on a password-change form
if (! Hash::check($request->current_password, $request->user()->password)) {
    return back()->withErrors(['current_password' => 'Your current password is incorrect.']);
}
```

***

## Determining when to rehash

Use `Hash::needsRehash()` to check whether a hash was generated with a work factor different from the current configuration.
Use it to update existing hashes to the new configuration after changing the work factor.

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

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

Here's an example of rehashing on successful login.

```mermaid theme={null}
flowchart TD
    A[Login succeeds] --> B{needsRehash?}
    B -->|true| C[Rehash with new work factor<br>and store]
    B -->|false| D[Continue as-is]
    C --> D
```

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

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

<Tip>
  Periodically review the work factor as hardware improves to maintain security. By leveraging `needsRehash()`, you can update passwords naturally at the moment a user logs in.
</Tip>

***

## Hash algorithm verification

By default, `Hash::check()` verifies that a hash was generated by the currently configured algorithm.
If the algorithm is different, a `RuntimeException` is thrown.

This prevents attacks that tamper with the hash algorithm.

When migrating algorithms and needing to support multiple algorithms simultaneously, you can disable this verification by setting `HASH_VERIFY` to `false`.

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

<Warning>
  Setting `HASH_VERIFY=false` disables algorithm verification. Only use it during a migration period and return to `true` (the default) once migration is complete.
</Warning>

***

## Summary

| What you want to do            | How                                |
| ------------------------------ | ---------------------------------- |
| Hash a password                | `Hash::make($password)`            |
| Verify a hash                  | `Hash::check($plain, $hash)`       |
| Check if a rehash is needed    | `Hash::needsRehash($hash)`         |
| Change the hash driver         | `HASH_DRIVER` environment variable |
| Disable algorithm verification | `HASH_VERIFY=false`                |

## Next steps

<Card title="Authentication introduction" icon="lock" href="/en/authentication">
  Learn the full picture of authentication, including implementing login handling using `Hash::check()`.
</Card>


## Related topics

- [Upgrading from Laravel 10 to 11](/en/blog/upgrade-10-to-11.md)
- [Encryption](/en/encryption.md)
- [Laravel Fortify and Starter Kits](/en/advanced/fortify.md)
- [Eloquent Custom Casts](/en/advanced/eloquent-casts.md)
- [Contracts](/en/contracts.md)
