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

My-*_*-Is 7 java security cryptography rsa padding-oracle-attack

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

  1. 如何验证RSA加密消息的完整性?
  2. 如何使用javax.crypto.Cipher确保RSA密码的消息完整性

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

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

我不应该考虑.据我所知,RSA执行的PKCS#1 v1.5是脆弱的Padding Oracale Attack,其中原和不(假设它的正确实施)

因此,我想知道javax.crypt.CipherJava 7 使用哪种填充实现

Art*_* B. 12

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

Cipher.getInstance("RSA")
Run Code Online (Sandbox Code Playgroud)

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

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

Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
Run Code Online (Sandbox Code Playgroud)

  • @My-Name-Is RSA 不使用 ECB 或 CBC 等操作模式。由于历史原因,它包含在字符串中,但正确的名称是 `Cipher.getInstance("RSA/None/OAEPWithSHA-256AndMGF1Padding");` 我相信 BouncyCastle 提供商支持:http://stackoverflow.com/a /23888246 (2认同)
  • 除此之外,即使对于使用相同密钥的密码的不同调用,密码的输出也应该与随机无法区分.这就是为什么你需要一个用于CBC模式加密的IV以及为什么ECB模式不安全的原因.正如Artjom已经指出,即使在Sun实施中,RSA/ECB也是RSA/None.如果它是ECB,你会期望加密一个完整的纯文本,无论它有多大.现在你应该使用[混合密码系统](https://en.wikipedia.org/wiki/Hybrid_cryptosystem),除非你使用真正的小消息. (2认同)

Maa*_*wes 8

在加密站点的第一个链接中,这不是一个好建议.您永远不应该依赖加密库加密算法的默认值.这有很多原因:

  1. 不同的实现,不同的默认值(加密提供程序对默认值没有要求,尽管大多数都会复制Oracle/Sun默认值);
  2. 现在安全性可能不会被认为是安全的,因为为了向后兼容,您永远不能更改默认值;
  3. 任何人都不清楚读取你的软件的默认设置(你可以记录它,但在这种情况下你也可以把它写出来).

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

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

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