7

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

    }
}
4

2 回答 2

8

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

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

于 2014-01-02T18:05:34.493 回答
1

正如其他用户所说,这取决于 JCE 提供者。如果您没有指定,Java SE会为您生成一个随机 IV。

只有Android 1和 Javacard API 使用空白 IV,这不符合 Java Crypto 规范,该规范指出

如果此密码需要任何不能从给定的算法参数,key则底层密码实现应该自己生成所需的参数(使用特定于提供程序的默认值或随机值),如果它正在初始化以进行加密或密钥包装,并引发一个InvalidKeyException它是否正在为解密或密钥解包而初始化。可以使用getParametersor检索生成getIV的参数(如果参数是IV)。

如果你没有指定 IV,在 Java SE 中你会得到一个随机的,并且需要用它来检索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 风格的广告一样。只是猜测,仅此而已。

于 2018-10-18T15:42:26.377 回答