【问题标题】:Breaking down RSA/ECB/OAEPWithSHA-256AndMGF1Padding分解 RSA/ECB/OAEPWithSHA-256AndMGF1Padding
【发布时间】:2015-11-16 15:53:00
【问题描述】:

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

RFC3447公钥加密标准 (PKCS) #1:RSA 加密规范 2.1 版7.1.2 解密操作部分说哈希和 MGF 都是RSAES-OAEP-DECRYPT 的选项。 MGF 是它自己的函数,在Section B.2.1 MGF1 中定义,它也有自己的哈希“选项”。

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

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

【问题讨论】:

    标签: java encryption cryptography rsa


    【解决方案1】:

    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 密文无效,您首先应确保使用了正确的“默认值”。选择自己的默认值是不可能错误的任何库实现;最后由协议来定义使用的哈希值。不幸的是,不存在强制默认值 - 如果协议所有者忘记完全指定算法的配置,这尤其是一个问题。

    【讨论】:

    • 我在玩 BouncyCastle 加密提供商,而 BouncyCastle 似乎在 RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING 方面的运作方式有所不同。 IE。而 Java 的默认加密提供程序使用 sha1 作为 MGF 哈希 bouncycastle 似乎使用 sha256。这可能应该经过独立验证,但在我看来就是这样......
    • 我刚刚验证了这一点,sun.security.rsa.RSAPadding 与 OAEP SHA256 一起使用时,MGF1 功能使用 SHA1,充气城堡两者都使用 SHA256,这就是它们不兼容的原因。
    • WebCrypto 也同时使用它。谢谢 - 这让我很难过。
    • 上面的代码示例仅适用于充气城堡提供商。 SunJCE 不支持填充“OAEPPadding”(至少不支持 JDK7)。也许您将其添加为旁注。
    • @MaartenBodewes:你当然是对的。但是你不应该低估这个行业的懒惰(“永远不要改变一个正在运行的系统”)。我无法影响我们的客户应用什么 Java 版本。并且:是的,我确信:''Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPPadding")'' 在 Oracle 1.7.0_75 和 OpenJDK 1.7.0-u80 中都会产生 NoSuchAlgorithmException。只有在添加 BC-Provider 之后,密码才会被初始化。
    猜你喜欢
    • 2019-05-27
    • 2020-03-17
    • 1970-01-01
    • 2021-11-16
    • 2015-08-31
    • 1970-01-01
    • 2015-03-27
    • 1970-01-01
    • 2014-07-13
    相关资源
    最近更新 更多