こんにちは!セキュリティの世界へようこそ。
新人のIT担当者や、これからアプリ開発を頑張っていこうという一般開発者の皆さん、日々の業務お疲れ様です!
「パスワードはハッシュ化して保存しなさい」――これはセキュリティの基本のキとして、皆さんも耳にータコができるほど聞いてきたことだと思います。でも、実際に「どうやってハッシュ化するのが正解なの?」「SHA-256を使えば万全なんでしょ?」と聞かれると、少しドキッとしてしまうことありませんか?
実は、ただ単にパスワードをSHA-256に通すだけでは、今のサイバー攻撃者の前では「紙で作った金庫」のようなものです。一瞬で破られてしまいます。
今回は、安全なパスワード保存の切り札である「PBKDF2(ピービーケーディーエフツー)」の仕組みと、現場で絶対に押さえておきたい推奨パラメータについて、身近な防犯の例えを交えながら、一歩ずつ優しく紐解いていきましょう!
—
1. なぜ「普通のハッシュ関数」だけではパスワードを守れないのか?
まずは、私たちの身の回りにある「鍵」に例えて考えてみましょう。
あなたが家に頑丈な玄関の鍵をつけたとしても、もし「泥棒が1秒間に10億回も違う合鍵を差し込んでガチャガチャ試せる機械」を持っていたらどうでしょう? どんなに複雑な鍵でも、総当たりで試されたらあっという間に開けられてしまいますよね。
コンピュータの世界でも全く同じことが起きているんです。
SHA-2(SHA-256など)やSHA-3といったハッシュ関数は、入力されたデータを一瞬で別の文字列に変換する天才的な計算機ですが、「計算が速すぎる」という特徴を持っています。
もし、攻撃者がデータベースを不正に盗み出し、そこに保存されているハッシュ値(パスワードの変換後データ)を手に入れたとします。攻撃者のパソコンは、世の中によくあるパスワード(「password123」や「123456」など)を次々とSHA-256に通して、「どのパスワードならこのハッシュ値と一致するか」を1秒間に何十億回という猛烈なスピードで試すのです。これを「ブルートフォース攻撃(総当たり攻撃)」や「レインボー攻撃」と呼びます。
計算が速い=攻撃者にとっても破りやすい。これが、普通のハッシュ関数をそのままパスワードに使ってはいけない致命的な理由なんですね。
—
2. 救世主登場!パスワードをガチガチに守る「PBKDF2」の仕組み
「じゃあ、どうすればいいの?」と思いますよね。そこで登場するのが、今回の主役であるPBKDF2(Password-Based Key Derivation Function 2)です。
PBKDF2は、一言で言うと「あえて計算にものすごく時間がかかるように仕掛けをした、パスワード専用の特殊な変換ボックス」です。
PBKDF2の仕組みを支える重要要素は、大きく分けて以下の2つです。
① ソルト(Salt)の追加
「ソルト(塩)」とは、パスワードに混ぜるランダムな文字列のことです。
同じ「password123」というパスワードであっても、ユーザーAには「salt_A」、ユーザーBには「salt_B」という全く違うランダムな文字列をくっつけてからハッシュ化します。
【防犯の例え】
世の中の多くの人が「家に入るときは右足から入る」という同じ習慣(よくあるパスワード)を持っていたとします。しかし、全員に「右足の靴のなかに違う色の小石(ソルト)を入れてね」とルールを決めると、泥棒は「全員分の靴の中の小石の色」を一つずつバラバラに調べ直さなければならなくなります。これによって、攻撃者が「よくあるパスワードのリスト」を使い回して一網打尽にする攻撃(レインボー攻撃)を完全に無効化できるのです。
② ストレッチング(Stretching / 反復処理)
ストレッチングとは、ハッシュ化の計算を「わざと何万回、何十万回と繰り返す」仕組みのことです。
通常のSHA-256なら1回で終わる計算を、PBKDF2では何十万回もループさせます。たった1回のログインであれば、人間が体感する遅さはほんのコンマ数秒(例えば0.1秒)なので、ユーザーはストレスを感じません。
しかし、攻撃者が100万人のパスワードを破ろうとして、1人あたり10万回計算させられたらどうなるでしょう? 攻撃者のパソコンは膨大な時間を計算に奪われ、攻撃を事実上不可能にすることができます。
③ HMACの活用
PBKDF2の頭文字にある「HMAC」は、秘密鍵とメッセージを組み合わせてデータの改ざんを防ぐ仕組みですが、PBKDF2の中では「ベースとなる強力な暗号のミキサー(混ぜ合わせ器)」として使われています。これにより、データの安全性をさらに高めているんです。
—
3. 現場で迷わない!NISTが推奨する最新パラメータ設定
「仕組みは分かったけど、具体的にどう設定すればいいの?」というエンジニアの皆さんのために、米国国立標準技術研究所(NIST)などのセキュリティ基準に基づく、現時点での推奨パラメータをご紹介します。
システムを設計する際は、以下の基準を目安にしてください。
- アルゴリズム(HMAC):
HMAC-SHA-256以上 (できればHMAC-SHA-512も選択肢に入れます) - 反復回数(Iterations): 最低でも 600,000回(60万回)以上 (※マシンの性能向上やNISTの勧告の改定に伴い、年々引き上げられています)
- ソルトの長さ: 最低でも 16バイト(128ビット)以上 の暗号学的乱数を使用する
—
4. 実装例:PHPでPBKDF2を安全に使ってみよう
それでは、実際の開発現場でどのようにPBKDF2を使うのか、PHPのサンプルコードを見てみましょう。最近のPHPでは標準関数として安全な実装が用意されているので、とても簡単です!
以下のコード例には、実務でそのまま参考にできるよう日本語で丁寧なコメントを入れています。
<?php
/**
* PBKDF2を用いた安全なパスワードハッシュ生成と検証のサンプルコード
*
* 現代のPHP(7.0以降)では、パスワードハッシュには password_hash() を使うのが基本ですが、
* 内部で使われている Bcrypt や Argon2 と並び、PBKDF2の仕組みを理解・実装する際の参考にしてください。
*/
// 1. ユーザーが入力した平文のパスワード(実際にはフォーム等から受け取る)
$plainPassword = "User_Secure_Password_123!";
// 2. 暗号学的に安全なランダムなソルトを生成 (最低16バイト推奨)
// random_bytes() は予測不可能な安全な乱数を生成します
$salt = random_bytes(16);
// 3. 推奨パラメータの設定
// HMACアルゴリズムとして sha256 を指定
$algorithm = "sha256";
// NIST推奨の反復回数(システムのパフォーマンスとセキュリティのバランスを見て調整)
$iterations = 600000;
// 生成するハッシュの長さ(バイト数。sha256の場合は32バイト)
Image::(length); // ダミー、正しくは以下の関数を使います
$length = 32;
// 4. hash_pbkdf2 関数を使って鍵導出(ハッシュ化)を実行
$hashedPassword = hash_pbkdf2(
$algorithm, // アルゴリズム
$plainPassword, // パスワード平文
$salt, // ソルト(生バイナリ)
$iterations, // 反復回数
$length, // 出力長
false // trueにすると生のバイナリ出力、falseで16進数文字列
);
// データベースには「ハッシュ値」「ソルト」「反復回数」の3つをセットで保存します!
// 例: $db->save($userId, $hashedPassword, bin2hex($salt), $iterations);
echo "生成されたハッシュ値: " . $hashedPassword . "\n";
echo "使用したソルト (Hex): " . bin2hex($salt) . "\n";
/**
* 5. ログイン時のパスワード検証プロセス
* データベースから取得した値を使って、入力されたパスワードが正しいか検証します。
*/
function verifyPassword(string $inputPassword, string $storedHash, string $hexSalt, int $iterations): bool {
// 保存されていた16進数のソルトをバイナリに戻す
$decodedSalt = hex2bin($hexSalt);
// 入力されたパスワードを、保存時と同じパラメータで再度PBKDF2に通す
$checkHash = hash_pbkdf2(
"sha256",
$inputPassword,
$decodedSalt,
$iterations,
32,
false
);
// hash_equals を使うことで、タイミング攻撃(処理時間の差からデータを推測する攻撃)を防ぎます
return hash_equals($storedHash, $checkHash);
}
// 検証テスト
$isLoginSuccess = verifyPassword("User_Secure_Password_123!", $hashedPassword, bin2hex($salt), $iterations);
if ($isLoginSuccess) {
echo "ログイン成功!パスワードが一致しました。\n";
} else {
echo "ログイン失敗。パスワードが間違っています。\n";
}
?>
—
5. まとめ:一歩ずつ、確実なセキュリティ対策を
今回は、パスワード保護の要であるPBKDF2の仕組みと、現場で実践すべき推奨パラメータについて解説しました。
- 普通のハッシュ(SHA-256など)は速すぎるため、パスワードの直接保存には不向き。
- PBKDF2は「ソルト」と「ストレッチング(反復処理)」によって、攻撃者の計算を途方もなく遅くする。
- NISTの推奨に従い、反復回数は60万回以上、ソルトは必ずランダムなものを使用する。
セキュリティの対策は、最初はいろいろな用語が出てきて難しく感じるかもしれませんが、一つひとつの技術が「なぜ必要なのか」のストーリー(防犯の例えなど)を理解すれば、決して怖くありません。
皆さんが構築するシステムが、サイバー攻撃からしっかりとユーザーを守れる堅牢なものになるよう、ぜひ今回の知識を実務の設計やコードレビューに役立ててくださいね。
それでは、また次回のセキュリティ解説でお会いしましょう!一歩ずつ、安全な開発を一緒に進めていきましょう!
コメント