go中md5.sum和sha256.sum返回结构体,需用.sum(nil)[:]转字节切片再hex编码;大文件须流式计算;hmac非加密仅校验;md5禁用于安全场景。

Go 里 md5.Sum 和 sha256.Sum 返回的不是字符串,别直接打印
很多人写完 md5.Sum([]byte("hello")) 就用 fmt.Println 打印,结果看到一串类似 {[10 20 ...]} 的字节切片输出,误以为“没算对”。其实 Sum 类型是结构体,[md5.Size]byte 字段才是真正的哈希值,得显式转成十六进制字符串。
- 正确做法是调用
.Sum(nil)[:]拿到字节数组,再用fmt.Sprintf("%x", bytes)或hex.EncodeToString() -
md5.Sum的底层是固定长度数组([16]byte),不能直接当[]byte传给需要切片的地方,必须加切片操作符[:] - 如果只是想快速验证,优先用
md5.Sum(nil).Sum(nil)[:]配合hex.EncodeToString,比手写循环更安全
用 crypto/md5 和 crypto/sha256 计算大文件哈希时,别一次性读进内存
直接 md5.Sum(os.ReadFile("big.log")) 看似简洁,但遇到几百 MB 的日志或二进制文件,会触发 OOM。Go 的哈希接口设计本意就是流式处理——所有 hash.Hash 实现都支持 Write,可以边读边算。
- 打开文件后,用
io.Copy(hash, file)最省心,自动分块、不占额外内存 - 手动控制时,用
bufio.NewReader+hash.Write(buf.Bytes()),注意每次Read后检查返回的n,别漏掉最后一块 -
sha256.New()比md5.New()多约 20% CPU 开销,但对现代机器几乎无感;真正影响性能的是 I/O,不是算法本身
crypto/hmac 不是“加密”,而是带密钥的哈希,别和 AES 混用场景
有人看到 hmac 就以为能替代加密,结果把敏感字段用 HMAC-SHA256 “保护”后存数据库,其实这只是完整性校验,无法防泄露。HMAC 输出仍是可公开的摘要,密钥一旦泄露,攻击者能伪造任意合法签名。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- HMAC 的典型用途是 API 签名(如 AWS v4)、Webhook 校验、防止参数篡改,不是数据保密
- 生成时密钥必须是
[]byte,别用字符串直接传——Go 不会自动编码,中文或特殊字符会导致结果不一致 - 密钥长度建议 ≥ 哈希输出长度(如 SHA256 密钥至少 32 字节),太短会削弱安全性;可用
crypto/rand.Read安全生成
MD5 在 Go 里还没被禁用,但别用在安全场景,连 crypto/md5 的 import 都该加注释说明原因
Go 标准库仍保留 crypto/md5,编译完全没问题,甚至 go.sum 里还常见它的哈希值。但这不代表它能用于密码存储、数字签名或防碰撞场景——已知可在秒级构造 MD5 碰撞。
- 内部系统做缓存 key 或临时校验,用 MD5 问题不大;对外接口、用户密码、JWT 签名等,必须换
sha256或sha512 - Go 1.22+ 对
crypto/md5加了// Deprecated: Weak cryptographic primitive.注释,静态扫描工具(如gosec)会报 warn - 如果 legacy 协议强制要求 MD5(比如某些老硬件通信),至少确保输入不可控的部分(如用户上传文件名)先经 SHA256 处理再喂给 MD5,避免直接拼接
哈希和 HMAC 的边界、流式计算的惯用法、以及 MD5 的实际存活位置,这几个点卡住的人最多。写的时候多看两眼 hash.Hash 接口定义,比查文档更快定位问题。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










