Java AES/CBC 真的需要 IV 参数吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20888851/
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
Does AES/CBC really requires IV parameter?
提问by
I am writing a simple app to encrypt my message using AES / CBC (mode). As my understanding CBC mode requires IV parameter but I don't know why my code work without IV parameter used. Anyone can explain why? Thanks.
我正在编写一个简单的应用程序来使用 AES / CBC(模式)加密我的消息。据我了解,CBC 模式需要 IV 参数,但我不知道为什么我的代码在没有使用 IV 参数的情况下工作。任何人都可以解释为什么?谢谢。
The encrypted message printed: T9KdWxVZ5xStaisXn6llfg== without exception.
打印的加密消息:T9KdWxVZ5xStaisXn6llfg== 无一例外。
public class TestAES {
public static void main(String[] args) {
try {
byte[] salt = new byte[8];
new SecureRandom().nextBytes(salt);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec("myPassword".toCharArray(), salt, 100, 128);
SecretKey tmp = keyFactory.generateSecret(keySpec);
SecretKeySpec key = new SecretKeySpec(tmp.getEncoded(), "AES");
Cipher enCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
enCipher.init(Cipher.ENCRYPT_MODE, key);
// enCipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
byte[] cipherBytes = enCipher.doFinal("myMessage".getBytes());
String cipherMsg = BaseEncoding.base64().encode(cipherBytes);
System.out.println("Encrypted message: " + cipherMsg);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
采纳答案by bgamlath
When it is used without an IV, for certain types of ciphers including AES, it implicitly uses 0 IV. See Cipher class documentation.
当它在没有 IV 的情况下使用时,对于包括 AES 在内的某些类型的密码,它隐式使用 0 IV。请参阅密码类文档。
The disadvantage of a null IV (or a deterministic IV) is that it is vulnerable to dictionary attacks. The requirement for IV is to prevent the same plain text block producing the same cipher text every time.
空 IV(或确定性 IV)的缺点是它容易受到字典攻击。IV 的要求是防止相同的明文块每次都产生相同的密文。
回答by rustyx
Like other users have said, it depends on the JCE provider. Java SEgenerates a random IV for you if you specify none.
正如其他用户所说,这取决于 JCE 提供者。如果您指定 none,Java SE 会为您生成一个随机 IV。
Only Android1and Javacard API use a blank IV, which is non-conforming to the Java Crypto spec, which states:
只有Android 1和 Javacard API 使用空白 IV,这不符合 Java Crypto 规范,其中指出:
If this cipher requires any algorithm parameters that cannot be derived from the given
key
, the underlying cipher implementation is supposed to generatethe required parameters itself (using provider-specific default or random values) if it is being initialized for encryption or key wrapping, and raise anInvalidKeyException
if it is being initialized for decryption or key unwrapping. The generated parameters can be retrieved usinggetParameters
orgetIV
(if the parameter is an IV).
如果此密码需要任何无法从给定 派生的算法参数
key
,则底层密码实现应该自己生成所需的参数(使用特定于提供者的默认值或随机值),如果它正在被初始化以进行加密或密钥包装,并引发aInvalidKeyException
如果它正在被初始化以进行解密或密钥解包。可以使用getParameters
or检索生成的参数getIV
(如果参数是IV)。
If you do not specify the IV, in Java SE you get a random one, and will need to retrieve it with cipher.getIV()
and store it, as it will be needed for decryption.
如果您不指定 IV,在 Java SE 中您会得到一个随机的,并且需要检索它cipher.getIV()
并存储它,因为解密需要它。
But better yet, generate a random IV yourself and provide it via IvParameterSpec
.
但更好的是,自己生成一个随机 IV 并通过IvParameterSpec
.
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecureRandom rnd = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
rnd.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), ivParams);
byte[] ciphertext = cipher.doFinal(input.getBytes());
1That could be because Android is Java-esque, like the Eminem-esquead. Just guessing, that's all.
1这可能是因为 Android 是Java 风格的,就像Eminem 风格的广告一样。只是猜测,仅此而已。