【问题标题】:Which padding is used by javax.crypto.Cipher for RSAjavax.crypto.Cipher 为 RSA 使用了哪个填充
【发布时间】:2015-11-09 02:40:08
【问题描述】:

我需要通过 RSA 解密消息以便通过不安全的通道发送它,但我害怕 Padding Oracle Attack。因此,我已经问了以下问题:

  1. How to verify the integrity of RSA encrypted messages?
  2. How to ensure message integrity for RSA ciphers by using javax.crypto.Cipher

就像第一个问题中建议的那样,

但是,由于您使用的是高级加密库,因此您不必担心这一点。该库的作者应该照顾它。

我不应该考虑。据我所知,PKCS#1 v1.5 的 RSA 实现容易受到Padding Oracale Attack 的影响,而OAEP 则不是(假设它实现正确)

因此我想知道 Java 7 中 javax.crypt.Cipher 使用了哪个填充实现

【问题讨论】:

  • 这取决于提供者,但很可能是 PKCS1Padding(PKCS#1 v1.5 填充)。为了澄清,你问的是当你没有像Cipher.getInstance("RSA")那样完全限定密码时使用什么填充?
  • @ArtjomB 是的,完全正确。但如果更安全的话,我会使用像 BouncyCastle 这样的不同的。
  • 如果你想要一个特定的填充方案,你应该指定它,而不是依赖默认值,尤其是当你不知道它是什么时。

标签: java security cryptography rsa padding-oracle-attack


【解决方案1】:

当您指定RSA 时,bouncy-castle 的默认值为RSA/NONE/NOPADDING

这也与RSA/ECB/NOPADDING 的结果相同。

【讨论】:

    【解决方案2】:

    这不是the first link to the cryptography site 中给出的好建议。您永远不应该依赖加密库加密算法的默认值。这有很多原因:

    1. 不同的实现,不同的默认值(对密码学提供者没有默认值的要求,尽管大多数会复制 Oracle/Sun 的默认值);
    2. 现在安全的东西明天可能不会被认为是安全的,因为为了向后兼容,您永远不能更改默认值;
    3. 阅读您的软件的任何人都不清楚默认值是什么(您可以记录它,但在这种情况下,您不妨写出来)。

    由于历史原因,Oracle 提供的SunJCEProvider 默认为 PKCS#1 填充 ("PKCS1Padding")(参见上面的原因 #2)。这没有很好的记录。

    当时设置了默认值,您基本上只有不安全的教科书 RSA ("NoPadding") 和 PKCS#1 v1.5 版本("PKCS1Padding"RSAES-PKCS1-v1_5 in the PKCS#1 v2.1 standard)。当时RSAES-PKCS1-v1_5绝对是更安全的选择。现在将默认值更改为 OAEP 会破坏所有使用默认值的 RSA 实现。

    otus 的建议(在此答案的第一个链接中)更适合库中的协议实现,而不是加密算法。 最终你应该能够捍卫所做选择的安全性,无论你选择什么。

    【讨论】:

      【解决方案3】:

      当你实例化一个 Cipher 而不完全限定它时,这取决于选择的或默认的提供者实际使用的填充:

      Cipher.getInstance("RSA")
      

      这样做是一种不好的做法,因为如果您切换 Java 实现,可能会有不同的默认值,并且突然之间,您将不再与旧的密文兼容。 始终完全限定密码。

      正如我之前所说,默认值可能(有很多提供者,不能确定)是 PKCS#1 v1.5 填充。如果您需要另一个,则必须指定它。如果你想使用 OAEP,这里是来自here 的完全限定密码字符串:

      Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
      

      【讨论】:

      • 嘿,彼此在 10 秒内发布:) 答案也很好地同步。包含 OAEP 字符串的好主意。
      • @My-Name-Is RSA 不使用 ECB 或 CBC 等操作模式。由于历史原因,它包含在字符串中,但正确的名称是 Cipher.getInstance("RSA/None/OAEPWithSHA-256AndMGF1Padding");,我相信 BouncyCastle 提供者支持:stackoverflow.com/a/23888246
      • 除此之外,密码的输出应该与随机无法区分,即使对于使用相同密钥的密码的不同调用也是如此。这就是为什么您需要一个 IV 来进行 CBC 模式加密以及 ECB 模式不安全的原因。正如 Artjom 已经指出的那样,即使在 Sun 实现中,RSA/ECB 也确实是 RSA/None。如果是 ECB,你会期望加密一个完整的明文,不管它有多大。现在你应该使用hybrid cryptosystem,除非你使用真正的小消息。
      • @My-Name-Is 它是安全的。只是不能用RSA加密任意长的数据。 RSA 只能加密小于其模数(以字节为单位)的内容。如果您有 2048 位 RSA 密钥,那么您只能加密 2048 位减去 42 字节(保留用于填充)等于 214 字节。要真正加密更大的明文,您可以使用对称密码对其进行加密,然后使用 RSA 对随机对称密钥进行加密。
      • 为了使其完整,如果您还需要完整性/真实性,您可能应该使用 SHA-256 进行 RSA-PSS 签名,然后 GCM 使用随机密钥和 IV(前缀 IV)对其进行加密,然后使用 OAEP 加密 GCM 密钥(并希望 OAEP 实现是安全的)。 RSA-KEM 也很棒,但没有在 Oracle 的 Java 中实现。不是加密的乐趣:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-22
      • 2017-10-17
      • 2023-03-18
      • 2011-07-12
      • 2020-01-08
      • 2010-10-14
      相关资源
      最近更新 更多