最近一直在使用密码算法写认证协议相关的东西,发现明文空间过长会导致加解密不成功的情况。
栗子:
1 |
|
关于密钥与明文长度,从网上查阅的说法如下:
一次能加密的明文长度与密钥长度成正比:
len_in_byte(raw_data) = len_in_bit(key)/8 -11,如 1024bit 的密钥,一次能加密的内容长度为 1024/8 -11 = 117 byte。
所以非对称加密一般都用于加密对称加密算法的密钥,而不是直接加密内容。
实际上,RSA 算法本身要求加密内容也就是明文长度 m 必须满足 0<m<n,也就是说内容这个大整数不能超过 n,否则就出错。
那么如果 m=0 是什么结果?
普遍 RSA 加密器会直接返回全 0 结果,如果 m>n,运算就会出错。
因此,RSA 实际可加密的明文长度最大也是 1024bits,但问题就来了:
如果小于这个长度怎么办?
就需要进行 padding,因为如果没有 padding 用户无法确分解密后内容的真实长度,字符串之类的内容问题还不大,以 0 作为结束符,便于区分。
但对二进制数据就很难理解,因为不确定后面的 0 是内容还是内容结束符。
只要用到 padding,那么就会占用实际的明文长度,我们一般使用的 padding 标准有 NoPPadding、OAEPPadding、PKCS1Padding 等。
其中 PKCS#1 建议的 padding 就占用了 11 个字节,于是才有 117 字节的说法。
如果大于这个长度怎么办?
很多算法的 padding 往往是在后边的,但 PKCS 的 padding 则是在前面的,此为有意设计,有意的把第一个字节置 0 以确保 m 的值小于 n。
这样,128字节(1024bits)- 11 字节正好是117字节,但对于 RSA 加密来讲,padding 也是参与加密的。
所以,依然按照 RSA 1024 实际的明文只有 117 字节。
关于 PKCS#1 padding 规范可参考:RFC2313 chapter 8.1。
我们在把明文送给 RSA 加密器前,要确认这个值是不是大于 n,也就是如果接近 n 位长,那么需要先 padding 再分段加密。
除非我们是“定长定量自己可控可理解”的加密则不需要 padding。
这就不难理解为什么公钥不适合用来做大规模数据传输的加密了,当然如果一定要用公钥来做,也可以通过分段加密或者数字信封的方式解决。
参考:
https://www.cnblogs.com/jpfss/p/8528406.html
https://www.cnblogs.com/aLittleBitCool/archive/2011/09/22/2185418.html