Android加密API无法为AES生成安全IV

时间:2015-06-24 20:50:14

标签: java android encryption

我使用javax.crypto在我的应用程序中执行一些加密操作。我使用AES进行加密/解密,如下所示:

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
cipher.init(Cipher.ENCRYPT_MODE, keySpec);
byte[] cipherText = cipher.doFinal(plaintext);
byte[] iv = cipher.getIV();   //The problematic IV

在加密后,生成的IV被添加到密文之前。

Java规范明确指出,如果未向cipher.init()提供IV,则必须自动生成IV:

  

如果此密码需要任何无法从给定密钥派生的算法参数,则底层密码实现应该自己生成所需的参数(使用特定于提供程序的默认值或随机值)

但有时我最终会得到一些看似非常随机的密文,例如这个(在base64中):

    AAAAAAAAAAAAAAAAAAAAAOmI9Qh1fMiG6HV3tKZK3q5sCruaPdYqYnoUOM00rs6YZY3EvecYfR6vTHzZqk7ugknR9ZMipedYWJB1YOLmSYg=

前面的A个字符串是IV。 IV实际上是16个零字节。

大多数情况下,库会生成适当的随机IV,但有时候,它会弹出零。为什么会这样?

2 个答案:

答案 0 :(得分:2)

有些(大多数?)提供商只使用零字节填充IV作为默认值。我强调你的引言:

  

如果此密码需要任何无法从给定密钥派生的算法参数,则底层密码实现应自行生成所需参数(使用特定于提供程序的默认值或随机值)

当你看到密文的正面时,你会看到它以一堆" A"开头。字符。它的基数为64,为0x00字节。

如果你想确保你有一个随机的IV,你必须自己生成它:

plot(augPred(fm1, length.out = 2, level = c(0,1)),
    par.settings = list(superpose.line = list(col = c("red", "blue"), lwd = 2),
                    plot.symbol = list(pch = NA)))

答案 1 :(得分:-2)

IV不安全。它被添加到密文之前,因此任何攻击者只需要读取密文并查看前16个字节以查看它是什么。

始终使用相同的IV并不是一个好主意 - 它有效地将实际密文的第一个块转换为ECB模式,这是不安全的。

我建议您自己生成随机IV。您无需使用加密安全的RNG,因为攻击者无论如何都可以看到它。您只需要避免对不同的消息使用相同的IV。即使像8字节(64位)计数器那样简单的8字节随机数也足以避免ECB效应。在计数器翻转之前更改密钥,并在更改密钥时将计数器重置为0.