OAEP 使用单独的哈希调用来哈希标签(通常为空)以及 MGF1(掩码生成函数)的参数,用于大多数 OAEP 填充。
该哈希对 OAEP 的安全性没有太大影响,因此可以保留此默认值。然而,大多数库对 MGF-1 和(始终为空)标签的散列使用相同的散列算法。然而,Java 默认使用 MGF1。
我们可以通过比较使用实例化的标准 Java Cipher 来轻松测试这一点"OAEPWITHSHA-256ANDMGF1PADDING"
针对一个实例化使用"OAEPPadding"
and OAEPParameterSpec
:
// --- we need a key pair to test encryption/decryption
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024); // speedy generation, but not secure anymore
KeyPair kp = kpg.generateKeyPair();
RSAPublicKey pubkey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privkey = (RSAPrivateKey) kp.getPrivate();
// --- encrypt given algorithm string
Cipher oaepFromAlgo = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");
oaepFromAlgo.init(Cipher.ENCRYPT_MODE, pubkey);
byte[] ct = oaepFromAlgo.doFinal("owlstead".getBytes(StandardCharsets.UTF_8));
// --- decrypt given OAEPParameterSpec
Cipher oaepFromInit = Cipher.getInstance("RSA/ECB/OAEPPadding");
OAEPParameterSpec oaepParams = new OAEPParameterSpec("SHA-256", "MGF1", new MGF1ParameterSpec("SHA-1"), PSpecified.DEFAULT);
oaepFromInit.init(Cipher.DECRYPT_MODE, privkey, oaepParams);
byte[] pt = oaepFromInit.doFinal(ct);
System.out.println(new String(pt, StandardCharsets.UTF_8));
如果您替换,代码将失败并出现与填充相关的异常"SHA-256"
对于 MGF1 作为参数,表明 SHA-1 确实是默认值。
需要长算法字符串的原因是与其他算法的兼容性Cipher
算法。编写的代码,例如"RSA/ECB/PKCS1Padding"
不使用任何参数;因此,如果没有更长的字符串,OAEP 就不能起到替换中的删除作用。
运作方式"ECB"
在这种情况下没有任何意义,它应该是"None"
或者它应该被完全排除在外。您只能使用 SunRSA 提供程序的 RSA 实现来加密单个块。
如果要加密更多数据,请创建随机 (AES) 对称密钥并使用 OAEP 对其进行加密。然后使用 AES 密钥加密您的特定数据。这称为混合密码系统,因为它使用非对称和对称原语来加密数据。
请注意,JDK 7 (1.7) 或更早版本不支持 OAEP。 OAEP 包含在 Java 运行时的实现要求中从 Java 8 开始 https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#impl:
-
RSA/ECB/OAEPWithSHA-1AndMGF1Padding
(1024, 2048)
-
RSA/ECB/OAEPWithSHA-256AndMGF1Padding
(1024, 2048)
某些协议可能要求您在填充中使用 SHA-256 或 SHA-512,因为 SHA-1 在大多数用途中已被弃用 - 即使它不会直接受到此类目的的攻击。 SHA-224 或 SHA-384 都没有任何意义,因为它们是 SHA-256 和 SHA-512 的版本,具有减小的输出大小,因此需要更多调用来创建填充,而不提供任何安全优势(是的,测试此确实表现出性能劣势)。
如果您有无效的 OAEP 密文,您应该首先确保标签和 MGF1 使用正确的“默认值”。
任何库实现都不可能因为选择自己的默认值而出错;最后由协议来定义所使用的哈希值。
不幸的是,不存在强制默认值 - 如果协议所有者忘记完全指定算法的配置,这尤其是一个问题。