- パスワードの安全なハッシュ化は「ユーザーの秘密を守るための最重要セキュリティ基盤です」
- ハッシュ化とは何か?不可逆変換でパスワードを守る技術です
- 暗号化とハッシュ化の違いを理解することが重要です
- ソルト(Salt)とは?辞書攻撃を防ぐための“塩”です
- ストレッチング(Stretching)とは?計算をわざと重くして攻撃を防ぐ技術です
- C# で安全にパスワードをハッシュ化する方法(PBKDF2)
- 実務で使える「安全なパスワードハッシュユーティリティ」テンプレート
- bcrypt / Argon2 を使う選択肢もあります(より強力)
- パスワードハッシュ化で絶対にやってはいけないこと
- まとめ:安全なパスワードハッシュは「ソルト+ストレッチング+不可逆性」が必須です
パスワードの安全なハッシュ化は「ユーザーの秘密を守るための最重要セキュリティ基盤です」
パスワードを安全に扱うことは、業務システムにおけるセキュリティの最重要ポイントです。 初心者の方でも誤解しやすいのですが、パスワードをそのまま保存する(平文保存)ことは絶対にしてはいけません。 万が一データベースが漏洩した場合、すべてのユーザーのパスワードが攻撃者に丸見えになってしまいます。
そのため、パスワードは必ず ハッシュ化(不可逆変換)+ソルト(Salt)+ストレッチング(Stretching) を組み合わせて安全に保存します。 ここでは、初心者にも分かりやすいように、仕組み・実務で使えるコード例・テンプレートを丁寧に解説します。
ハッシュ化とは何か?不可逆変換でパスワードを守る技術です
ハッシュ化は「元に戻せない変換」です
ハッシュ化とは、パスワードを特殊な計算式で「まったく別の文字列」に変換する技術です。 最大の特徴は 元に戻せない(不可逆性) ことです。
例: password123 → a58f9c2d...(元に戻せない)
これにより、データベースが漏洩しても攻撃者は元のパスワードを知ることができません。
暗号化とハッシュ化の違いを理解することが重要です
暗号化は「鍵があれば戻せる」、ハッシュ化は「戻せない」
- 暗号化(Encryption) → 鍵があれば元に戻せる(復号できる)
- ハッシュ化(Hashing) → 元に戻せない(不可逆)
パスワードは「戻す必要がない」ため、ハッシュ化が適しています。
ソルト(Salt)とは?辞書攻撃を防ぐための“塩”です
同じパスワードでも異なるハッシュ値にする仕組みです
ハッシュ化には弱点があり、同じ文字列は必ず同じハッシュになります。 攻撃者は「よく使われるパスワードのハッシュ一覧(レインボーテーブル)」を持っているため、照合されると簡単に突破されます。
そこで ソルト(Salt) を使います。
例: パスワード:mysecret ソルト:xyz987 → mysecretxyz987 をハッシュ化する
ユーザーごとに異なるソルトを使うことで、同じパスワードでもハッシュ値が変わり、辞書攻撃が無効化されます。
ストレッチング(Stretching)とは?計算をわざと重くして攻撃を防ぐ技術です
ハッシュ計算を数千〜数万回繰り返して攻撃を困難にします
コンピューターは高速なので、ハッシュ化を何億回も試す総当たり攻撃が可能です。 そこで、ハッシュ計算を 何千回・何万回も繰り返す(ストレッチング) ことで攻撃を困難にします。
ユーザーのログインでは数ミリ秒〜数秒の遅延は問題ありませんが、攻撃者にとっては膨大な計算量になります。
C# で安全にパスワードをハッシュ化する方法(PBKDF2)
PBKDF2 は .NET 標準で使える安全なハッシュ方式です
C# では、PBKDF2(RFC 2898)を使って安全にパスワードをハッシュ化できます。 Microsoft 公式ドキュメントでも PBKDF2 の利用例が紹介されています。
実務で使える「安全なパスワードハッシュユーティリティ」テンプレート
ソルト生成+PBKDF2+Base64 で保存する実務向けテンプレートです
using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
public static class PasswordHashUtility
{
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#使い方:
var (hash, salt) = PasswordHashUtility.HashPassword("MyPassword123");
bool ok = PasswordHashUtility.VerifyPassword("MyPassword123", hash, salt);
Console.WriteLine(ok); // true
C#ここでの重要ポイントは:
- ソルトは毎回ランダム生成する
- ハッシュ値とソルトは両方データベースに保存する
- 固定時間比較でタイミング攻撃を防ぐ
- PBKDF2 の反復回数は 100,000 回以上が推奨される(2026 年時点)
bcrypt / Argon2 を使う選択肢もあります(より強力)
bcrypt や Argon2 はパスワード専用に設計された強力なハッシュ方式です
.NET では PBKDF2 が標準ですが、 外部ライブラリを使えば bcrypt や Argon2 も利用できます。
これらは「計算を重くする」ことに特化しており、総当たり攻撃に強いです。
パスワードハッシュ化で絶対にやってはいけないこと
以下はすべて危険です。
- 平文で保存する
- reversible encryption(復号できる暗号化)で保存する
- SHA-256 単体でハッシュ化する(高速すぎて危険)
- ソルトを使わない
- 全ユーザーで同じソルトを使う
これらは攻撃者にとって突破しやすく、実務では絶対に避けるべきです。
まとめ:安全なパスワードハッシュは「ソルト+ストレッチング+不可逆性」が必須です
パスワードハッシュ化の本質は、
- 元に戻せないハッシュ化(不可逆性)
- ユーザーごとのランダムソルト
- 計算を重くするストレッチング(PBKDF2 / bcrypt / Argon2)
- 固定時間比較でタイミング攻撃対策
を組み合わせて、攻撃者が突破できないようにすることです。
多くの購読者のみなさんが業務システムを開発する際、 この「安全なパスワードハッシュユーティリティ」を導入するだけで、 セキュリティレベルが大幅に向上し、 データ漏洩時の被害を最小限に抑えることができます。

