
本文详解 go 中 rsa 与 aes 混合加密的正确实现方式:用 rsa 公钥加密 aes 随机密钥,用该 aes 密钥加密实际数据,避免直接用 rsa 加密长内容或误将 pem 字符串当 aes 密钥使用。
本文详解 go 中 rsa 与 aes 混合加密的正确实现方式:用 rsa 公钥加密 aes 随机密钥,用该 aes 密钥加密实际数据,避免直接用 rsa 加密长内容或误将 pem 字符串当 aes 密钥使用。
在密码学实践中,RSA 不适合直接加密大量数据,其加解密性能低、有严格长度限制(如 2048 位 RSA 最多加密约 245 字节明文),且直接加密敏感数据存在安全风险。而 AES 是高效、安全的对称加密算法,但密钥分发困难。因此,工业级应用普遍采用 混合加密(Hybrid Cryptography):用 RSA 加密一个随机生成的 AES 密钥(即“会话密钥”),再用该 AES 密钥加密原始数据;解密时,先用 RSA 私钥解出 AES 密钥,再用它解密数据。
你遇到的 crypto/aes: invalid key size 1639 错误,根本原因在于:误将 PEM 格式的 RSA 私钥字符串(长度约 1600+ 字节)直接传给 aes.NewCipher() —— AES 仅支持 16 字节(AES-128)、24 字节(AES-192)或 32 字节(AES-256)密钥,而 PEM 文本远超此范围,导致密钥尺寸校验失败。
✅ 正确做法如下:
1. 生成 RSA 密钥对(推荐 2048 或 3072 位)
import (
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/pem"
)
// 生成 2048 位 RSA 密钥对(注意:原代码中 2014 是笔误,应为 2048)
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
log.Fatal("RSA key generation failed:", err)
}
publicKey := &privateKey.PublicKey2. 生成随机 AES 密钥(如 AES-256)
aesKey := make([]byte, 32) // AES-256 requires 32-byte key
if _, err := rand.Read(aesKey); err != nil {
log.Fatal("Failed to generate AES key:", err)
}3. 用 RSA 公钥加密 AES 密钥(OAEP 填充,更安全)
import "crypto/rsa"
encryptedAesKey, err := rsa.EncryptOAEP(
sha256.New(), rand.Reader,
publicKey, aesKey, []byte("aes-key-encryption"),
)
if err != nil {
log.Fatal("RSA encryption of AES key failed:", err)
}4. 用 AES-GCM 加密明文数据
import (
"crypto/aes"
"crypto/cipher"
"io"
)
block, err := aes.NewCipher(aesKey)
if err != nil {
log.Fatal("AES cipher creation failed:", err)
}
gcm, err := cipher.NewGCM(block)
if err != nil {
log.Fatal("GCM creation failed:", err)
}
nonce := make([]byte, gcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
log.Fatal("Failed to read nonce:", err)
}
ciphertext := gcm.Seal(nonce, nonce, []byte("My name is Astaxie"), nil)5. 解密流程(逆向执行)
- 用 RSA 私钥解密
encryptedAesKey→ 得到原始aesKey - 用
aesKey初始化 AES-GCM,分离 nonce 并解密ciphertext
⚠️ 关键注意事项:
- ✅ RSA 仅用于加密 固定长度的 AES 密钥(如 32 字节),而非原始数据;
- ✅ 始终使用
EncryptOAEP(而非 PKCS#1 v1.5)提升抗攻击能力; - ✅ AES 推荐使用 AEAD 模式(如 GCM),确保机密性与完整性;
- ❌ 绝不将 PEM 字符串、私钥结构体或 DER 字节直接作为 AES 密钥;
- ? 私钥需安全存储(如 HSM、加密文件),公钥可自由分发。
通过以上混合方案,你既能享受 RSA 的安全密钥交换能力,又能获得 AES 的高性能数据加密能力——这才是 Go 中生产环境推荐的加密实践。

















