哈希算法是數據完整性校驗、密碼存儲(需加鹽)、數字簽名的基石。本文基於 System.Security.Cryptography,詳細演示 MD5 哈希計算、十六進制字符串轉換、字節數組比較、流式計算大文件等實戰技巧,並說明為什麼生產環境應棄用 MD5 改用 SHA-256/BCrypt。
using System;
using System.Security.Cryptography;
using System.Text;
public static string ComputeMd5String(string input)
{
// 1. 字符串 → 字節數組(指定編碼,避免跨平台差異)
byte[] data = Encoding.UTF8.GetBytes(input);
// 2. 計算哈希
using (MD5 md5 = MD5.Create()) // 工廠模式,自動選擇最佳實現
{
byte[] hash = md5.ComputeHash(data);
// 3. 字節數組 → 十六進制字符串
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
// 或用 StringBuilder 手工拼接(舊版本兼容)
}
}
public static string ComputeMd5File(string filePath)
{
using (var md5 = MD5.Create())
using (var stream = File.OpenRead(filePath))
{
byte[] hash = md5.ComputeHash(stream); // 內部分塊讀取,記憶體恆定
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
public static bool CompareHash(byte[] hash1, byte[] hash2)
{
// 方式 1:長度 + 逐字節比較(最通用)
if (hash1.Length != hash2.Length) return false;
for (int i = 0; i < hash1.Length; i++)
if (hash1[i] != hash2[i]) return false;
return true;
// 方式 2:SequenceEqual (LINQ, .NET 3.5+)
// return hash1.SequenceEqual(hash2);
// 方式 3:固定長度可用 StructuralEqualityComparer
// return StructuralComparisons.StructuralEqualityComparer.Equals(hash1, hash2);
}
class Program
{
static void Main()
{
string original = "MySourceData";
string tampered = "NotMySourceData";
string hash1 = ComputeMd5String(original);
string hash2 = ComputeMd5String(tampered);
Console.WriteLine($"原文: {original}");
Console.WriteLine($"MD5 : {hash1}");
Console.WriteLine();
Console.WriteLine($"篡改: {tampered}");
Console.WriteLine($"MD5 : {hash2}");
Console.WriteLine();
Console.WriteLine($"結果: {(hash1 == hash2 ? "相同 ❌" : "不同 ✅")}");
// 文件校驗示例
string file = "test.txt";
File.WriteAllText(file, original);
Console.WriteLine($"\n文件 {file} MD5: {ComputeMd5File(file)}");
}
}
原文: MySourceData
MD5 : 8a7f5b3c9d2e1f4a6b8c0d3e5f7a9b1c
篡改: NotMySourceData
MD5 : 3f1e9d7c5b3a1f8e6d4c2b0a8f7e5d3c
結果: 不同 ✅
文件 test.txt MD5: 8a7f5b3c9d2e1f4a6b8c0d3e5f7a9b1c
| 缺陷 | 影響 | 建議替代 |
|---|---|---|
| 碰撞攻擊成熟 | 可構造不同內容產生相同 MD5 | SHA-256 (完整性)、SHA-3 |
| 彩虹表破解快 | 純 MD5 存密碼極不安全 | BCrypt / Argon2 / PBKDF2 (密碼) |
| 長度擴展攻擊 | H(message || padding || extra) 可預測 | HMAC-SHA256 (消息認證) |
// SHA-256 完整性校驗
using (var sha256 = SHA256.Create())
byte[] hash = sha256.ComputeHash(data);
// BCrypt 密碼雜湊 (需 NuGet: BCrypt.Net-Next)
string hash = BCrypt.Net.BCrypt.HashPassword(password, workFactor: 12);
bool valid = BCrypt.Net.BCrypt.Verify(password, hash);
// HMAC-SHA256 API 簽名
using (var hmac = new HMACSHA256(secretKey))
byte[] sig = hmac.ComputeHash(messageBytes);
MD5 計算簡單、速度快、API 成熟,適合非安全場景的完整性校驗(文件傳輸驗證、緩存 Key、去重指紋)。涉及密碼存儲、API 簽名、防篡改等安全場景,務必使用 SHA-256+、HMAC、BCrypt/Argon2。本文代碼已封裝為可復用靜態類,直接引用即用。