パスワードのハッシュ化が実際に守るもの
パスワードのハッシュ化は魔法ではありません。ユーザーテーブルが漏えいした日に備える、被害抑制の仕組みです。
目次
要点
パスワードをハッシュ化する目的は、パスワードデータベースが盗まれたときにユーザーを守ることです。
それが主な役割です。唯一の論点でも、セキュリティモデル全体でもありませんが、パスワードをそのまま保存せずにハッシュ化する中心的な理由です。
適切にハッシュ化されたパスワードは、逆算が困難です。攻撃者がユーザーテーブルのコピーを入手しても、Alice のパスワードが Spring2026! であるとすぐに分かるべきではありません。代わりに攻撃者が得るのは、推測を照合するために時間、費用、ハードウェアを要する保存済みハッシュです。
この違いは重要です。パスワードのハッシュ化は、それだけでログインを安全にするものではありません。フィッシングを止めるわけではありません。漏えいしたパスワードをログインフォームに試す攻撃を止めるわけでもありません。ログイン後のセッション Cookie を守るものでもありません。これは、非常に具体的な失敗、つまりパスワード検証情報の保存場所が露出した後に、時間を稼ぎ、被害を減らすためのものです。
この境界を理解していれば、アルゴリズム、ワークファクター、リセット、ログ、インシデント対応について、より良い判断ができます。
パスワードハッシュとは何か
パスワードハッシュとは、通常は一意のソルトと意図的に遅いパスワードハッシュ化アルゴリズムを使って、パスワードに一方向関数を適用した出力です。
ユーザーがアカウントを作成するとき、システムはおおむね次のように処理するべきです。
- HTTPS 経由でパスワードを受け取る。
- ランダムで一意のソルトを生成する。
- パスワードとソルトを、Argon2id、bcrypt、scrypt、PBKDF2 などのパスワードハッシュ化関数に通す。
- アルゴリズム名、パラメータ、ソルト、生成されたハッシュを保存する。
- 元のパスワードを破棄する。
後でユーザーがログインするとき、システムは送信されたパスワードと保存済みパラメータを使って同じハッシュ化処理を繰り返します。生成されたハッシュが保存済みハッシュと一致すれば、ログインは成功します。
重要なのは、アプリケーションが元のパスワードを知る必要がないという点です。送信されたパスワードが期待される結果を生成することだけを検証できれば十分です。
これが、可逆暗号化でパスワードを保存するモデルが通常は誤りである理由です。アプリケーションがすべてのパスワードを復号できるなら、復号鍵を盗んだ人も同じことができます。パスワードは通常、単に隠すのではなく、逆方向には検証できない形にしておくべきです。
ハッシュ化が守るもの
1. データベース侵害後の即時のパスワード露出
攻撃者が平文パスワードを含むデータベースを盗むと、被害は即時に発生します。すべてのパスワードが露出します。ユーザーはあなたのサイトだけでなく、そのパスワードを使い回しているあらゆる場所で危険にさらされます。
データベースに適切にハッシュ化されたパスワードが含まれている場合、攻撃者にはさらに作業が必要です。候補となるパスワードを推測し、各推測を正しいソルトとパラメータでハッシュ化し、その結果を比較しなければなりません。
弱いパスワードであれば、それでも短時間で済むことがあります。強く一意なパスワードであれば、現実的でない場合があります。
ハッシュ化は、壊滅的な露出を競争に変えます。攻撃者が多くのパスワードを解読する前に、ユーザーはパスワードをリセットできるか、そしてあなたはインシデントを封じ込められるか、という競争です。
完全ではありません。侵害であることに変わりはありません。しかし、失敗時の挙動としては大幅にましです。
2. ユーザー基盤全体に対する一括攻撃
ソルトはパスワード保存の重要な要素です。事前計算済みテーブルを使って多数のユーザーを効率的に攻撃することを防ぐためです。
ソルトは秘密ではありません。ハッシュと一緒に保存されます。その役割は一意性です。
2 人のユーザーが同じパスワードを選んでも、一意のソルトにより保存されるハッシュは異なります。これにより、多くのユーザーが同じパスワードを共有していることを攻撃者がひと目で見抜くのを防げます。また、パスワードからハッシュへの対応を大量に事前計算したリストを使う、古典的なレインボーテーブル攻撃も防ぎます。
ソルトがない場合、1 つのハッシュを解読するだけで、同じパスワードを持つすべてのユーザーが明らかになる可能性があります。ソルトがあれば、各パスワード推測はユーザーごとに個別に試す必要があります。
3. 高速なオフライン推測
攻撃者がパスワードデータベースを入手すると、オフラインで推測できます。つまり、ログインのレート制限、CAPTCHA、IP ブロック、監視はもはや効きません。攻撃者は自分のハードウェア上で推測を試せます。
ここでアルゴリズムの選択が重要になります。
SHA-256 や SHA-512 などの汎用ハッシュは、高速であるように設計されています。これはファイル完全性やデジタル署名には有用です。しかし、パスワード保存には不向きです。
パスワードハッシュ化アルゴリズムは、遅く、調整可能で、ときにはメモリハードであるように設計されています。Argon2id、bcrypt、scrypt、PBKDF2 はいずれもコストパラメータを調整でき、各推測に意味のある時間をかけさせることができます。
Argon2id は、CPU 時間とメモリの両方を要求するよう設定でき、大規模な GPU クラッキングのコストを高められるため、新しいシステムで広く推奨されています。bcrypt は、パスワード長の扱いなどの制限はあるものの、適切に設定されていれば今でも一般的で許容可能です。PBKDF2 は、特に FIPS 検証済みコンポーネントが必要な環境など、コンプライアンス主導の環境で今も使われています。
原則は単純です。正当なログインは許容できる速さに保ちつつ、何十億回もの推測を高くつくものにします。
ハッシュ化が守らないもの
1. フィッシング
ユーザーが偽のログインページにパスワードを入力した場合、あなたのサーバー上でのハッシュ化は役に立ちません。攻撃者は、あなたのシステムがそのパスワードを見る前に受け取っています。
ここでの防御策は別のものです。多要素認証、パスキー、ユーザー教育、ドメイン管理、フィッシング耐性のある認証、慎重なパスワードリセットフローなどです。
パスワードのハッシュ化は、保存された秘密情報に対する最後の支えです。ユーザーがだまされてその秘密情報を渡してしまうことへの防御ではありません。
2. クレデンシャルスタッフィング
クレデンシャルスタッフィングは、あるサービスから漏えいしたユーザー名とパスワードの組を攻撃者が取得し、別のサービスで試す攻撃です。
あなたのパスワードハッシュが優れていても、ユーザーがパスワードを使い回していれば、クレデンシャルスタッフィングは成功する可能性があります。
これはデータベースに対するオフライン攻撃ではなく、ログインフォームに対するオンライン攻撃です。レート制限、異常検知、漏えい済みパスワードのチェック、MFA、そして簡単なサービス拒否の機会を作らない適切なロックアウトポリシーが必要です。
同じ実践的な考え方は、公開されたあらゆるフォームに当てはまります。認証まわりを見直しているなら、問い合わせフォームが最大のスパム負債になる理由を読む価値があります。仕組みは異なりますが、教訓は似ています。公開入力には、きれいなバックエンドコードだけでなく、悪用対策が必要です。
3. ログや分析に記録されたパスワード
ハッシュ化が役に立つのは、平文パスワードがすぐに破棄され、他の場所にコピーされない場合だけです。
よくある失敗には次のようなものがあります。
- ログイン失敗時にリクエストボディ全体をログに記録する。
- パスワードをエラー監視ツールに送信する。
- セッションリプレイ製品でパスワードフィールドを取得する。
- 設計の悪いリセットや移行フローで、認証情報を URL に含める。
- インポート時に一時的な平文パスワードを保存する。
こうしたミスは、パスワードハッシュ化を完全に迂回します。平文がログ、バックアップ、データウェアハウス、第三者ツールに入ってしまえば、ハッシュ関数は無関係です。
パスワードフィールドは有害データとして扱ってください。ログに記録する前にマスクする。分析から除外する。URL に入れない。本番トレースにアクセスできる人を制限する。
4. 不適切なセッションセキュリティ
ログイン後、ユーザーのブラウザは通常、セッション Cookie またはトークンを受け取ります。そのトークンが盗まれた場合、攻撃者はそもそもパスワードを必要としないかもしれません。
パスワードのハッシュ化は、クロスサイトスクリプティング、安全でない Cookie、セッション固定、弱いトークン生成、長すぎるセッション有効期間からは守りません。
セッション Cookie はそれ自体として点検に値します。HttpOnly、Secure、適切な SameSite、高リスクセッションの短い有効期間、パスワード変更時のサーバー側無効化などです。プライバシーとブラウザをめぐる状況も変化し続けており、2026 年に Cookie で何が変わったかでも取り上げています。
5. 弱いパスワードリセットとアカウント回復
多くのアカウント乗っ取りは、パスワードから始まるわけではありません。リセットフローから始まります。
リセットトークンが予測可能であったり、長期間有効であったり、リファラーヘッダー経由で漏えいしたり、侵害されたメールアカウントに送られたりする場合、パスワードハッシュ化は救いになりません。
高エントロピーのリセットトークン、短い有効期限、1 回限りの使用、明確なユーザー通知を使ってください。メールは多くの場合、回復チャネルであるため、基本的なドメイン認証も重要です。チームが DNS レコードを不可解な儀式のように扱っているなら、MX、SPF、DKIM、DMARC の開発者向けガイドから始めるとよいでしょう。
アルゴリズム選択: 今何を使うべきか
新しいアプリケーションでは、プラットフォームが十分にサポートしているなら Argon2id を使ってください。これは Password Hashing Competition の勝者であり、GPU を多用するクラッキングへの耐性を含め、パスワード保存向けに設計されています。
現代的な優先順位は、おおむね次のようになります。
- 利用できる新しいシステムでは Argon2id。
- Argon2id が現実的でなく、bcrypt のサポートが成熟している場合は bcrypt。
- メモリハードな設定が十分にサポートされている場合は scrypt。
- プラットフォームまたはコンプライアンス上の制約で必要な場合は PBKDF2。
素の SHA-256、SHA-512、MD5、または sha256(password + salt) のような自作の組み合わせは避けてください。高速なハッシュはパスワード保存関数ではありません。気の利いた独自構成は、退屈な標準方式より悪くなりがちです。
また、アルゴリズムの細かな知識に基づいて独自のパスワードポリシーを作ることも避けてください。予測可能なパターンにユーザーを追い込むなら、12 個のルールからなるパスワード構成チェックリストはユーザーの利益になりません。長く一意なパスワード、パスワードマネージャー、漏えい済みパスワードのスクリーニング、MFA の方が、たいてい重要です。
コストファクターは設定して終わりではない
パスワードハッシュ化にはパラメータがあります。Argon2id にはメモリ、反復回数、並列度があります。bcrypt にはコストファクターがあります。PBKDF2 には反復回数があります。
これらの値は、本番環境に基づいて選ぶべきです。低すぎると、攻撃者は安価に推測できます。高すぎると、ログインシステムが遅くなったり、サービス拒否に弱くなったりします。
実用的な目標は、実際のサーバー上でパスワード検証 1 回あたり数十ミリ秒から数百ミリ秒程度の範囲であることが多く、トラフィックとリスクによって変わります。高セキュリティのシステムでは、より大きな値を選ぶかもしれません。消費者向け大規模システムでは、慎重なキャパシティプランニングが必要になる場合があります。
5 年前のブログ記事からコストファクターをコピーしないでください。ハードウェアは変わります。ライブラリも変わります。トラフィックも変わります。
パラメータを定期的に見直し、再ハッシュ化を計画してください。一般的なパターンは、各ハッシュと一緒にアルゴリズムとパラメータを保存することです。ログインが成功したとき、保存されているパラメータが古ければ、送信されたパスワードを新しい設定で再ハッシュ化し、レコードを更新します。
ペッパー: 有用だが代替ではない
ペッパーは、パスワードハッシュ化処理に追加される秘密値であり、データベースとは別に、しばしばシークレットマネージャーやハードウェアセキュリティモジュールに保存されます。
ソルトと違い、ペッパーは秘密でなければなりません。
ペッパーは、データベースは漏えいしたがアプリケーションの秘密情報は漏えいしていない場合に、被害を減らせます。適切な鍵管理を備えた成熟した環境で最も有用です。同じ攻撃者がデータベースとアプリケーション設定の両方を盗める場合、有用性は下がります。
ペッパーを使うなら、ローテーションを慎重に計画してください。設計によっては、ローテーション時にユーザーの再ログインやパスワードリセットが必要になる場合があります。ペッパーは追加の層であり、基礎となるハッシュ設定を弱める理由ではありません。
運用チェックリスト
実際のシステムに責任を持つなら、実用的なチェックリストは短いものです。
- パスワードは標準的なパスワードハッシュ化アルゴリズムでのみ保存する。
- パスワードごとに一意のランダムソルトを使う。
- 新規構築では Argon2id を優先する。
- 本番に近いハードウェア上でコストパラメータを調整する。
- 各ハッシュと一緒にアルゴリズムとパラメータを保存する。
- パラメータが古くなったら、ログイン時に再ハッシュ化する。
- パスワードをログに記録したり、分析ツールに送信したりしない。
- 認証情報が送信される場所では常に TLS を使う。
- リスクに応じて MFA またはパスキーを追加する。
- リセットフローをログインフローと同じくらい真剣に保護する。
- 強制リセットとユーザー通知のためのインシデント計画を持つ。
パスワードハッシュ化は華やかではありません。配管のようなものです。しかし、侵害がつらいインシデントで済むか、全ユーザー規模の災害になるかを左右する種類の配管です。
<!-- tool-cta:start -->
💡 お試しください: Hash Generatorで、同じ入力が異なるアルゴリズムにどのように対応するかを確認し、高速なハッシュとパスワードグレードのハッシュの違いを具体的に理解できます。
<!-- tool-cta:end -->
正直なメンタルモデル
パスワードハッシュ化について考える最もよい方法は、次のとおりです。
ハッシュ化は、ユーザーがパスワードを入力している間のパスワードを守りません。ユーザーがログインした後のアカウントを守りません。Web 全体でパスワードを使い回すユーザーを守りません。
保存された検証情報を守ります。
これは狭く聞こえますが、非常に重要です。データベースは漏えいします。バックアップも漏えいします。ステージング環境はコピーされます。ベンダーが持つべきでないアクセス権を得ることがあります。古いエクスポートが、誰も覚えていないほど長くオブジェクトストレージに残ります。
そのとき、パスワード保存の設計は、攻撃者がパスワードを受け取るのか、それとも高くつく推測問題を受け取るのかの違いになります。
それこそが、パスワードのハッシュ化が実際に守るものです。