Go中AES-CBC加密需手动处理PKCS#7填充、随机IV(随密文传输)、正确密钥长度;RSA仅适用于小数据,大文本须用混合加密;HTTP传输需base64编码二进制密文,密钥生成必须用crypto/rand。

Go 里用 crypto/aes 做对称加密,别直接手写 CBC 模式
Go 标准库的 aes 包不直接提供“加密字符串”函数,必须自己组合分组模式、填充、IV 管理。常见错误是忽略 PKCS#7 填充或硬编码 IV,导致解密失败或安全漏洞。
实际用法要点:
-
aes.NewCipher只生成 cipher 实例,不处理模式;cipher.NewCBCEncrypter才真正启用 CBC - IV 必须随机生成且随密文一起传输(比如前 16 字节),不能复用,否则相同明文产生相同密文
- 明文长度不是 16 的倍数时,需手动做 PKCS#7 填充(
bytes.Repeat([]byte{byte(padLen)}, padLen)),标准库不自动补 - 密钥长度必须是 16(AES-128)、24(AES-192)或 32(AES-256)字节,传错会 panic:“invalid key size”
crypto/rsa 公钥加密适合小数据,别用来加密整个 HTTP body
RSA 加密有严格长度限制:用 2048 位密钥时,最多只能加密约 245 字节(PKCS#1 v1.5)或 190 字节(OAEP)。试图加密大文本会直接 panic:“message too long for RSA public key size”。
典型误用场景和应对方式:
立即学习“go语言免费学习笔记(深入)”;
- 想加密 JSON 请求体?改用混合加密:用 RSA 加密一个随机 AES 密钥,再用该 AES 密钥加密实际数据
- 公钥从 PEM 文件读取时,必须用
pem.Decode解包,再用x509.ParsePKIXPublicKey解析,跳过任一环节都会报 “invalid public key” - 私钥解密必须用
rsa.DecryptPKCS1v15或rsa.DecryptOAEP,对应加密时选的填充方案,混用会导致“crypto/rsa: decryption error”
HTTP 传输中加解密,关键在序列化与边界处理
加密后的二进制数据不能直接塞进 JSON 字段,否则会破坏结构或被转义。常见错误是把 []byte 直接 json.Marshal,结果得到 base64 字符串但没显式声明,下游解析时当成普通字符串处理。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
推荐做法:
- 加密后立刻用
base64.StdEncoding.EncodeToString转成可传输字符串,解密前用base64.StdEncoding.DecodeString还原 - 设计 API 时,在请求/响应结构体中明确字段用途,例如:
EncryptedData string `json:"data"`+IV string `json:"iv"` - 不要在 HTTP Header 里传密钥或敏感参数,Header 可能被日志、代理记录;密钥应通过 TLS 或预共享方式安全分发
别忽略 crypto/rand 和 time.Now().UnixNano() 的区别
生成 IV 或 AES 密钥时,必须用 crypto/rand.Read,不能用 math/rand 或时间戳。前者是密码学安全的随机源,后者可被预测,导致密钥可被还原。
典型错误代码片段:
key := make([]byte, 32) rand.Read(key) // ✅ 正确 // rand.Seed(time.Now().UnixNano()); rand.Read(key) // ❌ 完全不安全
另外,crypto/rand 在 Windows 上依赖 CryptoAPI,Linux/macOS 读 /dev/urandom,跨平台没问题,但若程序运行在容器中且 /dev 隔离不严,需验证 rand.Read 是否返回非零错误。
加密流程里最易被跳过的环节:密钥派生。如果用户密码当 AES 密钥用,必须走 crypto/scrypt.Key 或 crypto/bcrypt.GenerateFromPassword,直接 sha256.Sum256 不够安全。

















