密钥长度必须为16、24或32字节,否则aes.NewCipher直接panic;CBC需校验IV和PKCS#7填充;GCM严禁nonce重用且tag必须显式分离;ECB绝对禁用。
aes.NewCipher 不会宽容——传入 15 或 17 字节的密钥,它立刻抛出 crypto/aes: invalid key size。Go 不做截断、不补零、不提示“建议用 16”,只认死理:len(key) 必须是 16、24 或 32。
[]byte("1234567890123456")(注意:无空格、无换行、无 BOM)len(key) 检查字符串长度;要用 len([]byte(key)),否则含中文或 emoji 会误判sha256.Sum256([]byte(raw)).[0:32] 得到稳定 32 字节密钥,避免人为数错CBC 解密失败几乎从不报错,只会输出乱码。问题大概率出在三处:IV 切片位置错、PKCS#7 填充没验、明文末尾被截断。
ciphertext[:aes.BlockSize()] 提取,剩余部分才是真实密文x0b;若刚好整除,要额外补 16 个 x10
orig[:len(orig)-pad],得先读末字节 n := orig[len(orig)-1],再验证最后 n 字节是否全等于 n,否则可能是篡改或 IV 错cipher.NewGCM 返回的 AEAD 接口确实省去填充和手动 IV 管理,但 nonce 重用后果比 CBC IV 复用严重得多:攻击者可直接恢复密钥。
nonce 长度固定为 12 字节(Go 默认),不是 16,也不是随便设crypto/rand.Read(nonce) 生成,且每次加密都新生成——别拼时间戳、别用计数器、别复用nonce + ciphertext + tag(tag 默认 16 字节),解密前必须把最后 16 字节切出来当 tag,传给 aead.Open
aead.Open 返回 cipher.AEADDecryptError 表示认证失败,此时绝不能忽略错误继续用解密结果ECB 看似最简:不用 IV、不用填充、block.Encrypt 直接循环调用。但它让相同明文块永远输出相同密文块,比如日志里反复出现的 "status:success" 会被识别为固定密文模式,等同于裸奔。
立即学习“go语言免费学习笔记(深入)”;
key[:16] 当 IV:这等于把密钥的一部分暴露给攻击者,且完全丧失随机性io.ReadFull(rand.Reader, iv) 比 rand.Read(iv) 更安全,避免读不满