go中aes加密需严格校验密钥字节长度(16/24/32)、nonce与aad一致性及iv/nonce传输方式,否则解密必报crypto/cipher: message authentication failed。

Go 里 AES 加密不是“调个函数就行”,密钥长度错一位、nonce 混进密文、string 转 []byte 时隐式截断——任何一个都会让 Open 返回 crypto/cipher: message authentication failed,且几乎不提示具体哪出错了。
密钥长度必须严格为 16/24/32 字节,len([]byte(key)) 才是真实长度
Go 的 aes.NewCipher 对密钥字节长度零容忍:15 或 33 字节直接 panic。常见错误是拿字符串字面量当密钥,比如 "mysecret"(8 字节)或 "this-is-32-chars-but-has-emoji-✅"(len(key) 是 rune 数,len([]byte(key)) 才是字节数,含 emoji 就超了)。
- 别用
[]byte("key")硬编码——中间有\x00会被 C 风格截断 - 从配置读 key 时,务必检查
len([]byte(key)),不是len(key) - 安全补长推荐用
sha256.Sum256([]byte(passphrase)).[0:32],别用strings.Repeat补空格
AEAD 模式(如 GCM)下,nonce 和 additionalData 必须和加密时完全一致
解密失败报 message authentication failed,90% 是因为 nonce 不匹配——它不是 IV,不能每次随机生成后丢弃;它必须和密文一起传输,且解密时原样传入 Open。
在 Go 中使用 google/wire 实现编译时依赖注入——wire.NewSet、wire.Build、wire.Bind(接口→实现)、wire.Struct、wire.Value、wire.Interface
-
nonce长度由 AEAD 实现定:GCM推荐 12 字节,不是 8 或 16;ChaCha20-Poly1305要 24 字节 - 网络传输时,把
nonce单独发(比如前 12 字节),再发Seal返回的密文(不含nonce),避免边界混淆 -
additionalData(AAD)如果加密时用了,解密时必须传相同内容,哪怕为空切片[]byte{}也不可省略
CBC 模式要手动 PKCS7 填充,且 IV 必须随密文一起保存
CBC 不自带认证,没填充会 panic,IV 丢了就彻底解不开。标准库不提供自动填充,得自己写 pkcs7Pad 和 pkcs7UnPad。
- 填充必须在加密前做,解密后立即去填充;顺序错一步,解出来就是乱码
- IV 长度固定为
aes.BlockSize(16 字节),必须和密文拼在一起传输(比如ciphertext = append(iv, encrypted...)) - 别用 ECB 模式——它不安全,标准库甚至不鼓励用,
aes.NewCipher只给块,没封装 ECB 加密逻辑
所有操作基于 []byte,字符串转换极易丢数据
人输的是 "hello",但密钥可能是从文件读的二进制、base64 解码的、或 hex.DecodeString 来的——这些都不是 UTF-8 安全的 string。
- 明文是字符串?先
[]byte(plaintext),但确认它不含非法 UTF-8;否则直接读[]byte流 - 密钥来自 base64?用
base64.StdEncoding.DecodeString(keyB64),别用[]byte(keyB64) - 打印调试时用
fmt.Printf("%x", data)或base64.StdEncoding.EncodeToString(data),别直接string(data)
最常被跳过的细节:GCM 的 nonce 重用等于自毁,CBC 的 IV 绝对不能复用,密钥字节长度检查必须在 aes.NewCipher 之前做——这三件事没做对,后面全是白忙。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










