go中md5.sum和sha256.sum返回值类型而非字符串,需用fmt.sprintf("%x", sum)或hex.encodetostring(sum[:])转为十六进制;密码存储禁用md5/sha256,应使用bcrypt等慢哈希;aes与chacha20选型取决于硬件支持与场景。

Go 里 md5.Sum 和 sha256.Sum 返回的是值类型,别直接当字符串用
很多人调 md5.Sum([]byte("hello")) 后想直接 fmt.Println(sum) 或拼接进日志,结果看到一串看不懂的结构体输出,比如 {[...]} 。这是因为 Sum 返回的是一个带数组字段的结构体(如 [16]byte 或 [32]byte),不是字符串。
- 正确做法是显式转成十六进制字符串:
fmt.Sprintf("%x", sum)或用hex.EncodeToString(sum[:]) - 注意
sum[:]是切片转换,sum本身不能直接传给hex.EncodeToString - 如果只想要摘要字节,用
sum.Sum(nil)—— 它返回[]byte,但会额外分配内存;而sum本身是栈上值,更轻量 -
sha256.Sum的底层数组是[32]byte,比md5.Sum的[16]byte占更多栈空间,高频调用时留意逃逸分析
AES 加密必须手动处理 IV 和 padding,Go 标准库不自动补位
用 cipher.NewCBCEncrypter 或 cipher.NewGCM 时,常见错误是传入固定 IV(比如全零)、或对明文不做 PKCS#7 填充就直接加密,导致解密失败或 panic。
- IV 必须随机且每次加密不同,推荐用
crypto/rand.Read(iv)生成;GCM 模式下 IV(nonce)还要求不能重复,否则完全丧失安全性 - CBC 模式需要明文长度是块大小(16 字节)整数倍,
crypto/cipher不提供填充函数,得自己实现 PKCS#7:末尾补n个字节,值都为n - GCM 更推荐:它自带认证,不用手动 padding,但要注意
Seal返回的字节包含 nonce + ciphertext + auth tag,解密前得先拆出来 - 别把 key 当字符串硬编码——
"my-key-123"是 11 字节,AES-256 要求 32 字节 key,直接用会 panic:"invalid key size"
crypto/aes 和 golang.org/x/crypto/chacha20poly1305 性能与场景差异明显
选 AES 还是 ChaCha20?不是看名字新旧,而是看部署环境和数据量。
- AES 在有硬件加速(AES-NI)的 x86 CPU 上极快,但在 ARM 或老设备上可能慢 3–5 倍;ChaCha20 是纯软件算法,各平台性能更稳定
- HTTP/2 和 TLS 1.3 默认优先 ChaCha20-Poly1305,尤其在移动端;如果你做 IoT 设备通信或 WebAssembly 环境,ChaCha20 更稳妥
-
chacha20poly1305.XORKeyStream支持流式加解密,适合大文件边读边加,而 AES-GCM 的Seal/Open是全量操作 - 注意 ChaCha20 的 nonce 长度是 12 字节(不是 AES-GCM 的常用 12),传错长度会 panic:"
invalid nonce length"
MD5 和 SHA256 绝对不能用于密码存储,哪怕加盐也不行
看到项目里还有人用 md5.Sum(password+salt) 存用户密码,这等于没设防。标准库的哈希函数设计目标是快,而密码哈希必须“故意慢”。
立即学习“go语言免费学习笔记(深入)”;
- Go 官方推荐用
golang.org/x/crypto/bcrypt或scrypt;bcrypt.GenerateFromPassword内置 salt 且可调 cost 参数 - SHA256 可用于 HMAC 或数字签名场景(如 JWT 签名),但绝不用于密码;它的抗碰撞性再强,也挡不住 GPU 暴力跑字典
- 如果必须兼容旧系统(比如校验第三方传来的 MD5 摘要),仅限验证,且要确认该摘要来源可信、传输过程受 TLS 保护
- 别自己拼接 salt:
sha256.Sum([]byte(salt + password))有长度扩展攻击风险;用hmac.New更安全










