【PHP番外編-2】そのパスワード保存、危険です!ハッシュ化関数「password_hash」の使い方

Webサービスでよくある「会員登録」。
ここで入力されたパスワードを、そのままデータベースに保存しているとどうなるでしょうか?

もしデータベースがハッキングされたら、ユーザーのパスワードが全世界に丸見えになります。
多くの人は他のサイトでも同じパスワードを使っているので、被害は甚大です。

それを防ぐために、パスワードは「ハッシュ化(ぐちゃぐちゃに変換)」して保存するのが鉄則です。

ハッシュ化とは?

「ハッシュ化」とは、元のデータを特定のルールで計算し、全く別の文字列に変換することです。
最大の特徴は「一方通行(不可逆)」であること。

  • 入力: password123
  • ハッシュ化後: $2y$10$Qx/abc123... (解読不可能!)

「ミキサーでジュースにする」ようなイメージです。
リンゴをジュースにすることはできますが、ジュースからリンゴを復元することはできませんよね?
これなら、もし漏洩しても犯人は元のパスワードを知ることができません。

使う関数は2つだけ

昔は複雑な処理が必要でしたが、今のPHPは非常に優秀です。
以下の2つの関数だけで、銀行レベルのセキュリティが実装できます。

① 登録する時(ハッシュ化)

password_hash() を使います。

$raw_pass = "password123"; // ユーザーが入力したパスワード

// 変換! (PASSWORD_DEFAULT というモードを使うのが定石)
$hash = password_hash($raw_pass, PASSWORD_DEFAULT);

echo $hash; 
// 結果:$2y$10$EpMq... のような60文字の文字列になる
// ★これをデータベースに保存する!

② ログインする時(検証)

ここが重要です。
ハッシュ化された文字は元に戻せないので、「入力された文字」と「DBの文字」を比較して合っているか確かめます。
password_verify() を使います。

$input_pass = "password123"; // ログイン画面で入力されたもの
$db_hash    = '$2y$10$EpMq...'; // DBから取り出したハッシュ

// マッチするか判定!
if (password_verify($input_pass, $db_hash)) {
    echo "ログイン成功!";
} else {
    echo "パスワードが間違っています";
}

よくある間違い

❌ やってはいけないこと:
「入力されたパスワードをもう一回ハッシュ化して、文字列同士を比較する」のはNGです!

// ダメな例
if (password_hash($input) === $db_hash) { ... }

なぜなら、password_hash() はセキュリティ強化のため、実行するたびに毎回違う結果(ランダムな文字列)を生成するからです。
必ず password_verify() 関数を使ってください。

実践:ハッシュ化体験ツール

実際にパスワードがどのように変換され、どうやって検証されるのかを体験できるツールを作ってみましょう。

<?php
    $message = "";
    $generated_hash = "";

    // 1. 「ハッシュ化」ボタンが押されたら
    if (isset($_POST['mode']) && $_POST['mode'] === 'hash') {
        $raw = $_POST['raw_password'];
        // ハッシュ化実行
        $generated_hash = password_hash($raw, PASSWORD_DEFAULT);
    }

    // 2. 「検証(ログイン)」ボタンが押されたら
    if (isset($_POST['mode']) && $_POST['mode'] === 'verify') {
        $input = $_POST['input_password'];
        $target_hash = $_POST['target_hash'];

        // 検証実行
        if (password_verify($input, $target_hash)) {
            $message = "✅ 一致します!ログイン成功";
        } else {
            $message = "❌ 一致しません!ログイン失敗";
        }
    }
?>

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>ハッシュ化実験</title>
    <style>body{padding:20px;} .box{border:1px solid #ccc; padding:15px; margin-bottom:20px;}</style>
</head>
<body>
    <h1>セキュリティ体験:ハッシュ化</h1>
    
    <!-- 結果メッセージ -->
    <h2 style="color:red"><?= $message ?></h2>

    <div class="box">
        <h3>① パスワードをハッシュ化してみよう</h3>
        <form method="post">
            <input type="hidden" name="mode" value="hash">
            パスワード:<input type="text" name="raw_password" required>
            <button type="submit">変換</button>
        </form>
        
        <?php if ($generated_hash): ?>
            <p>変換結果(これをDBに保存します):</p>
            <textarea cols="60" rows="3"><?= $generated_hash ?></textarea>
            <p><small>※同じパスワードでも、ボタンを押すたびに結果が変わるのを確認してください!</small></p>
        <?php endif; ?>
    </div>

    <div class="box">
        <h3>② ログイン判定をしてみよう</h3>
        <form method="post">
            <input type="hidden" name="mode" value="verify">
            入力パスワード:<br>
            <input type="text" name="input_password" placeholder="password123" required><br><br>
            
            比較するハッシュ(上の結果をコピペ):<br>
            <textarea name="target_hash" cols="60" rows="3" required></textarea><br>
            
            <button type="submit">検証する</button>
        </form>
    </div>

</body>
</html>

まとめ

  • パスワードは password_hash() で変換して保存する。
  • 元に戻す(復号)ことはできない。
  • ログイン判定には password_verify() を使う。
  • 「同じパスワードでも毎回ハッシュ値が変わる」のが安全の証拠。

これで、万が一あなたのデータベースが流出しても、ユーザーのパスワードは(簡単には)解読されません。
「ハッシュ化」はWeb開発者の必須マナーなので、絶対に覚えておきましょう!

📝 今日のミニテスト

セキュリティ知識の確認!

Q1. パスワードをハッシュ化するPHPの関数は?

正解:password_hash()
第2引数には PASSWORD_DEFAULT を指定するのが一般的です。

 

Q2. ハッシュ化されたパスワードを元に戻す(復号する)ことはできる?

正解:できない(不可逆)
元に戻せないからこそ、盗まれた時に安全なのです。

 

Q3. ログイン時にパスワードが合っているか確かめる正しい方法は?

正解:password_verify() 関数を使う
「入力された文字」と「保存されたハッシュ」をこの関数に渡して判定します。== で比較してはいけません。

タイトルとURLをコピーしました