我正在编写一个简单的应用程序来使用AES / CBC(模式)加密我的消息。由于我的理解CBC模式需要IV参数,但我不知道为什么我的代码工作没有使用IV参数。有谁能解释为什么?谢谢。
打印的加密消息: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();
}
}
}
当它在没有IV的情况下使用时,对于某些类型的密码,包括AES,它隐含地使用0 IV。请参阅密码类documentation。
null IV(或确定性IV)的缺点是它易受字典攻击。 IV的要求是防止同一个纯文本块每次产生相同的密文。
像其他用户所说,这取决于JCE提供商。如果您指定none,Java SE会为您生成随机IV。
只有Android1和Javacard API使用空白IV,这不符合Java Crypto规范,which states:
如果此密码需要任何无法从给定的
key
派生的算法参数,则底层密码实现应该自行生成所需的参数(使用特定于提供程序的默认值或随机值),如果它正在初始化以进行加密或密钥包装,并且如果正在初始化解密或密钥解包,则引发InvalidKeyException
。可以使用getParameters
或getIV
检索生成的参数(如果参数是IV)。
如果你没有指定IV,在Java SE中你会得到一个随机的IV,并且需要使用cipher.getIV()
检索它并存储它,因为解密需要它。
但更好的是,自己生成一个随机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());
1这可能是因为Android是Java风格的,就像Eminem-esque广告一样。只是猜测,就是这样。