テック技報最新号へ →
セキュリティ

パスワードハッシュは「アルゴリズム+コストパラメータ」まで決める(Argon2id / scrypt / bcrypt / PBKDF2)

DB が盗まれた後の総当たりはログイン回数制限が効かないオフライン攻撃になる。速いハッシュ(SHA-256 / MD5)をやめ、わざと重い関数を OWASP の最低ライン以上のパラメータで使い、あとから強化できる仕組みも入れておく。

@yousukezan · 2026-10-16
#password#hashing#argon2#bcrypt#scrypt#authentication#data-breach

何を解決するか / いつ使うか

  • 新規にパスワード保存を実装するとき、または既存システムの設定値が数年前のまま放置されていないか点検するとき。
  • 最近の国内漏洩事案では、パスワードが平文保存だったケース(個人情報保護委員会の公表による KDDI の ISP 向けメールシステムの件など)が目立つ。侵入を 100% 防げなくても、「盗まれた後に読まれにくくする」部分は設計で変えられる。

なぜ SHA-256+ソルトでは足りないか

  • SHA-256 / MD5 は速く計算できるように作られており、GPU で 1 秒に膨大な候補を試せる。
  • ソルトはレインボーテーブル(事前計算の対応表)を無効にし、全ユーザーをまとめて照合できなくするだけ。1 件あたりの総当たり速度は変わらない(ソルトも DB と一緒に盗まれる)。

選ぶアルゴリズム(OWASP の優先順位)

  1. Argon2id(メモリハード。RFC 9106)
  2. 使えなければ scrypt(メモリハード)
  3. どちらも使えないレガシー環境では bcrypt
  4. FIPS-140 準拠が必要なら PBKDF2-HMAC-SHA-256

最低ラインのパラメータ(2026-10 時点の OWASP Password Storage Cheat Sheet)

アルゴリズム最低ライン補足
Argon2idm=19 MiB(19456 KiB), t=2, p=1同等の組み合わせ例: m=46MiB/t=1、m=12MiB/t=3、m=9MiB/t=4、m=7MiB/t=5(いずれも p=1)
scryptN=2^17, r=8, p=1(約 128 MiB)同等例: N=2^16, r=8, p=2
bcryptcost 10 以上cost が 1 上がるごとに計算量は約 2 倍。入力は 72 バイトまで
PBKDF2HMAC-SHA-256, 600,000 回以上FIPS-140 が必要な場合の選択肢
  • RFC 9106 自体はもっと重い設定を推奨している(第一推奨 t=1/p=4/2GiB、低メモリ向け t=3/p=4/64MiB)。OWASP の値はあくまで下限。
  • アルゴリズムごとに仕組みが違うので、scrypt の 128MiB と Argon2id の 19MiB を数字だけで比べない。

決め方の手順

  1. 本番相当の環境で実測し、ログイン待ち時間が許容できる範囲で一番重い値を選ぶ(開発機の感覚で決めない)。
  2. 同時ログインのピーク時にメモリが足りるか見積もる(Argon2 / scrypt はリクエストごとに大きなメモリを使う)。
  3. ログイン試行にレート制限をかけ、重い処理を DoS に悪用されないようにする。
  4. ライブラリのサンプルにある低い cost(4〜6 など)をそのまま本番に入れていないか確認する。ライブラリ既定値も変わる(PHP 8.4.0 で bcrypt の既定 cost が 10→12)。
  5. bcrypt を使うなら入力長を 72 バイト以下に制限する(日本語は UTF-8 で 1 文字 3 バイトが多く、約 24 文字で超える)。

あとから強化できるようにする

  • ログイン成功時に再ハッシュ: 平文が手元にある瞬間に、保存ハッシュが古い方式・低コストなら新しい設定でハッシュし直して保存する。方式とパラメータがハッシュ文字列に埋め込まれる形式($argon2id$v=19$m=... や $2b$12$...)なら古さの判定が簡単。
  • ログインしないユーザーの古いハッシュは残り続ける点に注意。
  • SHA-256 などからの一括移行: 旧ハッシュ値を新しい関数の入力にする「ラップ」で全員分を即座に強化できる。ただし旧ハッシュ自体への辞書攻撃が残るので暫定措置とし、次回ログイン時に元のパスワードから直接ハッシュし直して置き換える(OWASP 推奨)。bcrypt に渡すときはバイト列ではなく base64 などの文字列にする(NUL バイト問題)。

注意点

  • ハッシュ化は万能ではない。123456 のような弱いパスワードは重くしてもすぐ当たり、使い回しの被害も防げない。アクセス制御や多要素認証(パスキーで「詰まない」ための運用のコツ)は別途必要。
  • 公表文の「暗号化して管理」は、可逆の暗号化かハッシュ化か、鍵も一緒に盗まれたかが読み取れない。自社の公表でも方式を曖昧にしない。
  • 推奨値は更新されるので、実装時に OWASP の最新版を確認する。

出典

X の元の投稿を開く