AES / CBC真的需要IV参数吗?

时间:2014-01-02 17:58:57

标签: java aes password-encryption cbc-mode

我正在编写一个简单的应用程序来使用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();
    }

}
}

2 个答案:

答案 0 :(得分:5)

当它在没有IV的情况下使用时,对于包括AES在内的某些类型的密码,它隐含地使用0 IV。请参阅密码类documentation

null IV(或确定性IV)的缺点是它容易受到字典攻击。 IV的要求是防止同一个纯文本块每次产生相同的密文。

答案 1 :(得分:0)

就像其他用户所说的那样,这取决于JCE提供程序。如果未指定, Java SE 会为您生成随机IV。

只有 Android 1 和Javacard API使用空白的IV,它与Java Crypto规范which states不符:

  

如果此密码需要任何不能从给定key派生的算法参数,则基础密码实现应自行生成所需的参数(使用提供商特定的默认值或随机值)值)(如果正在初始化以进行加密或密钥包装),如果正在初始化以进行解密或密钥解包,则引发InvalidKeyException。可以使用getParametersgetIV(如果参数是 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 广告一样。只是猜测,仅此而已。