パスワードハッシュ・Salt・PBKDF2・bcrypt・scrypt・Argon2id
APP-1の利用者アリスがパスワードでログインするとき、サーバは照合用の値をどう保存すべきでしょうか。データベースDB-1が流出しても、攻撃者に大量の候補を高速で試させないための設計を、Salt、Stretching、PBKDF2、bcrypt、scrypt、Argon2idで追います。以下の構成、利用者、時刻、ログは教材用の架空例です。
読む順序は、ログインと保存の流れ→各方式のパラメータ→DB流出時の攻撃→移行と復旧→演習です。暗号学的ハッシュを使っていても、SHA-256を一回だけ計算した保存形式はパスワード向きではありません。
1. APP-1とDB-1で何を保存し、何を保存しないか
用語 | この事例での意味 |
|---|---|
パスワードハッシュ | 入力パスワードから検証用の値を作る一方向の保存方式。ログイン時に同じ設定で計算して照合する。復号して元のパスワードを返す設計ではない。 |
Salt | 利用者ごと、パスワードごとに独立して生成するランダム値。DB-1にハッシュと一緒に保存してよい。秘密ではない。同じパスワードでも異なる値にし、事前計算や一括照合を難しくする。 |
Stretching / work factor | 一回の推測に必要な計算時間やメモリを増やす考え方。正規ログインの負荷も増えるので、実環境の性能とDoS耐性を測って設定する。 |
PBKDF2 | HMAC等を繰り返し使うパスワードベースの鍵導出関数。反復回数が主な調整値。新規システムで使うなら適切なPRF、反復数、Saltを選ぶ。 |
bcrypt | パスワード保存に使う適応型方式。costで計算量を調整する。多くの実装で入力の72バイト制限に注意。古い形式の維持・移行時に扱う。 |
scrypt | 計算時間に加えてメモリも使う方式。主なパラメータはN、r、p。攻撃者の専用ハードウェアによる大量試行を難しくする。 |
Argon2id | 時間とメモリの両方を調整できる方式。主なパラメータはメモリm、反復t、並列度p。新規システムでの第一候補として検討する。 |
APP-1はアリスの登録時にランダムSaltを作り、Argon2idで照合値を作ります。DB-1に保存するのはアルゴリズム名、版、パラメータ、Salt、出力値です。平文パスワード、同じパスワードを復号できる鍵、パスワードの一部をログへ保存しません。
パスワードは通信路を通るが、DB-1には保存せず、アプリ側で照合値を作る。
図のAPP-1は受け取ったパスワードをメモリ上で処理します。通信路のTLSは盗聴対策ですが、サーバが平文を受け取ることや、サーバ側侵害を防ぐものではありません。APP-1のログ・トレース・エラー出力にも平文を残さない設計が必要です。
2. 同じパスワードでもSaltを変える理由
アリスとボブが同じパスワードを使っても、それぞれ別Saltなら保存値は通常異なります。攻撃者がDB-1を得て候補を試すとき、各利用者についてSaltを使って計算し直す必要があります。Saltは攻撃を不可能にするものではありません。弱いパスワードは候補から推測され得ます。
Saltを全ユーザー共通の固定文字列にすると同じパスワードに同じ保存値ができ、事前計算への耐性も下がります。ランダム値は利用者ごとだけでなく、パスワード再設定時にも新しく作ります。DBにSaltが保存されていること自体は設計ミスではありません。
保存項目 | 例と意味 |
|---|---|
algorithm / version | `argon2id`とフォーマット版。将来の移行時に旧方式の照合と新方式への更新を選ぶ。 |
m / t / p | この例はm=19456 KiB、t=2、p=1。19 MiB程度のメモリを使う。数値はOWASPの最低例を採った教材設定で、実運用は負荷測定と最新指針で決める。 |
salt | 利用者ごとに新しく作る16バイトのランダム値。値は公開可能だが、再利用を避ける。 |
hash | 照合用の出力値。DBに保存し、照合に使う。秘密のパスワードそのものではないが、漏えいすればオフライン推測の対象になる。 |
pepper(任意) | DBとは別に保管する共有秘密の追加防御。Saltとは目的と保管場所が違う。紛失時に既存ハッシュを検証できなくなる設計に注意する。 |
次は架空の認証ログで、実際のSaltやハッシュは表示しません。`argon2id`のmはKiB単位、tは反復回数、pは並列度として記録します。`verify=ok`は入力が保存値に合ったことを示すだけで、利用者本人が入力したことは証明しません。
13:00:00 user=alice event=login-start
13:00:00 user=alice scheme=argon2id v=19
m_kib=19456 t=2 p=1 salt_id=S-41
13:00:01 user=alice verify=ok action=session-create
13:00:01 user=alice rehash_needed=false`salt_id`は監査用の識別子です。パスワードの入力値やハッシュ本体をログに出しません。`session-create`は認証後のセッション発行であり、そのセッションの安全性はCookie設定や失効処理など別の仕組みにも依存します。
3. PBKDF2・bcrypt・scrypt・Argon2idを比較する
方式 | 設定する値と、この事例での判断 |
|---|---|
PBKDF2-HMAC-SHA-256 | 反復回数、Salt、出力長を指定する。FIPS系要件がある構成で採用を検討する。OWASPの参考下限例は600,000回だが、採用時点の指針と実機負荷で調整する。メモリ負荷を大きくする方式ではない。 |
bcrypt | costとSaltを使う。既存の利用者データなら検証・移行を計画する。入力の72バイト制限をコードポイント数と混同しない。単純な事前SHA-256で長さ制限を回避する処理にも注意。 |
scrypt | N、r、pで計算とメモリを調整する。Nは通常2のべき乗。サーバ側メモリ不足でログイン障害を起こさないよう、同時認証数で容量を見積もる。 |
Argon2id | m、t、pを設定する。mを大きくすれば攻撃コストが上がる一方、正規の大量ログイン時もメモリを消費する。パラメータを保存して段階的に更新する。 |
SHA-256一回 | 高速すぎてDB流出時のオフライン推測を安価にする。Saltを付けても計算自体が速いまま。パスワード保存の新規設計には使わない。 |
Stretchingは『同じSHA-256を何度も回せばどの専用方式とも同じ』という意味ではありません。PBKDF2は反復構成を規定し、scryptとArgon2idはメモリ消費を設計に取り込みます。独自方式を作るより、十分に検証された実装と保存フォーマットを使います。
4. DB-1が漏えいした場合に攻撃者ができること
攻撃者がDB-1の利用者ID、Salt、ハッシュを取得したとします。APP-1へログインせずに、候補パスワードとSaltから同じ方式の出力を計算し、保存値と比較できます。オンラインの試行回数制限はこのオフライン推測には効きません。強いパスワード、適切なコスト、利用者ごとのSaltが重要です。
攻撃者が得たもの | 影響と残る対策 |
|---|---|
DBのハッシュとSalt | オフライン推測が可能。Saltは秘密でなくてもよいが、コストの低いハッシュや弱いパスワードは危険。漏えい範囲と再設定対象を決める。 |
DBとpepper | 追加秘密も得たならpepperによる防御は失われる。別保管・アクセス監査と鍵更新が必要。 |
APP-1の実行環境 | 入力中の平文、照合前後のメモリ、セッション、pepperにアクセスされ得る。保存方式だけで守れない。 |
ログイン画面へのアクセスだけ | オンライン推測。レート制限、MFA、異常検知、漏えい済みパスワードの拒否などを組み合わせる。 |
`verify=ok`は正しいパスワードが入力されたことを示しても、盗まれたパスワードを攻撃者が使った可能性を排除しません。異常な端末、IP、セッション、MFA結果を調査します。一方、MFAがあるからパスワードハッシュの漏えいが無害になるわけでもありません。同じパスワードの使い回しが他サービスに波及します。
5. 設定変更、移行、障害と復旧
既存のbcrypt保存値は急にArgon2id形式へ変換できない。元のパスワードを復元できないため、次回の正しいログイン時に旧方式で照合し、その入力から新しいSaltとArgon2id値を生成して置き換える。
長期間ログインしない利用者には、安全な再設定手続きを用意する。旧ハッシュを無期限に残すか、期限後に再設定を求めるかをリスクに応じて決める。
パラメータを上げる前に、通常・ピーク・攻撃時の同時認証数とメモリ消費を測る。認証が遅すぎて可用性を失うなら、適切な処理制限と容量を設計する。
DB漏えい時はハッシュ形式とコスト、アクセス時刻、pepper保管先の侵害有無を調べ、影響利用者へ通知し、必要なパスワード再設定とセッション失効を実施する。
パスワードを変更した後は、新Saltと新パラメータで保存されたか、旧セッションやリセットトークンが適切に失効したかを確認します。障害復旧で古いDBバックアップを戻すと、以前のハッシュと失効済みセッションが復活し得ます。復旧後の利用者状態と認証イベントを検証します。
入力の正規化方針を無断で変えないことも重要です。Unicodeの扱い、大文字小文字、末尾空白の削除を途中で変えると、利用者が同じつもりで入力しても照合できなくなります。変更前に既存アカウントへの影響と移行方法を決め、平文をログへ残さずに失敗率を監視します。
5-1. パラメータを性能値として読む
m=19456 KiBは一回のArgon2id計算でおよそ19 MiBを使う設定です。同時に100件の検証が走れば、単純計算でも約1.9 GiBの作業メモリが必要です。実際には実装の追加負荷や並列度、サーバの他処理もあるため、ピーク時の認証数とコンテナのメモリ上限を測って決めます。
tを上げると利用者一人当たりの待ち時間が伸び、mを上げるとメモリ圧迫が増えます。pは単純な安全性倍率ではなく並列実行の設定です。攻撃者の試行コストだけでなく、正規利用者の応答時間、バッチログイン、再試行集中時の可用性を合わせて検証します。
ログ・メトリクス | 設定見直しの判断 |
|---|---|
verify_duration_ms | 通常時とピーク時の照合時間。遅延増加がCPU、メモリ、キューのどれに起因するか見る。 |
concurrent_verify | 同時照合数。mとの積を概算し、コンテナやノード全体の余裕を確保する。 |
rehash_needed | 旧方式や低コスト設定の利用者数を数える。移行が進まないアカウントに再設定を求める目安になる。 |
auth_fail / rate_limit | オンライン推測やDoSの兆候を調べる。正規利用者の入力ミスと区別し、アカウント列挙を招かない応答にする。 |
algorithm_distribution | Argon2id、bcryptなどの残存割合。古い形式をいつ廃止できるか計画する。 |
5-2. pepperを足す場合の失敗条件
pepperはDB-1と別の秘密保管基盤に置き、APP-1の限られた実行権限だけで使います。DBだけが流出した場合に追加の障壁になりますが、APP-1が同時に侵害されれば秘密が得られる可能性があります。Saltの代わりにpepperだけを使う設計は、全利用者で値が共通になるため不適切です。
pepperを失うと既存の照合値を検証できない方式が多いため、バックアップ、鍵ID、更新手順を決めます。漏えいしたpepperを新しい値へ変えるには、既存の平文パスワードが必要になる場合があります。次回ログイン時の再生成や全員のパスワード再設定が必要か、採用する構成で事前に確認します。
5-3. 移行時に弱い経路を残さない
bcryptからArgon2idへ段階移行する間、APP-1は保存レコードの方式を見て検証関数を選びます。攻撃者が方式フィールドを自由に書き換えられるなら弱い検証経路へ誘導される可能性があります。DB書込み権限、方式識別子の許可リスト、旧形式の利用期限を管理します。
ログイン成功時にArgon2idへ再ハッシュする場合でも、旧bcryptの72バイト制限で切り詰められていた入力をそのまま新しい方式へ登録すると、従来は同じ扱いだった長い入力が区別されます。移行前に旧実装の入力処理を調べ、必要なら安全な再設定フローへ誘導します。一般的なパスワードの長さは文字数とバイト数が違う点にも注意します。
5-4. 流出時の優先順位
DB漏えいが疑われたら、まず実際にどのテーブルとバックアップへアクセスされたかを保全します。次に保存方式、Saltの一意性、コスト設定、pepperの保管先、漏えい時刻を調べ、影響利用者を決めます。ハッシュが得られたと推定する場合、攻撃者のオフライン試行を止めることはできません。
利用者には再設定を求め、他サービスで同じパスワードを使っていた可能性を案内します。APP-1側ではセッションや再設定トークンの失効、MFAの状態、攻撃者のログイン成功履歴を確認します。復旧後は新しい方式で保存されていること、古いDBバックアップからの再漏えいを防げることを検証します。
6. 科目B(午後)の判断と演習
設問では、攻撃者が『ログイン画面だけ』を使えるのか『DBのハッシュとSalt』を持つのかを先に分けます。オンラインとオフラインでは有効な対策が違います。`salt_id`、`scheme`、`m/t/p`、`verify`を読んで、保存方式と照合結果を混同しないようにします。
演習1:同じパスワード
条件:アリスとボブが同じパスワードを使った。質問:適切なSaltなら保存値は同じか。解答:通常は異なる。誤答『同じ入力なら同じ値』は利用者ごとに異なるSaltを無視している。
演習2:Saltの保存
条件:DB-1にSaltとハッシュを並べて保存した。質問:Saltが公開されたので設計失敗か。解答:いいえ。Saltは秘密ではない。誤答はpepperとSaltの役割を混同している。
演習3:SHA-256一回
条件:各利用者に別Saltを付け、SHA-256を一回計算して保存。質問:十分か。解答:十分でない。推測一回の計算が速すぎる。誤答『Salt付きだから安全』はオフライン試行の速度を無視している。
演習4:bcryptの入力長
条件:既存bcrypt実装に長い日本語パスワードを入力する。質問:何を確認するか。解答:実装のバイト長上限と切詰めの有無。誤答『72文字までは安全』は72バイトと文字数を取り違えている。
演習5:旧方式からの移行
条件:bcrypt利用者をArgon2idへ移す。質問:DB中のbcrypt値から直接Argon2id値を作れるか。解答:元のパスワードを復元できないため、正しいログイン時に再ハッシュするか再設定する。誤答『ハッシュを再ハッシュ』は元入力が変わる。
演習6:DB流出後
条件:DB-1のSaltとハッシュが流出した。質問:ログイン試行回数制限だけでよいか。解答:よくない。オフライン推測には効かない。形式・コストを評価し、必要な再設定、セッション失効、再利用被害の対応を行う。
7. 一次資料
この記事についてAIに深掘り質問する
ChatGPT、Claude、Perplexityにこの記事を参照させ、要点の確認や疑問点を自由に質問できます。
次におすすめの学習
編集・検証について
編集・検証:IT資格ラボ編集部
IPAが公開する試験要綱・シラバス・過去問題と、各技術の公式資料を優先して内容を確認しています。制度変更や誤りを確認した場合は、記事を見直して更新します。
編集方針・情報源・訂正方針を見る