我有一个关于在AES加密中使用初始化向量的问题。我正在引用以下文章/帖子来为我的程序构建加密:
[1] Java 256-bit AES Password-Based Encryption
[2] http://gmailassistant.sourceforge.net/src/org/freeshell/zs/common/Encryptor.java.html
我最初是从第一个链接开始关注erickson的解决方案,但据我所知,我的实现不支持PBKDF2WithHmacSHA1。所以,我转向第二个链接,以了解我自己的迭代SHA-256哈希创建。
我的问题是如何创建IV。一个实现([1])使用Cypher类中的方法来导出IV,而另一个([2])使用散列的第二个16字节作为IV。很简单,为什么差异从安全的角度来看哪个更好?我对IV的推导和使用感到困惑(我理解它们的用途,而不是更微妙的差异),所以任何澄清都是非常受欢迎的。
我注意到第二个链接使用的是AES-128而不是AES-256,这对我来说,我必须要使用SHA-512才能使用这种方法。这似乎是一个不幸的要求,因为用户的密码必须长16个字符才能确保远程安全哈希并且这个应用程序的目的地是手机。
可根据要求提供来源,但仍然不完整。
提前谢谢。
答案 0 :(得分:28)
不应仅从密码生成IV。
即使重复使用相同的密钥和明文,IV的点也将产生不同的密文。如果仅通过密码确定性地生成IV,则每次都会得到相同的密文。在引用的示例中,随机选择 salt ,因此即使使用相同的密码也会生成新密钥。
只需使用随机数生成器来选择IV。这就是密码在内部的作用。
我想强调你必须将IV(如果使用第一种方法)或盐(如果使用第二种方法)与密文一起存储。如果一切都来自密码,您将无法获得良好的安全性;你需要在每条消息中都有一些随机性。
答案 1 :(得分:4)
我的理解是初始化向量只是加密算法的随机输入,否则对于相同的输入总是会得到相同的结果。初始化向量与密文一起存储,它不以任何方式保密。只需使用安全随机函数生成初始化向量。 PBKDF *算法用于从用户输入的密码中为加密算法导出所需长度的密钥。
您链接的第一个实现只是让Cipher对象生成初始化向量。然后它获取生成的IV以将其与密文一起存储。
第二个使用部分哈希字节。任何产生非重复IV的方法都足够好。
IV最重要的属性是它不会重复(经常)。
答案 2 :(得分:4)
密码学家应使用安全的伪随机数生成器生成IV。
应用程序开发人员应使用现有的现成密码术。我建议您使用SSL和证书来保护您的网络流量,并使用GPG来保护文件数据。
有很多细节可以使实施不安全,例如timing attacks。当应用程序开发人员在AES 128和AES 256之间做出决策时,几乎总是没有意义,因为你可能会留下一个定时攻击,使额外的密钥位变得无用。
答案 3 :(得分:1)
IV只是使用块链的结果。我认为这不仅仅是一个简单的API设计问题。我假设您知道使用它的原因是相同的明文不会在多个块中显示为相同的密文。
考虑来自最后一个块的递归,其中第N个密文块以某种方式依赖于第(N-1)个块等。当你到达第一个块,第0个块时,你需要一些数据才能开始。只要您在尝试解密之前知道该数据,这并不重要。使用非秘密随机数据作为初始化向量将导致在相同密钥下加密的相同消息作为完全不同的密文出现。
它在概念上与盐析哈希相似。这个源代码看起来有点可疑。 IV应该只是 fresh-at-encryption-time 随机位依赖于什么,就像nonce一样。 IV基本上是加密消息的一部分。如果使用相同的密钥重新加密相同的数据,则无法关联消息。 (嘿,考虑通过密文长度关联的后果。)
答案 4 :(得分:1)
与其他所有人一样,我一直都知道IV只是随机使用标准算法来选择。
但是,您提供的第二个参考资料似乎并没有这样做。看起来他给密码加密并对其进行哈希处理。然后获取该哈希并将其分成两半。一半是加密密钥,一个是IV。因此IV来自密码。
我对这种方法没有任何强烈的休息,但这是糟糕的设计。 IV应该是独立的,随机的。也许如果哈希算法存在弱点或者您选择了弱密码。您不希望能够从其他任何东西派生IV,或者可以想象发动预计算攻击。