RSA加密解密疑问:明文超110字节无法解密,为何剩7字节不可用?
解密失败的原因:RSA填充的“隐形字节”坑
嘿,这个问题我太懂了!先给你拆解清楚为啥会出现“117字节上限但实际只能用110字节”的矛盾:
先搞懂117字节上限的由来
你应该用的是1024位RSA密钥,1024位换算成字节就是128字节,但RSA加密必须加填充(不然完全不安全),最常用的PKCS#1 v1.5填充会占用至少11字节的固定+随机空间:
- 开头是固定的
0x00 + 0x02标识位(2字节) - 中间是至少8个随机非零字节(用来防止明文攻击,必须有)
- 最后是
0x00分隔符(1字节)
所以最大可加密的明文长度就是128 - 11 = 117字节,这就是错误提示里的数值。
为啥你实际只能用到110字节?
大概率是这两个细节坑:
- 编码的隐形长度:你直接用字符串长度数“i”的个数,但如果你的代码里用了默认编码(比如某些环境下不是UTF-8),或者你在加密前做了额外处理(比如先转Base64),会让实际字节数悄悄超标。比如如果不小心用了UTF-16编码,110个“i”会变成220字节,直接远超117上限。
- 填充验证的严格性:PKCS#1 v1.5要求填充的随机非零字节至少8个,当明文接近117字节时,留给随机字节的空间刚好是8个(比如117字节明文+11字节填充=128字节),如果你的代码里填充生成逻辑有问题,或者加密和解密的填充模式不一致(比如加密用PKCS1Padding,解密不小心用了NoPadding),就会触发解密时的填充验证失败,导致解密失败。
解决办法
- 显式指定填充模式:在Java里创建Cipher时一定要写全参数,比如
Cipher.getInstance("RSA/ECB/PKCS1Padding"),确保加密和解密用完全相同的填充规则,别依赖默认值。 - 按字节数判断明文长度:别直接数字符串的字符数,要把字符串转成字节数组后看长度(比如
message.getBytes(StandardCharsets.UTF_8).length),避免编码带来的隐形长度问题。 - RSA别用来加密长内容:RSA本来就不是为长明文设计的,正确姿势是用AES加密长明文,然后用RSA加密AES的密钥,这样就没有长度限制了。
内容的提问来源于stack exchange,提问作者Onur Kağan Aldemir
相关产品推荐
相关产品推荐

