加密(模式和填充)

use*_*403 5 java encryption cryptography public-key-encryption

我的任务是编写一个涉及加密的小型Java控制台应用程序.我不熟悉加密,所以我必须先做一些阅读.到目前为止,给出的高级要求是AES-256应该用于生成一次性密钥来加密文件.

之后,应使用收件人的公钥(RSA-2048)来加密该AES-256一次性密钥.然后,加密文件和加密的一次性AES-256密钥将被压缩并发送给收件人.

根据我对读取加密和解密的理解,除了算法(RSA,AES等)之外,还有称为模式和填充的东西.例如,以下代码将RSA指定为算法,ECB模式和PKCS1Padding.

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
Run Code Online (Sandbox Code Playgroud)

在加密和解密中必须使用相同的算法,模式和填充.因此,我可以向用户询问他们想要的模式和填充是否合理?

我注意到Cipher cipher = Cipher.getInstance("RSA")似乎使用了ECB的默认模式和PKCS1Padding的填充,因此这行代码与上面相同.那么可以假设ECB模式和PKCS1Padding模式将默认用于RSA-2048吗?

Maa*_*wes 3

不,要发送消息,您应该使用较新的 OAEP 方案,因为带有 PKCS#1 v1.5 的 RSA 可能容易受到Bleichenbacher 攻击。然而,请求 RSA 混合加密的人很可能甚至从未听说过这种攻击。一般来说,PKCS#1 v1.5 填充仍然用作默认值。

您永远不应该期望用户为您做出安全决策,除非唯一的用户是密码学的学生(并且了解上述攻击)。一般来说,安全不应过多依赖于对用户的教育。

就我个人而言,我肯定会询问请求者有关填充的问题。您还应该检查他们是否期望对称加密的身份验证(MAC、HMAC、经过身份验证的密码或签名)。如果他/她无法回答这个问题,他们可能不太了解加密。

我目前不认为您所提出的要求是完整的(尽管“出于学习目的”可能是一个很好的借口)。

笔记

"RSA/ECB/PKCS1Padding"实际上并没有实现ECB模式加密。它应该被调用"RSA/None/PKCS1Padding",因为它只能用于加密单个明文块(或者实际上是一个秘密密钥)。这只是Sun/Oracle的一个命名错误。

还有一种称为 RSA-KEM 的混合加密模式,应该至少与 RSA OAEP 一样安全,但它尚未在 Java SE 中实现。

AES-256 本身不应该用于“生成一次性密钥”。您应该使用生成 AES-256 一次性密钥的实例KeyGenerator(这可能有点命名混乱,因为它KeyGenerator本身不使用AES,而是AES创建密钥)。