714 字
4 分钟
C# 开发实战:深入理解 MD5 加密与用户密码保护

在 Web 应用中,绝对不要以明文形式存储用户密码。MD5(消息摘要算法第 5 版)虽已被证明存在碰撞风险,但在处理非高度机密数据或结合“加盐(Salting)”技术的遗留系统中,它依然是开发者需要了解的基础算法。


一、核心概念:什么是 MD5?#

MD5 是一种哈希函数,而非真正意义上的”加密”。它具有以下核心特性:

  • 不可逆性:无法通过密文还原出原始明文。
  • 等长输出:无论明文多长,生成的哈希值长度固定(通常为 128 位)。
  • 抗碰撞性(弱):理论上不同的输入产生不同的输出(虽然现代算力已能人工制造碰撞)。

二、C# 实现:不同位数的 MD5 加密#

1. 标准 32 位 MD5 加密#

这是最常用的实现方式,生成一个 32 位的十六进制字符串。

public static string GetMD5_32(string input)
{
using (var md5 = MD5.Create())
{
byte[] inputBytes = Encoding.UTF8.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// 将字节数组转换为十六进制字符串
return Convert.ToHexString(hashBytes).ToLower();
}
}

2. 16 位 MD5 加密#

16 位加密实质上是取 32 位加密结果的第 9 位到第 24 位

public static string GetMD5_16(string input)
{
return GetMD5_32(input).Substring(8, 16);
}

3. 64 位 MD5 加密(Base64 格式)#

这种方式不返回十六进制,而是返回更短的 Base64 字符串。

public static string GetMD5_64(string input)
{
using (var md5 = MD5.Create())
{
byte[] data = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
return Convert.ToBase64String(data);
}
}

三、实战演练:用户登录验证流程#

由于 MD5 不可逆,验证登录的逻辑是:“对用户输入的密码进行相同的哈希运算,比对产生的哈希值是否与数据库一致”

public bool VerifyLogin(string userId, string inputPassword)
{
// 1. 从数据库获取用户信息(包含已存储的哈希密码)
var user = _db.Users.Find(userId);
if (user == null) return false;
// 2. 对输入的明文密码进行 64 位加密
string hashedInput = GetMD5_64(inputPassword);
// 3. 比对结果
return user.PasswordHash == hashedInput;
}

四、安全进阶:为什么要”加盐”?#

直接对密码进行 MD5 加密是不安全的,因为黑客可以使用**彩虹表(预先计算好的明文-密文映射表)**秒破简单密码。

解决方案:加盐 (Salt) 在密码末尾拼接一段随机字符串(盐),再进行哈希。

public static string GetSaltedMD5(string password, string salt)
{
// 即使密码是 123456,加上盐后产生的哈希值也会完全改变
return GetMD5_32(password + salt);
}

五、总结与现代建议#

  • MD5 的优势:速度极快,适合文件校验。
  • MD5 的劣势:不抗暴力破解,不抗碰撞攻击。
  • 现代开发建议:如果您正在开发新系统,请优先考虑 BCryptArgon2 算法,它们内置了加盐机制,且计算成本更高,能有效抵御大规模算力攻击。
C# 开发实战:深入理解 MD5 加密与用户密码保护
https://sw.rscclub.website/posts/csharpmd5jjm/
作者
杨月昌
发布于
2019-12-18
许可协议
CC BY-NC-SA 4.0