
用 MD5.Create() 而不是 new MD5CryptoServiceProvider()
在 .NET Core 2.0+ 和 .NET 5+ 中,MD5CryptoServiceProvider 已标记为过时,直接 new 它会触发编译警告,且在某些 AOT 或受限运行时可能失败。官方推荐统一用工厂方法 MD5.Create() —— 它返回的实例行为一致,还能适配不同平台的底层实现。
常见错误现象:CS0618 ‘MD5CryptoServiceProvider’ is obsolete;或在 .NET 6+ Blazor WebAssembly 里抛出 PlatformNotSupportedException。
始终写 using var md5 = MD5.Create();,别手动 new它返回的是 HashAlgorithm 抽象类型,后续调用 ComputeHash() 方式不变如果项目还支持 .NET Framework 4.x,这个写法也完全兼容
字符串要先转成字节数组,编码必须显式指定
MD5 作用对象是字节流,不是字符串。不指定编码直接调用 Encoding.UTF8.GetBytes() 是常规做法,但容易忽略:中文、emoji 或旧系统数据可能用 GBK 或 ISO-8859-1,编码错一个字节,哈希值就全错。
使用场景:处理用户输入、读取配置文件、对接老接口时,务必确认源数据原始编码。
默认用 Encoding.UTF8,99% 场景够用若对接 Java 或 PHP 的 legacy 系统,对方用 new String(byte[], "GBK"),你也得用 Encoding.GetEncoding("GBK")别用 Encoding.Default——它随系统区域设置变,本地跑通,服务器可能崩
结果是字节数组,转十六进制字符串时别漏了格式化
ComputeHash() 返回 byte[],直接 ToString() 得到的是 System.Byte[] 字符串,不是哈希值。必须逐字节转两位十六进制,且要小写、无分隔符,才符合标准 MD5 表示(如 5eb63bbbe01eeed093cb22bb8f5acdc3)。
性能影响:用 string.Concat(bytes.Select(b => b.ToString("x2"))) 看似简洁,但 LINQ + 委托调用有额外开销;高频调用建议用 Span<char> 或预分配 char[32]。
最简安全写法:BitConverter.ToString(md5.ComputeHash(data)).Replace("-", "").ToLowerInvariant()想极致性能(比如日志脱敏批量计算),用 Convert.ToHexString()(.NET 5+)别写 b.ToString("X2")——大写不符合多数服务端约定,有些 API 校验严格区分大小写
MD5 不适合密码存储,但校验文件或签名仍可用
MD5 碰撞已被实证攻破,不能用于密码哈希(应选 Argon2、BCrypt 或至少 Rfc2898DeriveBytes)。但它对非密码类完整性校验依然有效:比如比对上传前后文件是否一致、生成资源缓存 key、轻量级接口签名。
容易踩的坑:把 MD5 当密码 hash 存数据库,被拖库后秒破;或在支付回调里用 MD5 做签名,却没加盐、没验时间戳,导致重放攻击。
仅用于校验场景时,确保输入不可控部分(如用户提交内容)已做归一化(trim、统一换行符等)接口签名务必拼接 secret key,且 key 不参与 URL 传输别在新系统中设计依赖 MD5 安全性的逻辑——哪怕只是“防误操作”,也建议升到 SHA256
真正麻烦的从来不是怎么算出那 32 位字符串,而是谁在什么时候、用什么编码、往哪塞了什么数据——这些细节一错,两边哈希对不上,排查起来比重写还累。

评论(0)