分解 RSA/ECB/OAEPWithSHA-256AndMGF1Padding

Breaking down RSA/ECB/OAEPWithSHA-256AndMGF1Padding

Java 有一个名为 RSA/ECB/OAEPWithSHA-256AndMGF1Padding 的模式。那到底是什么意思?

RFC3447Public-密钥加密标准 (PKCS) #1:RSA 加密规范版本 2.1,第 7.1 节。 2 解密操作说Hash和MGF都是RSAES-OAEP-DECRYPT的选项。 MGF 是它自己的函数,在第 B.2.1 节 MGF1 中定义,它也有自己的哈希“选项”。

也许 RSAES-OAEP-DECRYPT 和 MGF1 中的哈希“选项”应该相同,或者可能不同,我不清楚。如果是,那么我想当你有 RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING 时,这意味着 sha256 应该用于两者。但是,如果它们不应该相同,那么您可以将 sha256 用于 RSAES-OAEP-DECRYPT,例如,将 sha1 用于 MGF1。如果是这样,那么 sha256 应该用于什么功能?另一个函数应该使用什么哈希算法?

欧洲央行在这种情况下意味着什么? ECB 是一种对称块密码模式。电子密码本。也许它应该意味着 Java 如何处理大于模数的明文?就像也许将明文拆分成与模数一样大的块,然后用 RSA 加密每个块并将它们连接在一起?我只是猜测..

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));

如果您用 "SHA-256" 代替 MGF1 作为参数,代码将失败并出现与填充相关的异常。

完全需要扩展算法的原因是与其他 Cipher 算法的兼容性。为例如编写的代码"RSA/ECB/PKCS1Padding" 不使用任何参数,更不用说 OAEP 参数了。因此,如果没有更长的字符串,OAEP 将无法作为替代品。


操作模式"ECB"在此上下文中没有任何意义,它应该是"None"或者应该完全被忽略。您只能使用 SunRSA 提供程序的 RSA 实现来加密单个块。

如果您想加密更多数据,请创建一个随机 (AES) 对称密钥并使用 OAEP 对其进行加密。然后使用 AES 密钥加密您的特定数据。这被称为混合密码系统,因为它使用非对称和对称原语来加密数据。


请注意,JDK 7 (1.7) 或更早版本不支持 OAEP。 OAEP 包含在 Java 运行时的实施要求中,因为 Java 8:

  • RSA/ECB/OAEPWithSHA-1AndMGF1Padding (1024, 2048)
  • RSA/ECB/OAEPWithSHA-256AndMGF1Padding (1024, 2048)

某些协议可能要求您在填充中使用 SHA-256 或 SHA-512,因为 SHA-1 在大多数情况下已被弃用 - 即使它不会直接受到此类用途的攻击。


编辑:写这篇文章时主要考虑了 Java。到目前为止,许多其他库似乎采取了一些不同的方法,并为(大部分为空的)标签和 MGF1 使用相同的哈希值。如果您有无效的 OAEP 密文,您应该首先确保使用了正确的 "default"。选择自己的默认值是不可能错误的任何库实现;最后,由协议来定义所使用的哈希值。不幸的是,不存在强制性默认值 - 如果协议所有者忘记为算法完全指定配置,这尤其是一个问题。