Does AES/CBC really requires IV parameter?

蹲街弑〆低调 提交于 2019-12-21 04:59:05

问题


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.

The encrypted message printed: T9KdWxVZ5xStaisXn6llfg== without exception.

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();
    }

}
}

回答1:


When it is used without an IV, for certain types of ciphers including AES, it implicitly uses 0 IV. See Cipher class documentation.

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.




回答2:


Like other users have said, it depends on the JCE provider. Java SE generates a random IV for you if you specify none.

Only Android1 and Javacard API use a blank IV, which is non-conforming to the Java Crypto spec, which states:

If this cipher requires any algorithm parameters that cannot be derived from the given key, the underlying cipher implementation is supposed to generate the required parameters itself (using provider-specific default or random values) if it is being initialized for encryption or key wrapping, and raise an InvalidKeyException if it is being initialized for decryption or key unwrapping. The generated parameters can be retrieved using getParameters or getIV (if the parameter is an 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.

But better yet, generate a random IV yourself and provide it via 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-esque ad. Just guessing, that's all.



来源:https://stackoverflow.com/questions/20888851/does-aes-cbc-really-requires-iv-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!