OAEP 的默认设置是对 MGF1 使用 SHA-1(但请参阅此答案末尾的编辑)。请注意,选择的哈希值对 OAEP 的安全性没有太大影响,因此大多数情况下将保留此默认值。
我们可以通过对"OAEPPadding" 和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));
如果您将 MGF1 替换为 "SHA-256" 作为参数,代码将失败并出现与填充相关的异常。
完全需要扩展算法的原因是与其他Cipher算法的兼容性。为例如编写的代码"RSA/ECB/PKCS1Padding" 不使用任何参数,更不用说 OAEP 参数了。因此,如果没有更长的字符串,OAEP 就不能作为替代品。
"ECB" 的操作模式在这种情况下没有任何意义,它应该是 "None" 或者它应该被完全排除在外。您只能使用 SunRSA 提供程序的 RSA 实现加密单个块。
如果您想加密更多数据,请创建一个随机 (AES) 对称密钥并使用 OAEP 对其进行加密。然后使用 AES 密钥加密您的特定数据。这被称为混合密码系统,因为它同时使用非对称和对称原语来加密数据。
请注意,JDK 7 (1.7) 或更早版本不支持 OAEP。自 Java 8 起,OAEP 已包含在 Java 运行时的实现要求中:
-
RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
-
RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)
某些协议可能要求您在填充中使用 SHA-256 或 SHA-512,因为 SHA-1 在大多数情况下已被弃用 - 即使它对于此类用途而言并非直接易受攻击。
编辑:这主要是在考虑 Java 的情况下编写的。到目前为止,许多其他库似乎采取了一些不同的方法,并为(大部分为空的)标签和 MGF1 使用相同的哈希值。如果您的 OAEP 密文无效,您首先应确保使用了正确的“默认值”。选择自己的默认值是不可能错误的任何库实现;最后由协议来定义使用的哈希值。不幸的是,不存在强制默认值 - 如果协议所有者忘记完全指定算法的配置,这尤其是一个问题。