加密(模式和填充)

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

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

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

Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); 

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

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

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

您永远不应指望用户为您做出安全决策,除非唯一的用户是密码学的学生(并了解上述攻击)。 一般而言,安全性不应过分依赖于教育用户。

就个人而言,我当然会问请求者有关填充的问题。 您还应该检查他们是否期望对称加密的身份validation(MAC,HMAC,经过身份validation的密码或签名)。 如果他/她无法回答问题,他们可能对加密知之甚少。

我目前不会认为你的要求是完整的(虽然“出于学习目的”可能是一个借口)。

笔记

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

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

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

您不希望向用户询问填充或阻止模式。 我认为你需要做的是:

生成随机的256位密钥(确保使用加密库来执行此操作,并且播种良好)

使用带有密钥的AES256加密文件(如果你想略微隐藏文件的确切长度,请不要使用ECB,使用CBC并可能填充)

使用RSA-2048加密密钥(这里从安全的角度来看块模式是无关紧要的,因为密钥小于一个块,因为密钥是已知长度的填充。我会使用ECB)

您的协议不保证谁发送文件或文件的完整性。 考虑签名,这一点非常重要。

不幸的是,当实现与加密有关的任何事情时,你极有可能出错。 绝对使用Java库,如果您能找到更接近您想要的更高级别的可信库,请考虑使用它们。