AES加密报invalid key size是因为密钥长度必须为16、24或32字节,而字符串字面量如"my-secret"仅9字节;应使用sha256.Sum256或pbkdf2派生合规密钥。

crypto/aes 加密时为什么总报 crypto/aes: invalid key size
因为 AES 只支持固定长度密钥:128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)。传入的 key 长度不对,就会直接 panic。
- 别用字符串字面量直接当密钥——
"my-secret"是 9 字节,不合法 - 推荐用
sha256.Sum256或hmac.New派生固定长度密钥,比如:key := sha256.Sum256([]byte("your-password")).[0:32] - 如果必须从用户密码生成密钥,用
golang.org/x/crypto/pbkdf2,别手写迭代哈希 - 注意:AES 本身不处理密钥派生,这是你代码的责任
文件加密该用 crypto/cipher.AEAD 还是 raw BlockMode
优先选 cipher.AEAD(如 aes.NewGCM),除非你明确需要裸 CBC/CTR 且自己处理填充和认证。
-
AEAD自动提供机密性 + 完整性验证,解密时会校验密文是否被篡改;裸BlockMode不做任何校验,篡改后可能静默解出垃圾数据 - GCM 模式要求 nonce 唯一,建议每次加密用随机 12 字节:
nonce := make([]byte, 12); rand.Read(nonce)
- 不要复用同一个 nonce 加密多个文件,否则 GCM 安全性崩塌
- 如果旧系统只支持 CBC,务必手动加 PKCS#7 填充,并配 HMAC 校验——这相当于在重复造 AEAD 轮子
读大文件时 crypto/aes 内存暴涨甚至 OOM
问题不在 AES 本身,而在你一次性把整个文件读进内存再加密。Go 的 crypto/cipher.Stream 和 io.Pipe 支持流式加解密,这才是正确姿势。
- 用
cipher.Stream(如cipher.NewCTR)配合io.Copy,边读边加,内存占用恒定 - GCM 不支持流式?那就分块加密:每块独立用 GCM(带唯一 nonce),并在头部写入块数量和每块 nonce ——但注意,这会削弱 AEAD 的全局完整性保障
- 别用
os.ReadFile处理 >10MB 的文件;改用os.Open+bufio.NewReader+ 加密 writer 管道 - 加密后的文件体积会略增(GCM +16 字节/块,CTR 无额外开销),这点要提前规划磁盘空间
crypto 库加密的文件,Python/Java 怎么安全解密
跨语言互通的关键不是“用 Go 写了什么”,而是“协议层是否对齐”:AES 模式、填充方式、nonce 位置、密钥派生逻辑,全部得一致。
立即学习“go语言免费学习笔记(深入)”;
- 推荐固定使用
AES-GCM-256,nonce 长度设为 12 字节(主流语言默认值),密文结构统一为:[nonce(12)][ciphertext][auth_tag(16)] - 密钥派生必须用标准 PBKDF2-SHA256(非 md5、非单次 hash),并明确定义 salt(建议随文件存储,或固定)
- Go 默认用大端序处理整数,Python 的
cryptography库也默认大端,但 Java 的SecretKeySpec不处理派生——得自己调PBEKeySpec - 最容易踩的坑:Go 的
aes.NewGCM默认使用 12 字节 nonce,而某些 Python 示例硬编码 16 字节,导致解密失败且错误信息模糊(常报Authentication failed)










