javax.crypto.Cipher 为 RSA 使用了哪个填充

Which padding is used by javax.crypto.Cipher for RSA

我需要通过 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

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

However, since you are using a high level cryptographic library, this is something you shouldn't have to worry about. The writers of that library should have taken care of it.

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

因此我想知道 Java 7

javax.crypt.Cipher 使用了哪种填充实现

这取决于选择的或默认的提供程序,当您实例化一个 Cipher 而没有完全限定它时实际使用哪个填充,例如:

Cipher.getInstance("RSA")

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

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

的完全限定密码字符串
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");

这不是 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 的建议(在这个答案的第一个 link 中)比加密算法更适合 库中的协议实现 最终,无论您选择什么,您都应该能够捍卫所做选择的安全性。

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

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