crypto/aes仅提供AES分组密码原语,需配合crypto/cipher的CBC/GCM等模式及正确IV/nonce/填充使用;密钥必须为16/24/32字节,IV须16字节且加解密一致,GCM优于CBC,IV/nonce/密钥严禁硬编码。

Go 标准库的 crypto/aes 本身只提供底层分组密码原语,不能直接加解密任意长度明文;必须搭配 crypto/cipher 中的模式(如 CBC、GCM)并手动处理填充/nonce/IV —— 否则运行时 panic 或解密乱码是常态。
crypto/aes.NewCipher 报 “invalid key size” 怎么办
这个错误只有一种原因:aes.NewCipher 接收的密钥字节长度不是 16、24 或 32。
- 传入
[]byte("1234567890123456")(16 字节)→ OK,对应 AES-128 - 传入
[]byte("mykey")(5 字节)→ panic - 别用
[]byte("password")直接当密钥:它只有 8 字节,且含可读字符,安全性极低 - 正确做法:用
sha256.Sum256([]byte(rawKey)).Sum(nil)[:32]固定截出 32 字节,或用crypto/rand.Read安全生成
CBC 模式下解密得到乱码或 panic
绝大多数情况不是算法写错,而是 IV 或填充没对齐。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
- 加密和解密必须用**完全相同的 IV**,且 IV 必须是 16 字节(AES 块大小)
- 密文结构应为
iv + ciphertext,解密前先切出前 16 字节作为 IV,剩余部分才是密文 - 必须补位:明文长度不是 16 倍数时,
cipher.NewCBCEncrypter.CryptBlocks会 panic;即使刚好 16 的倍数,也要补 16 字节\x10\x10…(PKCS#7 规则) - 解密后必须调用去填充函数,且校验末尾字节值是否在 1–16 范围内 —— 若是
\x00或 >16,说明密钥错、IV 错或密文被截断
该选 CBC 还是 GCM 模式
GCM 是现代首选,CBC 已不推荐用于新项目。
-
cipher.NewGCM返回的是AEAD接口,自动附带认证(防篡改),无需额外加 HMAC - GCM 的 nonce 长度建议设为 12 字节(Go 默认),用
crypto/rand.Read生成,和密文一起存/传 - 绝对禁止 nonce 复用:同一密钥下两次用相同 nonce,会导致密钥可被完全恢复
- CBC 没有完整性保护,攻击者翻转密文某字节,解密后只影响当前块和下一个块的对应字节 —— 看似无害,实则可能绕过鉴权逻辑
最易被忽略的一点:无论用哪种模式,IV/nonce 和密钥都绝不能硬编码在代码里,也不能从配置文件明文读取后直译成 []byte。它们必须通过环境变量注入,并在运行时用安全方式派生或解密加载 —— 否则整个加密形同虚设。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










