PBKDF2入門ガイド:安全なパスワードストレージの鍵導出と実装ポイント
PBKDF2 とは — 概要
PBKDF2(Password-Based Key Derivation Function 2)は、パスワードやパスフレーズから暗号鍵やハッシュを安全に生成するための鍵導出関数です。元は RSA の PKCS #5 規格の一部として定められ、その仕様は IETF の RFC にもまとめられています。PBKDF2 は HMAC を擬似乱数関数(PRF)として繰り返し適用することにより、短く低エントロピーなパスワードをより強力な鍵材料に変換します。
なぜ PBKDF2 が使われるのか
単純なハッシュ(例えば SHA-256)をパスワードに直接適用すると、ブルートフォース攻撃やレインボーテーブル攻撃に弱い。PBKDF2 は「ソルト」と「反復回数(イテレーション)」を導入して、攻撃コストを大幅に増加させる。
PBKDF2 は仕様が長く使われてきたため、多くのライブラリやプラットフォームで利用可能であり、導入が容易である。
パラメータ(ソルト、イテレーション、PRF)を変えることで運用環境に合わせた調整が可能。
アルゴリズムの仕組み(技術的詳細)
PBKDF2 は以下のパラメータを用いる:
Password(パスワード / パスフレーズ)
Salt(ソルト:ランダムデータ)
c(反復回数:iteration count)
PRF(擬似乱数関数、通常は HMAC-SHA 系)
dkLen(導出鍵長:desired key length)
出力は指定した長さの派生鍵(Derived Key, DK)です。内部ではブロック単位の計算を行い、各ブロック T_i は次のように定義されます(RFC の表記に準拠):
U1 = PRF(Password, Salt || INT(i))
U2 = PRF(Password, U1)
U3 = PRF(Password, U2)
…
Uc = PRF(Password, U_{c-1})
T_i = U1 XOR U2 XOR ... XOR Uc
ここで INT(i) は 4 バイトの大きさで i をビッグエンディアン表現にしたもの(RFC 準拠)です。DK は必要なブロック数だけ T_i を連結して先頭から dkLen バイト切り取ったものになります。
注意点として、最大で導出可能な鍵長は (2^32 - 1) * hLen(hLen は PRF の出力長)です。
主要パラメータの選び方と運用上の注意
ソルト(Salt): 各ユーザー/エントリごとに一意のランダム値を用いる。一般的には 16 バイト以上の真の乱数(CSPRNG)を推奨。ソルトは秘密にする必要はなく、ハッシュと共に保存する。
反復回数(c): 高いほど攻撃コストが増えるが、正当な認証処理の負荷も増える。固定の「安全な最小値」を示す公式は状況によるため、サーバーでの実行時間を測定して「認証にかけられる許容時間(例:100–500 ms 程度)」を目安に調整するのが現実的。将来的にハードウェアが高速化したら増やせるように、反復回数は各ハッシュと一緒に保存しておく。
PRF(HMAC のハッシュ関数): SHA-1、SHA-256、SHA-512 などが選べる。現在は SHA-1 は衝突攻撃の観点から推奨されないため、HMAC-SHA256 以上の選択が望ましい(ただし HMAC-SHA1 自体は衝突脆弱性の影響を受けにくい場面があるが、将来性を考慮して強いハッシュを用いるのが一般的)。
導出鍵長(dkLen): 目的に応じた長さを指定。鍵生成(例:AES-256)であれば 32 バイト等。長すぎると余分な計算が発生する。
保存フォーマットと運用例
パスワードハッシュをデータベースに保存する際は、少なくとも以下を保持する:
ソルト(Salt)
反復回数(iteration count)
使用した PRF(例:HMAC-SHA256)やアルゴリズム名
導出鍵(ハッシュ値)
典型的な保存フォーマットの例(実装に依存):
$pbkdf2$sha256$100000$saltbase64$dkbase64
あるいは JSON で { "alg":"PBKDF2-HMAC-SHA256", "iter":100000, "salt":"...", "dk":"..." } のように保存する方式もある。
重要なのは、イテレーション数やアルゴリズムを後から変更できるようにメタデータを保持しておくことです。既存ユーザーのハッシュはログイン時に再生成して更新するか、段階的にマイグレーションする必要があります。
攻撃シナリオと弱点
GPU/ASIC による並列化: PBKDF2 は主に CPU 時間に依存する(メモリ使用量は少ない)ため、高度な GPU や専用チップで並列化されると攻撃効率が高くなる。メモリハードな KDF(Argon2、scrypt 等)に比べて耐性は低い。
低イテレーション/固定ソルト: イテレーションが低すぎたりソルトを使い回すと容易にブルートフォースされる。必ず十分なランダムソルトを各エントリで利用し、イテレーションは運用上可能な範囲で高く設定する。
アルゴリズムの陳腐化: ハッシュ関数(例えば SHA-1)や暗号標準の脆弱性が見つかった場合、迅速により強力な PRF(例:HMAC-SHA256)へ移行する計画が必要。
PBKDF2 と他の鍵導出関数との比較
bcrypt: 内蔵でソルトとコストファクタを持つ。設計上メモリ使用は中程度で、PBKDF2 より GPU に対する耐性がある場合がある。
scrypt: メモリハード設計で GPU/ASIC による高速化に強い。
Argon2: 近年の推奨されるメモリハード KDF(Argon2i, Argon2d, Argon2id)。攻撃耐性が高く、パスワードストレージ用途での現在のファーストチョイスの一つ。
結論として、「既存の互換性や広いサポートのために PBKDF2 を選ぶ」ケースは依然として多いが、新規設計では Argon2 などメモリハードな関数を検討する価値が高い。
実装例とライブラリ
OpenSSL: PKCS5_PBKDF2_HMAC 関数などで PBKDF2 を利用可能(digest を指定して HMAC-SHA256 等を選択)。
Python: hashlib.pbkdf2_hmac(hash_name, password, salt, iterations, dklen=None)
Node.js: crypto.pbkdf2 / crypto.pbkdf2Sync(第2引数でハッシュ関数を指定可能)
Java: SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256") 等(バージョンやプロバイダによってサポート状況を確認すること)。
実装の際はライブラリのドキュメントに従い、バイナリ→Base64 や hex での保存、エンコード/デコードに注意してください。
移行・マイグレーション戦略
古いハッシュ(例:PBKDF2-HMAC-SHA1 あるいは小さなイテレーション)からの移行は、ユーザーのパスワードが再入力される(ログイン)タイミングで新しいアルゴリズム/パラメータで再ハッシュして更新する「漸進的マイグレーション」が現実的。
全ユーザー一斉の強制リセットを行う場合は、ユーザービリティとセキュリティのバランスを考慮する。可能ならば段階的に更新する方が摩擦が少ない。
運用時の推奨事項(チェックリスト)
各エントリにユニークなランダムソルト(少なくとも 16 バイト)を使用する。
PRF は HMAC-SHA256 以上を優先する(互換性要件がある場合は注意)。
反復回数はサーバーでの実行時間を基に決め、将来増やせるようにメタデータとして保存する。通常は短すぎない(数千〜数十万のレンジだが、ハードウェアと許容レスポンスタイムに依存)。
検出されたアルゴリズム脆弱性やハードウェアの進化に備え、より強力な KDF への移行プランを用意する。
PBKDF2 はメモリハードではないため、特に高価値なシステムでは Argon2 等の検討を行う。
まとめ
PBKDF2 は長年にわたり広く使われているパスワードベースの鍵導出関数であり、適切に使えばパスワードストレージにおいて十分な安全性を提供します。ただし、ソルト、十分な反復回数、強い PRF の採用といった運用ルールを守ることが前提です。GPU/ASIC による並列化に弱い点や、メモリハード性がない点を考慮すると、新規システムや高セキュリティが求められる用途では Argon2 等の選択も検討すべきです。いずれにせよ、パラメータは運用中に見直し・更新できるように設計しておくことが重要です。
参考文献
- RFC 8018 — PKCS #5: Password-Based Cryptography Specification Version 2.1 (2016)
- RFC 2898 — PKCS #5: Password-Based Cryptography Specification Version 2.0 (2000)
- OWASP Password Storage Cheat Sheet
- NIST SP 800-63B — Digital Identity Guidelines: Authentication and Lifecycle
- Python hashlib.pbkdf2_hmac ドキュメント
- OpenSSL PKCS5_PBKDF2_HMAC ドキュメント
- Wikipedia: PBKDF2(参照用)


