MD5不可用于安全场景,仅适用于非安全用途;md5.Sum不是字符串,需用Sum(nil)配合hex.EncodeToString转换;流式计算用md5.New(),一次性计算用md5.Sum();复用hasher必须Reset(),否则结果累积。

Go 标准库的 crypto/md5 仍可用,但**不应用于安全敏感场景(如密码、签名、防篡改校验)**——MD5 已被证实存在碰撞漏洞,RFC 6151 明确弃用。它只适合遗留协议兼容、非安全哈希(如简单文件指纹、缓存 key)等低风险用途。
为什么不能用 md5.Sum 直接当字符串用?
md5.Sum 是一个带 [16]byte 底层数组的结构体,不是字符串;直接打印会输出 Go 的结构体格式(如 {[0 0 0 ...]}),不是你想要的十六进制摘要。
- 正确做法是调用
sum.Sum(nil)得到[]byte,再用fmt.Sprintf("%x", ...)或hex.EncodeToString(...) - 更推荐用
sum.Sum(nil)+hex.EncodeToString:避免 fmt 包的反射开销,且明确控制编码逻辑 - 错误示例:
fmt.Println(md5.Sum(data))→ 输出不可读结构体;string(sum[:])→ 得到乱码二进制字节,不是 hex 字符串
md5.New() 和 md5.Sum() 两种写法怎么选?
本质是流式计算 vs 一次性计算,取决于输入数据形态:
- 用
md5.New():适合大文件、网络流、需要分块写入的场景(如边读文件边哈希)
→ 调用io.Copy(hash, file)或反复hash.Write([]byte),最后hash.Sum(nil) - 用
md5.Sum():适合小数据、内存中已有的[]byte或string
→md5.Sum([]byte("hello"))返回结构体,再取.Sum(nil) - 注意:
md5.Sum内部仍会新建 hasher 并重置状态,性能略低于复用md5.New()实例(尤其高频调用时)
常见错误:忘记重置 hasher 导致哈希值叠加
如果复用同一个 hash.Hash 实例多次计算,必须在每次前调用 hash.Reset(),否则结果是“上次结果 + 本次输入”的累积哈希,不是独立摘要。
立即学习“go语言免费学习笔记(深入)”;
- 错误写法:
h := md5.New() h.Write([]byte("a")) fmt.Printf("%x\n", h.Sum(nil)) // a 的 hash h.Write([]byte("b")) // 没 Reset!这是 "a"+"b" 的 hash,不是 "b" 的 fmt.Printf("%x\n", h.Sum(nil)) - 正确写法:每次
h.Reset()后再Write,或每次新建md5.New() - 更安全的习惯:短生命周期内创建新 hasher,而非全局复用——除非你明确控制重置时机
真正麻烦的地方在于:MD5 的“够用”边界很模糊。比如用它生成缓存 key 看似无害,但如果 key 来源可控(如用户上传文件名拼接),攻击者可能构造碰撞输入使不同内容映射到同一 key,引发缓存污染。这种细节往往在压测或上线后才暴露。










