本节从实用角度讲了公钥密码学标准和RSA的padding标准及使用。可以总结如下: 每次RSA加密明文的长度是受RSA填充模式限制的,但是RSA每次加密的块长度是固定的,就是key length
上一节整理了RSA运算中的快速幂模运算。 本节介绍下PKCS标准和Java中相关实现,
PKCS全称Public Key Cryptography Standers, 是RSA信息安全公司与其合作伙伴共同制定的,被信息界的产业广泛认同。 下面简要罗列下主要的PKCS内容:
PKCS#1:定义RSA公开密钥算法加密和签名机制,主要用于组织PKCS#7中所描述的数字签名和数字信封。 PKCS#3:定义Diffie-Hellman密钥交换协议。 PKCS#5:描述一种利用从口令派生出来的安全密钥加密字符串的方法。从口令中派生密钥,并采用DES-CBC模式加密。主要用于加密从一个计算机传送到另一个计算机的私人密钥,不能用于加密消息。 PKCS#6:描述了公钥证书的标准语法,主要描述X.509证书的扩展格式。 PKCS#7:定义一种通用的消息语法,包括数字签名和加密等用于增强的加密机制,PKCS#7与PEM兼容,所以不需其他密码操作,就可以将加密的消息转换成PEM消息。 PKCS#8:描述私有密钥信息格式,该信息包括公开密钥算法的私有密钥以及可选的属性集等。 PKCS#9:定义一些用于PKCS#6证书扩展、PKCS#7数字签名和PKCS#8私钥加密信息的属性类型。 PKCS#10:描述证书请求语法。 PKCS#11:称为Cyptoki,定义了一套独立于技术的程序设计接口,用于智能卡和PCMCIA卡之类的加密设备。 PKCS#12:描述个人信息交换语法标准。描述了将用户公钥、私钥、证书和其他相关信息打包的语法。 PKCS#13:椭圆曲线密码体制标准。 PKCS#14:伪随机数生成标准。 PKCS#15:密码令牌信息格式标准。
注:近年来RSA公司也与其他组织(比较知名的有IETF、PKIX)将标准的制定通过standards track程序来达成,并不包含在上面的列表中,感兴趣的可自行查阅。
简单知道一下,需要的时候再看具体内容。下面具体说下PKCS中RSA的padding方式。
RSA加密常用的填充模式有三种【注:其实第三种已经不常用了】:
填充方式 | 输入明文最大值 |
---|---|
RSA_PKCS1_PADDING | RSA_size(rsa) – 11 |
RSA_PKCS1_OAEP_PADDING | RSA_size(rsa) – 41 |
RSA_NO_PADDING | 可同RSA钥模长一样,如过长,必须切割,然后填充 |
三者的输出都是模长的位数。 填充方式规范见于PKCS#1_v1.5
下面详细说说这三种方式:
这种方式是Java库中默认采用的填充方式,其格式如下:
00 02 [R] 00 [M]
第一位默认为00 第二位是块类型:01表示签名,02表示加解密 第三部分是一串随机数R 第四部分是一个0 最后一部分就是明文, 其中随机R的位数大小是根据其他几个字段决定的,如下: R位数 = 公钥n位数 - 3 - 明文M位数 而PKCS#1建议最小的随机数R为8位才足够安全,可得明文最大是: 公钥n位数 - 11 * 8 下面列出不同公钥大小能加密的明文最大长度:
1024: (1024 - 11 8) / 8= 117 2048: (2048 - 11 8) /8 = 245 4096: (4096 - 11 * 8)/8 = 501
使用1024位的话,最大单次加密只能117个字节,这也通常被认为是RSA的一个缺点【虽然增加位数能提高支持明文长度,比如2048位,也最多245个字节,依然很小】,虽然在理论上可以支持大于n的数据加密(分组),实际应用中考虑各种因素并没有这么做。如果传入大于117字节数据,会抛出异常“javax.crypto.IllegalBlockSizeException: Data must not be longer than 117 bytes”
这一种方式已经比较安全了,唯一一点瑕疵是明文的完整性不好百分百确保,下面要说的OAEP方式又引入了hash校验。
这种方式安全性是最高的,和前面RSA_PKCS1_PADDING的区别就是加密前的编码方式不一样。
OAEP的组成由明文文的Hash + 随机数+分隔符+原文, 具体的操作参见RSA密文攻击与OAEP
如何在代码中指定使用OAEP模式呢?图中展示了Java代码调用示例。
当你在客户端选择RSA_NO_PADDING填充模式时,如果明文不够128字节 加密的过程会在明文前面填充0。当然,解密后的明文也会包括前面填充的0,这时需要服务器把解密后的字段去掉前面的0,才是真正的明文。
当然如果本来明文就以0开头的,就难以区别是填充的0还是明文中的0,使用时要注意。截图是个实验实例:明文是“test no padding message!”, 前面都是被填充的0
这种填充方式因为安全性低使用较少,Java代码中可按如下指定使用该方法,不再赘述。
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding");
填充技术关系到RSA的安全性的高低,这在之前安全分析文章可以看出。现在一般推荐OAEP的填充模式。
本节从实用角度讲了公钥密码学标准和RSA的padding标准及使用。可以总结如下: 每次RSA加密明文的长度是受RSA填充模式限制的,但是RSA每次加密的块长度是固定的,就是key length
关于PCKS1.5&RSA的详细paper,参见:http://tools.ietf.org/html/rfc2313
关于RSA的主题还有一个是在VRF(Verified Random Function)可验证随机函数中的应用。以后找机会再说。
好了,下一篇继续说schnorr经典签名机制。
欢迎关注公众号:blocksight
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!