不能直接用crypto/aes.NewCipher做文件加密,因其仅返回cipher.Block,不处理IV、无填充、无完整性校验;需配合CBC或GCM模式,正确生成IV/nonce、PKCS#7填充(CBC)或使用cipher.NewGCM(GCM),并严格校验密钥长度与结构。

为什么不能直接用 crypto/aes.NewCipher 做文件加密
因为 aes.NewCipher 只返回一个 cipher.Block,它不带模式、不处理 IV、不填充、不校验完整性——你得自己拼出完整流程。直接拿它套 io.Copy 或整块 bytes 加密,十有八九解出来是乱码或 panic。
- CBC 模式必须手动做 PKCS#7 填充,
cipher.BlockMode不自动补; - GCM 模式必须用
cipher.NewGCM得到cipher.AEAD,否则没认证标签,解密时Open会失败; - 复用 IV(比如固定写死
[]byte{0,0,...})会让相同明文生成相同密文,等于裸奔; - 大文件一次性读进内存会 OOM,但用
io.Copy直接流式加密又会破坏块对齐,最后一块填充错位。
如何安全地派生 AES 密钥而不是硬编码 password
用户输的密码(如 "my123!")不能当 AES-256 密钥直接用——太短、熵低、易被爆破。必须走密钥派生函数(KDF),推荐 scrypt 或 pbkdf2,别用 sha256 简单哈希。
-
scrypt.Key参数建议设为N=32768, r=8, p=1,输出 32 字节密钥; - 每次加密都生成新 salt:
crypto/rand.Read(salt),长度至少 32 字节; - salt 和 IV 都要存进密文头部(例如前 32 字节 salt + 接着 12 或 16 字节 nonce/IV);
- 密钥切片用完立刻清零:
bytes.Fill(key),防止内存 dump 泄露。
文件加解密该选 CBC 还是 GCM 模式
优先选 AES-256-GCM。CBC 只保证机密性,不防篡改;GCM 一步到位,加密同时生成认证标签,解密失败时直接报错,不会输出垃圾数据。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- GCM 的 nonce 推荐 12 字节(不是 16),用
crypto/rand.Read(nonce)生成; - 加密后密文 =
nonce + sealed(sealed包含密文+16字节 tag); - 解密时先读 12 字节 nonce,再调
aesgcm.Open(dst, nonce, sealed, nil); - 如果必须用 CBC(如兼容旧系统),务必额外加 HMAC 校验,或至少在解密后验证 PKCS#7 填充是否合法。
gin 或 gorm 场景下怎么嵌入加密逻辑
框架本身不处理加密,但你可以把加解密逻辑封装成中间件或模型方法,关键点是:别让密钥出现在 handler 或 model 定义里,更别塞进 struct tag。
立即学习“go语言免费学习笔记(深入)”;
- 密钥从环境变量读:
os.Getenv("AES_KEY_BASE64"),启动时 decode 成[]byte; - gin 中做请求体解密:在 middleware 里读
c.Request.Body→ 解密 → 替换为新io.NopCloser; - gorm 里加密字段:用
Scanner/Valuer接口,在Scan时解密、Value时加密,密钥仍走外部注入; - 避免在日志打印明文或密钥——哪怕只是 debug 日志,也得过滤掉敏感字段。

















