我需要通过RSA解密消息,以便通过不安全的通道发送消息,但我害怕填充Oracle攻击。因此,我已经问了以下问题:
- 如何验证RSA加密消息的完整性?
- 如何使用javax.crypto.Cipher保证RSA密码的消息完整性
如第一个问题所建议的,
我不应该考虑。据我所知,然而,由于您使用的是高级加密库,因此您不应该担心这个问题。那个库的作者应该注意到这一点。
PKCS#1 v1.5
的RSA实现容易受到Padding Oracale Attack
的攻击,而OAEP则不会(假设它实现正确)
因此我想知道Java 7
javax.crypt.Cipher
使用的填充实现这取决于所选择的或默认的提供程序,当您实例化Cipher时实际使用的填充,而不完全限定它,如:
Cipher.getInstance("RSA")
这样做是一个不好的做法,因为如果您切换Java实现,可能会有不同的默认值,并且突然之间,您将不再与旧的密文兼容。总是完全限定密码
正如我之前所说,默认值可能是pkcs# 1 v1.5填充(有许多提供程序,无法确定)。如果您需要另一个,则必须指定它。如果您想使用OAEP,这里有一个完全限定的密码字符串:
Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
在加密站点的第一个链接中给出的建议不太好。永远不要依赖默认的加密库加密算法。这有很多原因:
- 不同的实现,不同的默认值(没有要求加密提供商关于默认值,尽管大多数会复制Oracle/Sun默认值);
- 现在安全的东西可能明天就不安全了,因为向后兼容,你永远不能改变默认值;
- 阅读你的软件的任何人都不清楚默认值是什么(你可以记录它,但在这种情况下,你不妨把它写出来)。
由于历史原因,Oracle提供的SunJCEProvider
默认为pkcs# 1填充("PKCS1Padding"
)(参见上面的原因#2)。
在那个时候,默认设置基本上只有不安全的教科书RSA ("NoPadding"
)和pkcs# 1 v1.5版本(pkcs# 1 v2.1标准中的"PKCS1Padding"
或RSAES-PKCS1-v1_5
)。当时RSAES-PKCS1-v1_5
绝对是更安全的选择。现在将默认值更改为OAEP将破坏所有使用默认值的RSA实现。
当您指定RSA
时,弹力城堡的默认值是RSA/NONE/NOPADDING
这与RSA/ECB/NOPADDING
的结果相同