はじめに
「パスワードは平文で保存してはいけない」とはよく言われますが、では実際にどう保存すべきか?PHP8上級試験では、「password_hash()
関数と salt(ソルト)の扱い方」がよく問われます。一見正しそうに見えるコードでも、saltを手動で生成して渡すと誤りになる点は注意が必要です。
この記事では、なぜ random_bytes()
で salt を作るのが間違いなのか、そして正しいパターンはどう書くのかを図解で解説します。
🧠 パスワードは平文保存NG!ハッシュ化が必須
パスワードをそのまま保存するのは、情報漏洩リスクの観点から非常に危険です。
そのため、保存時には「一方向ハッシュ関数」を使って変換(ハッシュ化)します。
PHPではこれを簡単に行う関数が用意されています:
$hash = password_hash($password, PASSWORD_DEFAULT);
この $hash
には salt(ソルト)も含まれた状態 で格納されます。これが重要なポイントです!
⚠️ よくある誤り:「saltを自分で作って渡す」
例えば、以下のようなコードは一見正しそうですが…
$salt = random_bytes(32);
$hash = password_hash($password, PASSWORD_DEFAULT, ['salt' => $salt]);
これは 誤り です。
❌ 誤りの理由
'salt'
オプションは PHP7.0以降で非推奨。password_hash()
は自動的に安全な salt を生成する。- 自作の salt を渡しても 警告が出る/無視される。
つまり、試験の選択肢に「['salt' => $salt]
を渡す」とあれば、誤りを選ぶのが正解です。
✅ 正しい実装
<?php
$raw_password = 'password_exam';
// saltは自動生成に任せる
$hash = password_hash($raw_password, PASSWORD_DEFAULT);
// 保存するのはこの$hashだけでOK
var_dump($hash);
// 認証時に照合
if (password_verify($raw_password, $hash)) {
echo "パスワード一致";
} else {
echo "不一致";
}
この $hash
の中には、saltやハッシュアルゴリズムなどの情報がすべて埋め込まれています。
🧩 認証処理の流れ(図解)
+--------------------------------------+
| 入力されたパスワード ($raw_password) |
+--------------------------------------+
│
▼
┌──────────────────────────────┐
│ password_verify($raw, $hash) │
└──────────────────────────────┘
│
▼
┌────────────────────────────┐
│ $hash から salt を抽出 │
│ 同じアルゴリズムで再計算 │
└────────────────────────────┘
│
▼
┌───────────────┐
│ 一致 → 認証OK │
│ 不一致 → NG │
└───────────────┘
password_verify()
の内部で自動的に salt 抽出・再計算を行ってくれるため、開発者は salt の管理を意識する必要がありません。
📘 試験対策まとめ
項目 | 内容 |
---|---|
saltの生成 | password_hash() が自動で生成 |
saltの保存 | 不要(ハッシュ内に含まれる) |
認証時関数 | password_verify() |
'salt' オプション | 非推奨(使わない) |
$salt と$hash を両方保存 | 誤り(hashのみ保存) |
💡 まとめ
🔸 誤り:「random_bytes()でsaltを生成し、オプションに渡す」
🔹 正解:「password_hash()に任せ、hashのみを保存する」
PHP8上級試験では、このあたりの「仕様の進化」を正しく理解しているかが問われます。
昔の知識のまま解答すると誤るポイントなので、要チェックです。