security-audit

パスワードハッシュ完全ガイド:アルゴリズム一覧と実務での選び方

MD5、SHA、PBKDF2、bcrypt、scrypt、Argon2、yescrypt、旧来形式を整理し、選定、パラメータ調整、移行方法まで解説する。

Jul 14, 2026
パスワードセキュリティパスワードハッシュ認証Argon2暗号技術

先に実務上の結論を書く。新しい一般的なパスワードデータベースなら、保守されているフレームワークやライブラリの Argon2id から始める。Argon2id を使えない場合は、メモリハードな scrypt が通常の次候補になる。検証済み暗号モジュールやコンプライアンス境界に制約される環境では、PBKDF2-HMAC に今も役割がある。既存の bcrypt は検証を続けられるが、72 バイトの入力境界を理解し、段階的な移行を用意したい。MD5、SHA-1、SHA-256、SHA-3、BLAKE2、BLAKE3 をそのままパスワード保存に使ってはいけない。

話がややこしくなるのは、「パスワードハッシュ」という言葉が別物をまとめて指しているからだ。高速なダイジェスト関数、古い OS の保存形式、パスワードから鍵を導出する KDF が同じ一覧に並ぶことがある。しかし、名前に hash が入っていても、オフライン攻撃者に課すコストは同じではない。

まず暗号プリミティブを分ける

種類復元できるか主な用途パスワード保存
暗号化鍵があれば可能復元が必要なデータの保護通常は不適切。復号鍵の漏えいで全件が露出する
汎用暗号学的ハッシュ不可逆完全性、署名、コンテンツ識別不適切。高速になるよう設計されている
MAC / HMAC不可逆、鍵付き真正性と完全性単独では不十分
パスワードハッシュ / KDF不可逆一回の推測を高コストにする適切な設定と実装なら利用できる

パスワード検証側は、元の文字列を復元できる形ではなく、導出値を保存する。ログイン時には保存済みの salt とパラメータを読み、入力されたパスワードを同じ方式で処理し、ライブラリの検証 API で比較する。

「一方向」は「解読不能」という意味ではない。データベースを盗んだ攻撃者は、候補パスワードを同じ公開アルゴリズムに通し、結果をオフラインで比較できる。したがってパスワードハッシュは攻撃コストの設計でもある。一回ごとの推測に時間とメモリを使わせ、漏えい直後にありふれたパスワードが大量復元されないようにする。

アルゴリズム以外に必要な要素

アルゴリズム名だけでは、保存レコードとして不十分だ。

  • **Salt:**パスワードごとに生成する一意のランダム値。同じパスワードから同じ保存値が生まれることや、一つの事前計算表が多数のアカウントに使い回されることを防ぐ。秘密ではなく、通常はハッシュと一緒に保存する。
  • **Work factor:**時間や反復回数を調整する値。ハードウェアの高速化に合わせて引き上げられる。
  • **メモリコスト:**一回の計算で必要になる作業メモリ。メモリハード設計は GPU や ASIC による大規模並列推測のコストを上げる。
  • **並列度:**同時に進める計算レーンなどを表す。意味はアルゴリズムごとに異なり、大きければ常に安全になるわけではない。
  • **Pepper:**パスワード DB とは別に保存する任意の秘密値。KMS、HSM、同等の保護境界に置く。DB だけが盗まれた場合の多層防御になる一方、紛失やローテーションは salt より難しい。現行 NIST ガイダンスも、可能なら検証側だけが持つ秘密鍵による追加処理を推奨している [5]
  • **バージョンとパラメータ:**どう生成したレコードかを保存する。これがなければ段階的な更新ができない。

Salt は事前計算とアカウント間の再利用を防ぐが、弱いパスワードを強くするものではない。Pepper は別の問題を扱う。DB だけを盗んだ攻撃者に、検証処理に必要な独立秘密を渡さないためのものだ。

アルゴリズムの全体像

高速な汎用ハッシュ:安全な用途はあるが、ここでは使わない

MD5、SHA-1、SHA-2、SHA-3、BLAKE2、BLAKE3 はデータを効率よく処理するための関数だ。SHA-2 と SHA-3 は標準化された汎用ハッシュで、BLAKE2 と BLAKE3 も効率的な計算を設計目標にしている [10] [11] [12] [13]。ファイル完全性、電子署名、Merkle tree、コンテンツアドレッシング、各種プロトコルでは速さが重要になる。オフラインのパスワード推測では、その速さが欠点になる。

系列現在の役割パスワード保存での判断
MD5旧式チェックサム。衝突耐性は破られているsalt の有無に関係なく使わない
SHA-1旧システム互換。衝突耐性は破られている直接使わない
SHA-2 / SHA-3現代の汎用ハッシュプリミティブは有効だが、単独では速すぎる
BLAKE2 / BLAKE3高性能な汎用ハッシュ高速性が目的であり、パスワードハッシュではない

パスワード保存で中心になる問題は衝突だけではない。攻撃者は確率の高い候補を試し、特定レコードの原像を探す。衝突耐性のある高速ハッシュでも、一秒に試せる候補が多ければ不利だ。SHA-256 に salt を加えるとレインボーテーブルの使い回しは防げるが、推測速度は下がらない。SHA-256 を自作ループで何度も回す方法も、符号化、パラメータ保存、更新方法、ハードウェア耐性がレビューされていない独自 KDF になる。

旧来のパスワード形式

監査や移行では次の形式を認識する必要がある。ただし、新しいパスワードを書き込む方式として選ぶものではない。

方式見分ける点実務での扱い
従来の DES cryptパスワード長と salt が短く、コストが初期 Unix のまま廃止。ログイン時移行かリセット
LM hash大文字小文字を区別せず分割処理し、構造上の弱点が大きい廃止対象
NT hash / NTLM password hashUTF-16LE パスワードの unsalted MD4Windows 互換用途のみ。可能なら移行
MD5-crypt($1$salt と反復を加えた MD5 の Unix 形式廃止対象
SHA-crypt($5$$6$SHA-256/SHA-512 と可変 rounds の Unix 形式Unix 互換。CPU-hard だがメモリハードではない
phpass portable hash古い PHP アプリの反復 MD5 形式移行元としてのみ扱う

libxcrypt は rounds を十分上げた SHA-256/512-crypt を Unix の新規ハッシュとして今も許容している。一方、OWASP のアプリケーション向け選定では Argon2id、次に scrypt が優先される [14]。対象環境が違うのであって、SHA-crypt がメモリハード KDF と同等という意味ではない。LM と NT hash も Windows 互換の資格情報であり、新規アプリの設計例にはならない [15] [16]。Openwall も phpass の portable MD5 fallback を延命保守と位置づけ、新しい PHP プロジェクトには標準 password API を案内している [19]

PBKDF2

PBKDF2 は疑似ランダム関数を反復実行する方式で、一般には HMAC と組み合わせる。PKCS #5 で標準化され、多くのプラットフォーム暗号 API が対応している [4]。相互運用性と実装の成熟度が高く、検証済み暗号モジュールでも利用しやすい。その反面、主に CPU 時間だけを使い、メモリ使用量が小さいため、並列攻撃用ハードウェアに最適化されやすい。

PBKDF2 を選ぶ理由は、実際のプラットフォームやコンプライアンス境界であるべきだ。「NIST」という名前だけで決めてはいけない。FIPS が検証するのは、配備された暗号モジュール、approved mode、設定、システム境界であり、ソースコードに書かれたアルゴリズム名ではない [17]。OWASP は FIPS-140 が必要な場合の現行基準として PBKDF2-HMAC-SHA-256 の 600,000 iterations を示している [1]。これは計測の出発点であり、永続的な万能値ではない。NIST SP 800-132 は 2010 年の文書で、現在改訂予定でもある。2026 年の固定 iteration 表として読むべきではない [6]

PBKDF1 は互換性のために残る方式であり、PKCS #5 は新規利用を推奨していない [4]

bcrypt

bcrypt は 1999 年、Blowfish の高コストな key schedule を使う方式として発表された。対数形式の cost と 128-bit salt を持ち、ハードウェアが速くなってもコストを上げられるようにした [7]

長い運用実績は強みだが、現代の設計として二つの制約がある。

  1. 使用メモリが小さく、Argon2 や scrypt の意味でメモリハードではない。
  2. 互換実装の多くは入力の先頭 72 バイトだけを使う。バイト数と文字数は違う。UTF-8 では 72 文字よりかなり前に上限へ達することがあり、上限超過時に切り捨てるか拒否するかもライブラリで異なる。

72 バイトより後ろだけが違う二つの入力を、同じパスワードとして静かに受け入れてはいけない。既存 bcrypt システムでは、正確なライブラリとバージョンをテストし、符号化と長さの扱いを決め、必ず verify API を使う。OWASP は bcrypt をレガシー用途とし、維持する場合は work factor 10 以上を求めている [1]

先に SHA-512 をかけてから bcrypt に渡す案も、単純な修正ではない。domain separation、バイナリ表現、NUL、切り捨て、password shucking といった追加問題が生まれる。採用するなら、バージョン、形式、テスト、移行方法を持つ一つのプロトコルとして設計する必要がある。

scrypt

scrypt は計算時間と大きなメモリを同時に要求する。主なパラメータは Nrp で、CPU/メモリコスト、block size、並列度を制御する。RFC 7914 が構成と test vector を定義している [3]

Argon2id を使えない環境では、scrypt は今も妥当な候補だ。ただしパラメータを理解せずコピーしやすい。OWASP の現行基準で最初に挙げられる組は N=2^17, r=8, p=1 で、およそ 128 MiB を使う。ほかには、並列計算を増やしてメモリを下げる組もある [1]。単発の benchmark だけでなく、認証ピーク時の同時実行数で確認しなければならない。

Argon2d、Argon2i、Argon2id

Argon2 は Password Hashing Competition の勝者で、後に RFC 9106 で仕様化された。メモリサイズ m、pass 数 t、並列度 p を持ち、エンコード形式には variant、version、salt、各パラメータを含められる [2]

  • Argon2d はデータ依存のメモリアクセスを使う。time-memory trade-off への耐性は高いが、アクセスパターンの side channel が問題になり得る。一般的なパスワード DB の標準選択ではない。
  • Argon2i はデータ非依存アクセスで side channel を抑えるが、一部の trade-off 攻撃に対して追加 pass が必要になる。
  • Argon2id は Argon2i 型で始まり、その後 Argon2d 型へ切り替える。RFC 9106 と OWASP がパスワード保存に推奨するバランス型である [1] [2]

信頼できる文書が違う数値を示していても、必ずしも矛盾ではない。RFC 9106 の統一推奨は 2 GiB、t=1p=4、またはメモリ制約下で 64 MiB、t=3p=4。どちらも 128-bit salt と 256-bit 出力を使う。OWASP はアプリケーションサーバー向けの実用下限を示し、最初の組は 19 MiB、t=2p=1 だ。想定するリソース予算が違う。適用するガイダンスの下限を守りつつ、実環境で維持できる最大限のメモリを使い、測定して決める。

yescrypt と Balloon Hashing

yescrypt は scrypt を基礎に、大規模な解読コストを高めるモードを追加した方式だ。論文上だけの存在ではなく、Openwall によれば複数の Linux distribution でシステムパスワードの標準方式になっている [8]。OS と libxcrypt/etc/shadow を管理する環境では有力な選択になる。一方、複数言語で動く Web サービスなら、ガイダンスとライブラリ対応の広い Argon2id の方が通常は導入しやすい。

Balloon Hashing はデータ非依存アクセスを使うメモリハード方式で、論文には形式的な分析と sequential attack model の限界が示されている [9]。ただし一般的な認証フレームワークの対応は Argon2id、scrypt、PBKDF2、bcrypt より少なく、著者自身も公開 prototype は本番利用に安全ではないと警告している [18]。重要な研究設計ではあるが、通常の標準選択ではない。

Catena、Lyra2、Makwa、POMELO など Password Hashing Competition の候補にも研究価値がある。しかし、学術的な価値と、成熟したライブラリ、保存形式、運用ツールが揃うことは別の評価軸だ。

実務での選び方

状況基本方針理由
新規アプリ、通常のサーバーArgon2idメモリハード、現行推奨、自己記述形式を使える
Argon2 はないが成熟したメモリハード KDF があるscrypt標準化され実装も広い
検証済みモジュールや FIPS 境界があるapproved module 内の PBKDF2-HMAC実際の module と security policy の確認が必要
安定稼働中の bcrypt DB検証を維持し、実測で cost を上げ、Argon2id へ移行一斉切替のリスクを避けながら旧制約を解消する
現代的 Linux distribution が管理する Unix loginOS が対応する yescrypt / Argon2 policyPAM、crypt、復旧ツール、形式を揃えられる
MD5、SHA、LM/NTLM-only、DES-crypt など優先移行またはパスワードリセットオフライン推測コストや形式上の安全性が不足する

アルゴリズム選定はキャパシティ設計でもある。一回 64 MiB を使う検証に数千の同時リクエストを許せば、メモリを枯渇させられる。rate limit、キュー、timeout、アカウント悪用対策、負荷試験もパスワードハッシュ設計に含まれる。オンライン DoS が怖いからといって KDF を危険なほど軽くするのは解決にならない。

パラメータは検証を実行する環境で決める

権威ある設定例は下限と benchmark の開始点であり、計測の代わりではない。

  1. 利用者が許容でき、サービスが継続処理できる検証時間を決める。OWASP はおおむね一秒未満を目安にするが、オンラインサービスではさらに短く設定することも多い。
  2. 本番に近い CPU、メモリ、container の cgroup、serverless の制限で測る。
  3. 一回の中央値だけでなく、ピーク時の同時ログインを試す。
  4. パスワード不一致と rate limiter の経路を試し、無効リクエストの計算量を制御する。
  5. algorithm、variant、version、parameters、salt、output を保存する。対応ライブラリでは PHC string などの自己記述形式を使う。
  6. 定期的に benchmark をやり直し、policy 更新後はログイン成功時に rehash する。

Salt を username や timestamp から作ってはいけない。パスワードライブラリか暗号学的擬似乱数生成器に任せる。最終比較も通常の文字列比較ではなく、フレームワークの定数時間 verify API を使う。

入力処理も仕様にする。製品として明示的な normalization policy がない限り、空白の trim、大文字小文字の変更、別入力を同じにする Unicode 正規化を黙って行わない。NIST が認める入力補正も限定的で、文書化が必要であり、長いパスワードへの対応も求めている [5]

一斉切替を避ける移行

保存済みハッシュをそのまま Argon2id へ「変換」することは通常できない。旧レコードに元パスワードが入っていないからだ。安全に再ハッシュできる時点はログイン成功時で、アプリが入力パスワードを一時的に持っている瞬間になる。

保存レコードからアルゴリズムとパラメータを読む
旧方式で検証する
検証成功かつ policy 上 rehash が必要なら:
    入力されたパスワードを現行方式でハッシュする
    保存レコードを原子的に置き換える
入力パスワードを破棄する

段階移行は次の流れにできる。

  1. DB に残る全形式を検証できるようにする。
  2. 現行の algorithm と parameter profile を一つ決める。
  3. 旧形式の検証に成功した直後、新形式を生成して置換する。
  4. 長期間ログインしないアカウントは期限後に安全な reset flow へ送る。
  5. 形式別件数を監視し、ゼロになってから旧 verifier を削除する。

旧ハッシュを新 KDF の入力にする二重ハッシュは、平文がない状態で一時的にコストを追加できる場合がある。しかし元パスワードの entropy は増えず、切り捨てや旧形式の欠点も直らない。独自形式も増えるので、version と終了条件を持つ一時的な橋としてのみ使う。

Pepper のローテーションにも同じ制約がある。旧 pepper が必要なレコードを残したまま鍵を削除すると、全員がログインできなくなる。移行期間は version 付き鍵を保持するか、パスワードリセットを求める。DB の書き換えだけで失われた秘密を再作成することはできない。

レビュー用チェックリスト

  • 単なる暗号学的ハッシュではなく、パスワード向け関数を使っているか。
  • パスワードごとに一意のランダム salt があるか。
  • algorithm、version、parameters、salt、output を曖昧なく識別できるか。
  • 本番相当の hardware とピーク並列数で時間、メモリを測ったか。
  • bcrypt の byte 上限、文字 encoding、Unicode 処理、最大リクエスト長を定義したか。
  • Pepper は DB 外にあり、ローテーションと復旧方法があるか。
  • 保守中ライブラリの API と定数時間比較を使っているか。
  • 古い parameter を判定し、ログイン成功後に rehash できるか。
  • rate limit と容量制御で KDF を DoS 手段にさせないか。
  • コンプライアンス判断はアルゴリズム名ではなく、実際の検証済み module と mode に基づくか。

長く使える原則は「一つのハッシュを永久に使う」ことではない。レビュー済みのパスワードハッシュを選び、完全なパラメータを保存し、実システムで計測し、移行経路を残す。Argon2id は今日の一般的な出発点だが、将来の変更に耐えるのは version 付きレコードと rehash の仕組みである。

参考文献

[1] OWASP Foundation. “Password Storage Cheat Sheet.” https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html

[2] A. Biryukov et al. “Argon2 Memory-Hard Function for Password Hashing and Proof-of-Work Applications.” RFC 9106. https://www.rfc-editor.org/rfc/rfc9106.html

[3] C. Percival and S. Josefsson. “The scrypt Password-Based Key Derivation Function.” RFC 7914. https://www.rfc-editor.org/rfc/rfc7914.html

[4] K. Moriarty et al. “PKCS #5: Password-Based Cryptography Specification Version 2.1.” RFC 8018. https://www.rfc-editor.org/rfc/rfc8018.html

[5] National Institute of Standards and Technology. “SP 800-63B: Authentication and Authenticator Management.” https://pages.nist.gov/800-63-4/sp800-63b.html

[6] National Institute of Standards and Technology. “SP 800-132: Recommendation for Password-Based Key Derivation, Part 1.” https://csrc.nist.gov/pubs/sp/800/132/final

[7] Niels Provos and David Mazières. “A Future-Adaptable Password Scheme.” USENIX ATC 1999. https://www.usenix.org/conference/1999-usenix-annual-technical-conference/future-adaptable-password-scheme

[8] Openwall. “yescrypt — scalable KDF and password hashing scheme.” https://www.openwall.com/yescrypt/

[9] Dan Boneh, Henry Corrigan-Gibbs, and Stuart Schechter. “Balloon Hashing: A Memory-Hard Function Providing Provable Protection Against Sequential Attacks.” https://eprint.iacr.org/2016/027

[10] National Institute of Standards and Technology. “Secure Hash Standard (SHS).” FIPS 180-4. https://csrc.nist.gov/pubs/fips/180-4/upd1/final

[11] National Institute of Standards and Technology. “SHA-3 Standard.” FIPS 202. https://csrc.nist.gov/pubs/fips/202/final

[12] M-J. Saarinen and J-P. Aumasson. “The BLAKE2 Cryptographic Hash and Message Authentication Code.” RFC 7693. https://www.rfc-editor.org/rfc/rfc7693.html

[13] BLAKE3 Team. “BLAKE3 specification and implementations.” https://github.com/BLAKE3-team/BLAKE3

[14] libxcrypt Project. “crypt(5): password hashing methods and prefixes.” https://man.archlinux.org/man/crypt.5.en

[15] Microsoft. “Prevent Windows from storing an LM hash of your password.” https://learn.microsoft.com/en-us/troubleshoot/windows-server/windows-security/prevent-windows-store-lm-hash-password

[16] Microsoft Open Specifications. “MS-NLMP: NTLM v1 Authentication.” https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/464551a8-9fc4-428e-b3d3-bc5bfb2e73a5

[17] NIST Cryptographic Module Validation Program. “FIPS 140-3 standards and approved security functions.” https://csrc.nist.gov/Projects/cryptographic-module-validation-program/fips-140-3-standards

[18] Stanford Applied Cryptography Group. “Balloon Hashing project and prototype.” https://crypto.stanford.edu/balloon/

[19] Openwall. “Portable PHP password hashing framework.” https://www.openwall.com/phpass/