javax.crypto.Cipher 为 RSA 使用了哪个填充
Which padding is used by javax.crypto.Cipher for RSA
我需要通过 RSA 解密消息以便通过不安全的通道发送消息,但我害怕 Padding Oracle Attack。因此我已经提出了以下问题:
- How to verify the integrity of RSA encrypted messages?
- 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 中给出的好建议。您永远不应该依赖密码库密码算法的默认值。这有很多原因:
- 不同的实现,不同的默认值(对密码学提供者没有关于默认值的要求,尽管大多数会复制 Oracle/Sun 默认值);
- 现在安全的东西明天可能就不安全了,因为为了向后兼容,您永远无法更改默认设置;
- 任何阅读您软件的人都不清楚默认值是什么(您可以将其记录下来,但在那种情况下,您最好将其写出来)。
由于历史原因,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
的结果相同。
我需要通过 RSA 解密消息以便通过不安全的通道发送消息,但我害怕 Padding Oracle Attack。因此我已经提出了以下问题:
- How to verify the integrity of RSA encrypted messages?
- 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 中给出的好建议。您永远不应该依赖密码库密码算法的默认值。这有很多原因:
- 不同的实现,不同的默认值(对密码学提供者没有关于默认值的要求,尽管大多数会复制 Oracle/Sun 默认值);
- 现在安全的东西明天可能就不安全了,因为为了向后兼容,您永远无法更改默认设置;
- 任何阅读您软件的人都不清楚默认值是什么(您可以将其记录下来,但在那种情况下,您最好将其写出来)。
由于历史原因,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
的结果相同。