go中aes文件加密不能直接用aes.newcipher+io.copy,因其仅支持16字节单块加密,需手动处理16字节iv随机生成、pkcs#7填充、密文结构(iv+密文)、大文件流式分块对齐及密钥长度(16/24/32字节)校验。

Go 语言里对文件内容做 AES 加密,不能直接用 aes.NewCipher 塞进去就完事——它只负责单块加密,不处理 IV、不填 PKCS#7、不解耦文件 I/O,硬来会 panic、解密乱码或被攻击。
为什么 aes.NewCipher + io.Copy 一跑就崩?
常见错误组合是:读文件 → aes.NewCipher(key) → io.Copy 到加密 writer。这根本走不通,原因很实在:
-
aes.NewCipher返回的是cipher.Block,只能加密恰好aes.BlockSize()(16 字节)的输入;传入任意长度的 []byte 会 panic 或越界写入 -
io.Copy是流式复制,不保证每次读到的数据长度是 16 的倍数,最后一块很可能短于 16 字节,导致CryptBlocks失败 - 没生成随机 IV,也没把 IV 写进输出,解密时根本不知道用什么 IV 还原
- 没做 PKCS#7 填充,明文长度不是 16 倍数,CBC/CFB 模式下解密后末尾一堆垃圾字节
用 CBC 模式加密文件,必须三步闭环
CBC 兼容性好(比如要和 Python/Java 互通),但得自己闭环所有环节:
- 密钥必须是 16/24/32 字节 —— 别用
[]byte("mykey")(5 字节),推荐用sha256.Sum256([]byte(raw)).Sum(nil)[:32]派生 AES-256 密钥 - IV 必须是 16 字节、每次加密调用
io.ReadFull(rand.Reader, iv)随机生成,绝不能复用或硬编码 - 明文要先
PKCS7Padding:算出pad := 16 - len(data)%16,追加pad个值为byte(pad)的字节;解密后要校验末尾字节再截掉,不能无脑切最后 N 字节 - 密文结构固定为:
[16-byte IV][padded encrypted data],解密端先读前 16 字节作 IV,再解剩余部分
更推荐直接上 cipher.NewGCM(别手搓 CBC)
GCM 是 Go 标准库里最省心又安全的选择,它把填充、认证、nonce 管理全包了,只要你不踩两个坑:
- nonce 长度必须严格匹配
gcm.NonceSize()(默认 12 字节);存文件时前置 12 字节,读的时候io.ReadFull(r, nonce)精确读取,多 1 字节或少 1 字节都会让gcm.Open返回cipher.ErrInvalidLength - 同一个密钥下,绝对禁止重复使用 nonce —— 即使是 12 字节随机值,也要确保概率足够低;生产环境建议用
crypto/rand.Read(nonce),别用time.Now().UnixNano()这种可预测源 - 加密输出是
gcm.Seal(nonce, nonce, data, nil),结果 =[nonce][ciphertext][auth tag](tag 固定 16 字节);解密时gcm.Open(dst, nonce, ciphertextWithTag, nil)会自动校验 tag,失败直接返回 error,不会吐出错乱明文 - 密钥长度仍要合规:AES-256 就必须 32 字节,
aes.NewCipher(key)才不 panic
大文件别全读进内存,但分块加密有讲究
几 MB 还行,上百 MB 就得流式处理。注意关键细节:
- 不要用
bufio.Scanner或按行读 —— AES 是块密码,必须按 16 字节对齐;缓冲区大小设为 65536(64KB)这种 16 的倍数 - CBC 模式不能随意分块加解密:后一块依赖前一块密文,所以整文件得当一个逻辑单元处理;真要分块,得用 CFB 或 GCM,并确保每块 nonce 独立且可追溯(比如用块序号派生)
- GCM 更现实的做法是:小文件全读 →
aead.Seal;中等文件(bytes.Buffer 分段拼接;真正的大文件(>500MB)建议换chacha20poly1305(标准库也支持),它对长流更友好 - 无论哪种模式,IV/nonce 和 salt(如果用了 KDF)都必须随密文一起持久化,通常放在文件开头,解密端按约定顺序读取
最容易被忽略的其实是密钥来源和 IV 生命周期 —— 密钥不能是字符串字面量,IV 不能从密钥里切出来,哪怕只用一次。这些点不卡死,加密看起来能跑,实则毫无语义安全性。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











