我使用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,但有时候,它会弹出零。为什么会这样?
答案 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.