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() 関数を使う
「入力された文字」と「保存されたハッシュ」をこの関数に渡して判定します。== で比較してはいけません。