RSA 到底能加密多长的数据?上限怎么算,超了该怎么办

· 约 5 分钟 🗝️ RSA 加解密

「RSA 一次能加密多少字节」这个问题,网上给出的答案往往是一个具体数字。但只要你换一个填充方案或换一个摘要算法,那个数字就不对了。

上限由三个变量共同决定:密钥长度、填充方案、摘要算法。

完整对照表

密钥长度PKCS#1 v1.5OAEP-SHA-1OAEP-SHA-256OAEP-SHA-384OAEP-SHA-512
RSA-1024117 字节86 字节62 字节30 字节放不下
RSA-2048245 字节214 字节190 字节158 字节126 字节
RSA-3072373 字节342 字节318 字节286 字节254 字节
RSA-4096501 字节470 字节446 字节414 字节382 字节

有几件事值得单独指出:

  • 摘要越强,能加密的越少。 同样是 RSA-2048,SHA-256 能加 190 字节,SHA-512 只剩 126 字节
  • RSA-1024 配 OAEP-SHA-512 是负数,一个字节也放不下,算式本身就不成立
  • 这里说的是字节不是字符。 一个汉字按 UTF-8 占 3 字节,190 字节只够装 63 个汉字

上限是怎么算出来的

RSA 的数学运算是对一个不超过模数的整数做幂模运算。明文必须先被填充成正好 k 字节的一个数据块(k 是模数的字节数,RSA-2048 就是 256)。填充自己要占位置,剩下的才留给明文。

PKCS#1 v1.5:固定开销 11 字节

块结构是:

0x00 || 0x02 || PS || 0x00 || M
  1      1     ≥8     1      明文
  • 开头 0x00 保证这个整数小于模数
  • 0x02 标记这是加密块(签名块是 0x01
  • PS 是随机非零填充串,标准要求至少 8 字节
  • 0x00 分隔符,标记明文从哪开始

固定开销 1 + 1 + 8 + 1 = 11 字节,所以上限是 k - 11

OAEP:固定开销 2×hLen + 2

OAEP 要放的东西更多:一个 hLen 字节的标签哈希、一个 hLen 字节的随机种子、一个前导零字节、一个分隔符字节。加起来是 2×hLen + 2

SHA-256 的 hLen 是 32,开销就是 66 字节;SHA-512 的 hLen 是 64,开销 130 字节。

明明更费空间,为什么还要用 OAEP

因为 v1.5 的填充结构是确定的,历史上被 Bleichenbacher 攻击利用过——1998 年提出,只要攻击者能观察到「填充是否合法」这一位信息,就能通过大量请求逐步把密文解出来,不需要私钥。这类攻击后来在 TLS 实现上反复复发。

OAEP 是 PKCS#1 v2.0 引入的,有可证明安全的形式化证明。新代码一律用 OAEP,v1.5 只在对接老系统时保留。

报错 data too large for key size 之后

先确认三件事:

  1. 明文实际有多少字节(中文按 UTF-8 一个字 3 字节)
  2. 密钥是多少位——PEM 文本里看不出来,得解析
  3. 当前选的填充方案和摘要

然后按推荐程度排,有三条路:

① 改用混合加密(推荐)—— 见下一节,没有长度限制

② 降低摘要强度 —— OAEP-SHA-512 换 SHA-256 能多出 64 字节。这只是把天花板抬高一点,治标不治本

③ 换更长的密钥 —— RSA-4096 配 OAEP-SHA-256 能加 446 字节。代价是运算慢一个量级,而且仍然装不下任何有实际体量的数据

还有第四条路,分段加密,不推荐

为什么不该分段加密

看起来很自然:数据长就切片,每片单独 RSA 加密,接收方逐片解密再拼起来。但这条路有三个问题。

慢。 RSA 的运算比 AES 慢三到四个数量级。加密 1 MB 数据,用 RSA-2048 配 OAEP-SHA-256 要切成约 5500 段,每段做一次模幂运算。同样的数据用 AES-GCM 是毫秒级。

不安全。 每段独立加密,段与段之间没有任何绑定。攻击者可以删掉中间某一段、复制某一段、调换顺序——解密方完全察觉不到。这和 ECB 模式的分组重排问题是同一类。

难维护。 切分长度依赖填充方案和摘要算法,改任何一个参数,所有历史密文都要重算。

正确做法:混合加密

RSA 从设计上就不是用来直接加密数据的,它是用来传密钥的。TLS、PGP、JWE、S/MIME 全都是这个结构。

发送方:

  1. 生成一把一次性的随机 AES 密钥(32 字节,来自密码学安全随机源)
  2. 用 AES-GCM 加密真实数据,nonce 也随机生成
  3. 用对方的 RSA 公钥加密那把 AES 密钥——只有 32 字节,任何密钥长度配任何填充都放得下
  4. 把四段一起发出去:
RSA 加密后的 AES 密钥  (256 字节,RSA-2048)
nonce                 (12 字节)
AES-GCM 密文           (和明文等长)
认证标签               (16 字节)

接收方: 用 RSA 私钥解出 AES 密钥,再用它解密数据。

为什么这是安全的:RSA 保护的是那 32 字节的一次性随机密钥——没有任何结构可供攻击者利用;数据本身由 AES-GCM 保护,既保密又能检测篡改。两边各自做自己擅长的事。

密钥长度怎么选

长度安全强度运算相对成本建议
RSA-1024约 80 位基准❌ 只用来解历史数据
RSA-2048约 112 位约 6 倍✅ 当前主流
RSA-3072约 128 位约 20 倍长期保密的数据
RSA-4096约 140 位约 40 倍保守场景,注意并发代价

RSA-1024 从 2010 年起就不再被 NIST 推荐,各大 CA 早已停止签发。本站工具保留它只是为了让你能解出历史数据。

一个实际的取舍:如果只是保护短期数据且并发量大,RSA-2048 完全够用。如果数据要保密十年以上,考虑 RSA-3072,或者干脆换椭圆曲线——EC P-256 的安全强度接近 RSA-3072,密钥只有 32 字节,运算快一个量级。

动手验证

RSA 加解密会在加密前先算出当前组合的上限,超了就明确告诉你「明文多少字节、上限多少字节」,而不是抛一个 data too large for key size 让你自己猜。

工具支持 PKCS#1 v1.5 和 OAEP 两种填充,OAEP 可选 SHA-1 / SHA-256 / SHA-384 / SHA-512,能直接对照出摘要强度对上限的影响。密钥对生成、加解密、签名验签全在浏览器本地完成,私钥不会离开你的设备。

如果你手上的密钥 PEM 贴进去解析不了,那多半是格式问题不是长度问题,见 RSA 密钥格式认不出来:PKCS#1、PKCS#8、SPKI 到底差在哪

❓ 常见问题

RSA 一次最多能加密多少字节?

取决于密钥长度、填充方案和摘要算法三者,不是一个固定值PKCS#1 v1.5 的上限k - 11,其中 k 是密钥的字节数(RSA-2048 就是 256)。所以 RSA-2048 配 v1.5 能加 245 字节OAEP 的上限k - 2×hLen - 2,hLen 是摘要输出的字节数。RSA-2048 配 OAEP-SHA-256(hLen=32)就是 256 - 64 - 2 = 190 字节注意摘要越强上限越低:同样是 RSA-2048,换成 OAEP-SHA-512 只剩 126 字节。极端情况会直接放不下:RSA-1024 配 OAEP-SHA-512 算出来是 128 - 128 - 2 = 负数,一个字节也加不了,工具会直接拒绝。一个常被忽略的点:这里说的是字节不是字符。一个汉字按 UTF-8 是 3 字节,190 字节只够装 63 个汉字。

为什么 PKCS#1 v1.5 要减 11,OAEP 要减 2 倍摘要长度加 2?

因为填充本身要占地方。RSA 的数学运算是对一个不超过模数的整数做幂模运算,明文必须先被填充成正好 k 字节的一个块。PKCS#1 v1.5 的块结构0x00 || 0x02 || PS || 0x00 || M:开头两个固定字节,结尾一个分隔符,中间的随机填充串 PS 标准要求至少 8 字节——加起来固定开销就是 2 + 8 + 1 = 11 字节OAEP 的结构更复杂:它要放一个 hLen 字节的标签哈希、一个 hLen 字节的随机种子、一个字节的前导零,还有一个字节的分隔符,加起来是 2×hLen + 2为什么 OAEP 更费空间还要用它:v1.5 的填充是确定长度的固定结构,历史上被 Bleichenbacher 攻击利用过(1998 年,只要能观察到「填充是否合法」就能逐步解出密文);OAEP 有可证明安全的形式化证明,是 PKCS#1 v2.0 之后的推荐方案。新代码一律用 OAEP,v1.5 只在对接老系统时保留。

报错 data too large for key size 该怎么办?

这不是 bug,是 RSA 的硬性限制,解决办法是改用混合加密而不是换个工具先确认三件事:(1) 你的明文实际有多少字节(不是字符,中文按 UTF-8 是一个字 3 字节);(2) 密钥是多少位——PEM 里看不出来,用工具解析一下;(3) 当前选的填充方案和摘要。三条出路,按推荐程度排:(1) 换成混合加密——用 AES 加密真实数据,只用 RSA 加密那把 16 或 32 字节的 AES 密钥。这是所有正经协议的做法,没有长度限制;(2) 降低摘要强度——OAEP-SHA-512 换成 SHA-256 能多出 64 字节空间,但这只是把天花板抬高一点,治标不治本;(3) 换更长的密钥——RSA-4096 配 OAEP-SHA-256 能加 446 字节,但代价是运算慢一个量级,且仍然装不下任何有实际体量的数据。唯一不推荐的是分段加密

为什么不推荐把长数据切片后逐段 RSA 加密?

因为它慢得离谱,而且分段本身会引入 ECB 那一类的问题性能:RSA 的私钥运算比 AES 慢三到四个数量级。加密 1 MB 数据,用 RSA-2048 配 OAEP-SHA-256 要切成大约 5500 段,每段做一次模幂运算;同样的数据 AES-GCM 在同一台机器上是毫秒级。安全性:每一段独立加密,就重新引入了 ECB 模式的全部问题——相同的明文段产生相同的密文段(v1.5 和 OAEP 有随机填充,这一条被缓解了),但段与段之间没有任何绑定,攻击者可以删掉中间某一段、复制某一段、或者调换顺序,解密方完全察觉不到。工程性:切分长度依赖填充方案和摘要,改一个参数所有历史密文都要重算。正确做法只有一个:RSA 只用来传密钥,数据本身交给对称算法。

混合加密具体怎么做?

用 AES 加密数据,用 RSA 加密 AES 的密钥,两段一起传发送方:(1) 生成一把一次性的随机 AES 密钥(32 字节,密码学安全随机源);(2) 用 AES-GCM 加密真实数据,nonce 也随机生成;(3) 用对方的 RSA 公钥加密那把 AES 密钥——32 字节,任何密钥长度配任何填充都放得下;(4) 把「RSA 加密后的密钥 + nonce + 密文 + 认证标签」四段一起发出去。接收方:用 RSA 私钥解出 AES 密钥,再用它解密数据。为什么是安全的:RSA 保护的是那 32 字节的密钥,一次性的、随机的、没有任何结构可利用;数据本身由 AES-GCM 保护,既保密又防篡改。这不是什么变通方案——TLS、PGP、JWE、S/MIME 全都是这个结构,RSA 从设计上就不是用来直接加密数据的。

密钥长度该选多少位?1024 还能用吗?

新系统最低 RSA-2048,1024 位已经不该在生产环境出现RSA-1024:NIST 从 2010 年起就不再推荐,业界普遍认为它在有组织的算力面前不再安全,各大 CA 早已停止签发 1024 位证书。它在本站工具里保留只是为了让你能解出历史数据。RSA-2048:目前的主流选择,安全强度大致相当于对称的 112 位。RSA-3072:安全强度约 128 位,对标 AES-128,是需要长期保密的数据的合理选择。RSA-4096:更保守,但签名和解密的运算量大约是 2048 位的 6 到 7 倍,在高并发场景下这个代价很明显。一个实际的取舍:如果只是保护短期数据、且并发量大,RSA-2048 完全够用;如果数据要保密十年以上,考虑 3072 或者干脆换椭圆曲线——EC P-256 的安全强度接近 RSA-3072,但密钥只有 32 字节、运算快一个量级。

🗝️ 打开 RSA 加解密 公钥加密/私钥解密·PKCS1v1.5 与 OAEP·SHA 签名验签·PEM 密钥对生成·本地运行不上传

📖 同一工具的其他教程

🔗 相关阅读

全部教程 →