Java 使用 AES-256 和初始化向量加密
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4504280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encryption with AES-256 and the Initialization Vector
提问by MysteryMoose
I have a question relating to the use of an Initialization Vector in AES encryption. I am referencing the following articles / posts to build encryption into my program:
我有一个关于在 AES 加密中使用初始化向量的问题。我正在参考以下文章/帖子将加密构建到我的程序中:
[1] Java 256-bit AES Password-Based Encryption
[2] http://gmailassistant.sourceforge.net/src/org/freeshell/zs/common/Encryptor.java.html
[1] Java 256 位 AES 基于密码的加密
[2] http://gmailassistant.sourceforge.net/src/org/freeshell/zs/common/Encryptor.java.html
I was originally following erickson's solution from the first link but, from what I can tell, PBKDF2WithHmacSHA1 is not supported on my implementation. So, I turned to the second link to get an idea for my own iterative SHA-256 hash creation.
我最初是从第一个链接中遵循 erickson 的解决方案,但据我所知,我的实现不支持 PBKDF2WithHmacSHA1。因此,我转向第二个链接以了解我自己的迭代 SHA-256 哈希创建。
My question comes in how the IV is created. One implementation ([1]) uses methods from the Cypher class to derive the IV where are the other ([2]) uses the second 16 bytes of the hash as the IV. Quite simply, why the difference and which is better from a security standpoint? I am kinda confused to the derivation and use of IVs as well (I understand what they are used for, just not the subtler differences), so any clarification is also very welcome.
我的问题是如何创建 IV。一个实现 ([1]) 使用来自 Cypher 类的方法来派生 IV,而另一个实现 ([2]) 使用散列的后 16 个字节作为 IV。很简单,为什么会有不同,从安全的角度来看哪个更好?我对 IV 的推导和使用也有点困惑(我了解它们的用途,只是不知道更细微的差异),因此也非常欢迎任何澄清。
I noticed that the second link uses AES-128 rather than AES-256 which would suggest to me that I would have to go up to SHA-512 is I wanted to use this method. This seems like it would be an unfortunate requirement as the user's password would have to be 16 characters longer to ensure a remotely secure hash and this app is destined for a cell phone.
我注意到第二个链接使用 AES-128 而不是 AES-256,这会向我建议我必须使用 SHA-512 才能使用这种方法。这似乎是一个不幸的要求,因为用户的密码必须长 16 个字符才能确保远程安全散列,并且此应用程序用于手机。
Source is available on request, though it is still incomplete.
来源可应要求提供,但仍不完整。
Thank you in advance.
先感谢您。
采纳答案by erickson
The IV should not be generated from the password alone.
不应仅从密码生成 IV。
The point of the IV that even with the same key and plaintext is re-used, a different ciphertext will be produced. If the IV is deterministically produced from the password only, you'd get the same ciphertext every time. In the cited example, a saltis randomly chosen, so a new key is generated even with the same password.
IV 的一点是,即使重复使用相同的密钥和明文,也会产生不同的密文。如果仅根据密码确定性地生成 IV,则每次都会得到相同的密文。在引用的示例中,随机选择了一个盐,因此即使使用相同的密码也会生成新的密钥。
Just use a random number generator to choose an IV. That's what the cipher is doing internally.
只需使用随机数生成器来选择 IV。这就是密码在内部所做的事情。
I want to stress that you have to store either the IV (if you use the first method) or a salt (if you use the second method) together with the ciphertext. You won't have good security if everything is derived from the password; you need some randomness in every message.
我想强调的是,您必须将 IV(如果您使用第一种方法)或盐(如果您使用第二种方法)与密文一起存储。如果一切都来自密码,您将不会有很好的安全性;每条消息都需要一些随机性。
回答by Peter ?tibrany
My understanding is that Initialization Vector is just random input to encryption algorithm, otherwise you would always get same result for same input. Initialization Vector is stored together with cipher text, it's not secret in any way. Just use secure random function to generate initialization vector. PBKDF* algorithms are used to derive secret keys of desired length for encryption algorithms from user-entered passwords.
我的理解是初始化向量只是加密算法的随机输入,否则对于相同的输入,您总是会得到相同的结果。Initialization Vector 与密文存储在一起,它绝不是秘密的。只需使用安全随机函数来生成初始化向量。PBKDF* 算法用于从用户输入的密码中导出加密算法所需长度的密钥。
First implementation that you link to simply lets Cipher object to generate Initialization Vector. Then it fetches this generated IV to store it together with cipher text.
您链接到的第一个实现只是让 Cipher 对象生成初始化向量。然后它获取这个生成的 IV 以将它与密文存储在一起。
Second one uses part of hash bytes. Any approach that generates non-repeating IVs is good enough.
第二个使用哈希字节的一部分。任何生成非重复 IV 的方法都足够好。
Most important property of IV is that it doesn't repeat (very often).
IV 最重要的特性是它不重复(非常频繁)。
回答by Rob
The IV is just a consequence of the use of block chaining. I presume that this is more than a simple API design question. I assume that you know that the reasoning for using it is so that the same plaintext will not show up as the same ciphertext in multiple blocks.
IV 只是使用区块链的结果。我认为这不仅仅是一个简单的 API 设计问题。我假设您知道使用它的原因是相同的明文不会在多个块中显示为相同的密文。
Think about recursion from the last block where the Nth ciphertext block depends in some way on the (N-1)th block, etc. When you get to the first block, 0th block, you need some data to get started. It doesn't matter what that data is as long as you know it before you attempt to decrypt. Using non-secret random data as an initialization vector will cause identical messages encrypted under the same key to come out as completely different ciphertext.
考虑从最后一个块开始递归,其中第 N 个密文块以某种方式依赖于第 (N-1) 个块等。当您到达第一个块,第 0 个块时,您需要一些数据才能开始。只要您在尝试解密之前知道该数据是什么并不重要。使用非秘密随机数据作为初始化向量会导致使用相同密钥加密的相同消息作为完全不同的密文出现。
It's similar in concept to salting a hash. And that source code looks a little fishy to me. An IV should simply be fresh-at-encryption-timerandom bits dependent upon nothing, like a nonce. The IV is basically part of the encrypted message. If you re-encrypt identical data with identical key, you should not be able to correlate the messages. (Hey, think about the consequences of correlating by ciphertext length as well.)
它在概念上类似于对哈希加盐。那个源代码对我来说有点可疑。IV 应该只是加密时新鲜的随机位,不依赖任何东西,例如随机数。IV基本上是加密消息的一部分。如果您使用相同的密钥重新加密相同的数据,您应该无法关联消息。(嘿,想想通过密文长度关联的后果。)
回答by Spike Gronim
Cryptographers should generate IVs using a secure pseudo-random random number generator.
密码学家应该使用安全的伪随机随机数生成器来生成 IV。
Application developers should use existing, off the shelf cryptography. I suggest that you use SSL with certificates to secure your network traffic and GPG to secure file data.
应用程序开发人员应该使用现有的、现成的密码学。我建议您使用带有证书的 SSL 来保护您的网络流量,并使用 GPG 来保护文件数据。
There are so many details that can make an implementation insecure, such as timing attacks. When an application developer is making decisions between AES 128 and AES 256 it is nearly always pointless since you've likely left a timing attack that renders the extra key bits useless.
有很多细节会使实现变得不安全,例如时序攻击。当应用程序开发人员在 AES 128 和 AES 256 之间做出决定时,这几乎总是毫无意义的,因为您可能留下了使额外密钥位无用的时序攻击。
回答by AltF4
As with everyone else here, I've always known IVs to be just chosen randomly using the standard algorithms for doing so.
和这里的其他人一样,我一直都知道 IV 只是使用标准算法随机选择的。
The second reference you provided, though, doesn't seem to be doing that. Looks like he salts a password and hashes it. Then takes that hash and splits it up into halves. One half is the encryption key, one is the IV. So the IV is derived from the password.
但是,您提供的第二个参考文献似乎没有这样做。看起来他对密码加盐并对其进行哈希处理。然后获取该哈希并将其分成两半。一半是加密密钥,一半是 IV。所以IV是从密码派生出来的。
I don't have any strong breaks for such a method, but it's bad design. The IV should be independent and random all on its own. Maybe if there's a weakness in the hashing algorithm or if you choose a weak password. You don't want to be able to derive the IV from anything else or it's conceivable to launch pre-computation attacks.
对于这种方法,我没有任何强烈的突破,但它的设计很糟糕。IV 应该是独立且随机的。也许如果散列算法存在弱点,或者您选择了弱密码。您不希望能够从其他任何东西中推导出 IV,或者可以想象发起预计算攻击。