rsa.encryptpkcs1v15 报 “message too long” 是因明文长度超过 rsa 密钥限制:最多 keysize/8−11 字节(如 2048 位密钥限 245 字节);正确做法是用 aes 加密数据、rsa 加密 aes 密钥。

rsa.EncryptPKCS1v15 为什么总 panic: crypto/rsa: message too long
公钥加密时超长报错,根本原因是 RSA 加密对明文长度有硬性限制:最多只能加密 KeySize / 8 - 11 字节(PKCS#1 v1.5 填充)。比如 2048 位密钥,最多加密 256 - 11 = 245 字节。
常见错误现象:panic: crypto/rsa: message too long 或 crypto/rsa: decryption error(解密时因填充损坏)。
- 别直接加密大文本、JSON 或文件内容——RSA 不是干这个的
- 真实场景中,应先用
AES加密原始数据,再用rsa.EncryptPKCS1v15加密那个随机 AES 密钥 - 如果只是测试小字符串,确保长度 ≤
(rsa.PublicKey.Size() - 11),例如 2048 位密钥下控制在 245 字节内 - 注意:
rsa.EncryptPKCS1v15输入是[]byte,不是字符串;中文需先utf8编码转字节,长度按字节算(一个汉字可能占 3 字节)
私钥解密必须用 rsa.DecryptPKCS1v15,且要传 *rsa.PrivateKey
很多人卡在解密失败,不是算法问题,而是类型或参数传错了。Go 的 rsa.DecryptPKCS1v15 要求第一个参数是 *rsa.PrivateKey,不是 *rsa.PublicKey,也不是 interface{}。
使用场景:服务端收到加密后的密文(比如前端用公钥加密的 token),需用本地私钥还原原始数据。
立即学习“go语言免费学习笔记(深入)”;
- 私钥对象必须完整,包含
D、Primes等字段——从 PEM 解析时别漏掉ParsePKCS1PrivateKey或ParsePKCS8PrivateKey - 第二个参数是密文
[]byte,即EncryptPKCS1v15的输出,不能额外 base64 decode 后再解(除非你加密前 base64 了) - 第三个参数是
rand.Reader,生产环境别用rand.New(rand.NewSource(0)),必须用cryptorand.Reader - 返回值第一个是明文
[]byte,第二个是 error;即使解密成功,也要检查 error 是否为 nil —— 有些填充错误会静默返回空切片
生成密钥对时,2048 位是底线,4096 更稳妥
密钥长度直接影响加密/解密能处理的数据上限和安全性。低于 2048 位的 rsa.GenerateKey 在现代系统里已不被信任,部分 TLS 实现会拒绝。
性能影响:密钥越长,EncryptPKCS1v15 和 DecryptPKCS1v15 越慢,尤其是私钥解密(涉及大数模幂),但对单次 token 或小数据影响不大。
- 生成命令建议:
openssl genrsa -out private.pem 4096,对应 Go 中用rsa.GenerateKey(cryptorand.Reader, 4096) - 公钥导出别用
MustEncodePublicKey这类不存在的函数——Go 标准库没有封装,得手动用ssh.MarshalPublicKey或x509.MarshalPKIXPublicKey - 私钥保存务必设密码(PEM 加密),否则磁盘上裸存
private.pem等同于交出系统权限 - 别把
*rsa.PrivateKey长期缓存在 map 里当全局变量——它含敏感字段,GC 不保证及时清零;用完尽快显式置nil
加密后密文长度固定,等于 PublicKey.Size()
这是判断是否用对 API 的快速验证点:len(ciphertext) == pub.Size() 必须成立。比如 2048 位公钥,密文一定是 256 字节;4096 位就是 512 字节。
如果你看到密文长度忽长忽短,说明可能误用了 rsa.EncryptOAEP(它加盐后长度固定但逻辑不同),或中间做了非预期编码(如多套了一层 base64)。
- 密文是原始二进制,网络传输前通常要
base64.StdEncoding.EncodeToString;接收方先base64.StdEncoding.DecodeString再传给DecryptPKCS1v15 - 别用
string(ciphertext)打印密文——乱码且可能截断 \x00 字节;调试时用fmt.Printf("%x", ciphertext) - 某些硬件模块或 HSM 要求密文按特定字节序填充,标准 Go
crypto/rsa输出是 big-endian,一般无需调整
最常被忽略的是:加密和解密用的填充模式必须严格一致。PKCS#1 v1.5 是默认,但一旦混用 OAEP(比如前端用 WebCrypto 的 rsa-oaep),Go 侧就必须换 EncryptOAEP + DecryptOAEP,且哈希、标签都得对齐——这里没商量余地。










