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

> 說明如何運用 Laravel 的 Hash Facade 安全地雜湊與驗證密碼，涵蓋 bcrypt 與 Argon2 演算法的設定與使用方式。

## 雜湊是什麼

雜湊（Hashing）是將密碼等明文以單向轉換方式產生固定長度字串的處理。
相同輸入永遠會得到相同雜湊值，但無法從雜湊值還原成原本的明文。

Laravel 的 `Hash` Facade 支援用於安全儲存密碼的 **bcrypt** 與 **Argon2** 雜湊演算法。

### 演算法比較

| 演算法          | 特色                           | 建議用途            |
| ------------ | ---------------------------- | --------------- |
| **bcrypt**   | 可用工作因子（rounds）調整計算成本，為預設     | 一般 Web 應用程式     |
| **argon2i**  | 可調整記憶體、時間、執行緒數，對邊道攻擊有較強抵抗力   | 需要高安全性的情境       |
| **argon2id** | argon2i 與 argon2d 的混合，PHC 推薦 | 新專案要使用 Argon2 時 |

<Info>
  bcrypt 的「工作因子」控制產生雜湊所需的時間。雜湊越慢，對暴力破解的抵抗力就越高。當硬體變快時，可提高工作因子維持安全性。
</Info>

### 雜湊與驗證流程

```mermaid theme={null}
flowchart LR
    A[明文密碼] -->|Hash::make| B["雜湊值<br>存入 DB"]
    C[登入時輸入] -->|Hash::check| D{一致？}
    B --> D
    D -->|true| E[認證成功]
    D -->|false| F[認證失敗]
```

***

## 設定

Laravel 預設使用 `bcrypt` 驅動。可透過 `HASH_DRIVER` 環境變數變更。

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

若要自訂雜湊設定，可用 `config:publish` 發布設定檔。

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

發布後可在 `config/hashing.php` 更改預設工作因子等設定。

***

## 基本用法

### 對密碼進行雜湊

將明文密碼傳入 `Hash::make()` 可得雜湊值，將此值存入資料庫。

```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>
  請將雜湊值存進資料庫，絕對不要儲存明文密碼。
</Warning>

### 調整 bcrypt 的工作因子

可透過 `rounds` 選項調整產生雜湊的計算成本。值越大越安全，但耗時也越多。
預設值（12）在多數應用中都合宜。

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

### 調整 Argon2 的工作因子

使用 Argon2 時可透過 `memory`、`time`、`threads` 調整計算成本。

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

| 選項        | 說明           | 預設    |
| --------- | ------------ | ----- |
| `memory`  | 使用的記憶體量（KiB） | 65536 |
| `time`    | 疊代次數         | 4     |
| `threads` | 使用的執行緒數      | 1     |

<Tip>
  Argon2 選項的詳細說明可參閱 [PHP 官方文件](https://secure.php.net/manual/en/function.password-hash.php)。
</Tip>

***

## 密碼驗證

使用 `Hash::check()` 可確認明文密碼是否與既存雜湊相符。
這在登入處理中是典型的用法。

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

if (Hash::check($request->password, $user->password)) {
    // 密碼相符
} else {
    // 密碼不符
}
```

使用 `Auth::attempt()` 時，此驗證會自動進行，不必自行呼叫。
`Hash::check()` 適合用在手動確認目前密碼的情境。

```php theme={null}
// 在變更密碼表單中確認目前密碼的範例
if (! Hash::check($request->current_password, $request->user()->password)) {
    return back()->withErrors(['current_password' => '目前的密碼不正確。']);
}
```

***

## 判斷是否需重新雜湊

使用 `Hash::needsRehash()` 可以確認產生雜湊時的工作因子是否與目前設定不同。
在你變更工作因子後，可將既有雜湊以新設定更新。

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

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

在登入成功時執行重新雜湊的範例：

```mermaid theme={null}
flowchart TD
    A[登入成功] --> B{needsRehash?}
    B -->|true| C[以新工作因子<br>重新雜湊並儲存]
    B -->|false| D[繼續]
    C --> D
```

```php theme={null}
// 在登入處理中執行重新雜湊
if (Auth::attempt($credentials)) {
    if (Hash::needsRehash(Auth::user()->password)) {
        Auth::user()->update([
            'password' => Hash::make($credentials['password']),
        ]);
    }

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

<Tip>
  請隨硬體效能提升定期檢視工作因子，以維持安全性。搭配 `needsRehash()`，即可在使用者登入時自然地更新密碼。
</Tip>

***

## 雜湊演算法驗證

預設情況下，`Hash::check()` 會確認雜湊是否以目前設定的演算法產生。
若演算法不同，會拋出 `RuntimeException`。

如此可防止透過竄改雜湊演算法的攻擊。

若正處於演算法遷移期，需要同時支援多個演算法，可將 `HASH_VERIFY` 設為 `false` 停用此驗證。

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

<Warning>
  將 `HASH_VERIFY=false` 會停用演算法驗證。僅在遷移期間使用，遷移完成後請改回 `true`（預設）。
</Warning>

***

## 總結

| 想要做的事      | 方法                           |
| ---------- | ---------------------------- |
| 對密碼進行雜湊    | `Hash::make($password)`      |
| 驗證雜湊       | `Hash::check($plain, $hash)` |
| 確認是否需要重新雜湊 | `Hash::needsRehash($hash)`   |
| 變更雜湊驅動     | `HASH_DRIVER` 環境變數           |
| 停用演算法驗證    | `HASH_VERIFY=false`          |

## 下一步

<Card title="認證入門" icon="lock" href="/zh-TW/authentication">
  學習使用 `Hash::check()` 實作登入等，掌握認證的全貌。
</Card>


## Related topics

- [從 Laravel 10 升級到 11](/zh-TW/blog/upgrade-10-to-11.md)
- [加密（Encryption）](/zh-TW/encryption.md)
- [Core — AT Protocol 核心操作](/zh-TW/packages/laravel-bluesky/core.md)
- [Laravel Fortify 與啟動套件](/zh-TW/advanced/fortify.md)
- [URL 生成](/zh-TW/urls.md)
