C# Tips | セキュリティ:パスワードを安全にHashする

C# C#
スポンサーリンク
スポンサーリンク

PBKDF2 の仕組みをやさしく理解する

PBKDF2 は「パスワードを安全に保存するための標準的な方法」です。 名前は難しそうですが、やっていることは次の 3 つだけです。

  1. ソルト(Salt)を混ぜる
  2. ハッシュを何千〜何万回も繰り返す(ストレッチング)
  3. 結果を保存する(元に戻せない)

この 3 つを組み合わせることで、攻撃者がパスワードを推測するのを極端に難しくします。

PBKDF2 は「パスワードをそのまま保存しないための変換装置」です。

  • パスワード
  • ソルト
  • 反復回数(iteration)
  • ハッシュ関数(HMAC-SHA256 など)

これらをまとめて「ぐるぐる計算」して、 元に戻せない長い文字列(ハッシュ値) を作ります。

PBKDF2 の 3 つの重要ポイントを深掘りする

① ソルト(Salt)を混ぜる

ソルトとは「ランダムな追加データ」です。

例: パスワード:MyPassword123 ソルト:XyZ9!@# → MyPassword123XyZ9!@# をハッシュ化する

なぜソルトが必要なのか?

  • 同じパスワードでも ソルトが違えばハッシュ値が変わる
  • 辞書攻撃(レインボーテーブル攻撃)を防げる
  • ユーザーごとに異なるソルトを使うことで安全性が跳ね上がる

② ストレッチング(反復回数)

PBKDF2 はハッシュ計算を 何千〜何万回も繰り返します。

例: 「HMAC-SHA256 を 100,000 回繰り返す」

なぜ繰り返すのか?

攻撃者は高速なコンピューターで総当たり攻撃をします。 そこで、計算を重くすることで攻撃を極端に難しくします。

  • ユーザーのログインでは 0.01 秒の遅延は問題ない
  • 攻撃者が 10 億回試すときは致命的な遅延になる

③ 元に戻せない(不可逆性)

PBKDF2 は「暗号化」ではなく「ハッシュ化」です。

  • 暗号化 → 鍵があれば元に戻せる
  • ハッシュ化 → 元に戻せない

パスワードは「戻す必要がない」ため、ハッシュ化が最適です。

PBKDF2 の仕組みをコードで理解する(C#)

実務で使える PBKDF2 ハッシュユーティリティ

(ソルト生成+PBKDF2+固定時間比較)

using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;

public static class Pbkdf2Utility
{
    public static (string Hash, string Salt) HashPassword(string password)
    {
        // ランダムソルト生成(128bit)
        byte[] salt = RandomNumberGenerator.GetBytes(128 / 8);

        // PBKDF2(HMACSHA256、10万回)
        string hash = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: salt,
            prf: KeyDerivationPrf.HMACSHA256,
            iterationCount: 100000,
            numBytesRequested: 256 / 8));

        return (hash, Convert.ToBase64String(salt));
    }

    public static bool VerifyPassword(string password, string storedHash, string storedSalt)
    {
        byte[] saltBytes = Convert.FromBase64String(storedSalt);

        string hash = Convert.ToBase64String(KeyDerivation.Pbkdf2(
            password: password,
            salt: saltBytes,
            prf: KeyDerivationPrf.HMACSHA256,
            iterationCount: 100000,
            numBytesRequested: 256 / 8));

        // 固定時間比較(タイミング攻撃対策)
        return CryptographicOperations.FixedTimeEquals(
            Convert.FromBase64String(storedHash),
            Convert.FromBase64String(hash));
    }
}
C#

PBKDF2 を使ったパスワード保存の流れ

登録時(Sign Up)

  1. ユーザーがパスワードを入力
  2. ソルトを生成
  3. PBKDF2 でハッシュ化
  4. ハッシュ値とソルトをデータベースに保存

保存するのはこの 2 つだけ:

保存するもの内容
HashPBKDF2 の結果
Saltランダム生成したソルト

ログイン時(Sign In)

  1. ユーザーがパスワードを入力
  2. データベースからソルトを取得
  3. PBKDF2 で同じ条件でハッシュ化
  4. 保存されているハッシュ値と一致するか比較
  5. 一致すればログイン成功

PBKDF2 の「危険な使い方」を知ることも重要です

以下は絶対にやってはいけません。

  • ソルトを使わない
  • 全ユーザーで同じソルトを使う
  • SHA-256 単体でハッシュ化する(高速すぎて危険)
  • 反復回数が少ない(1000 回などは危険)
  • ハッシュ値を平文でログに出す

PBKDF2 は「正しく使う」ことで初めて安全になります。

PBKDF2 をさらに深掘りしたい読者向け

もっと詳しく知りたい方は以下のテーマもおすすめです。

  • PBKDF2 の内部計算
  • bcrypt と PBKDF2 の違い
  • ソルトの生成方法
  • ストレッチングの回数の決め方

まとめ:PBKDF2 は「ソルト+ストレッチング+不可逆性」で攻撃を防ぐ仕組みです

PBKDF2 の本質は次の 3 つです。

  • ソルトで辞書攻撃を防ぐ
  • ストレッチングで総当たり攻撃を遅らせる
  • 不可逆ハッシュでパスワードを守る

これらを組み合わせることで、 攻撃者がパスワードを推測するのを極端に難しくします。

多くの読者のみなさんが業務システムを開発する際、 PBKDF2 を正しく使うだけでセキュリティレベルが大幅に向上し、 ユーザーの秘密を安全に守ることができます。

タイトルとURLをコピーしました