在Java中为AES生成随机IV

16

我正在为Android实现一个用于PBE的AES加密引擎,我发现有两种方法可以实现IV的创建,我想知道哪一种更好、更安全,以获得 IvParameterSpec:

方法 #1:

SecureRandom randomSecureRandom = SecureRandom.getInstance("SHA1PRNG");
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);

IvParameterSpec ivParams = new IvParameterSpec(iv);

方法二:

AlgorithmParameters params = cipher.getParameters();
byte[] iv2 = params.getParameterSpec(IvParameterSpec.class).getIV();

ivParams = new IvParameterSpec(iv2);
1个回答

22

我会选择方法#1,因为Java API对只需要加密/解密模式和密钥的 API做出了以下规定:

 

如果此密码实例需要任何算法参数或指定密钥无法提供的随机值,则该密码的底层实现应生成所需参数(使用其提供程序随机值)。

(强调部分是我的。)

因此,当选择方法2时,不清楚不同的提供程序将执行什么操作。查看Android源代码,似乎至少一些版本(包括版本21?)不会创建随机IV - 随机IV创建被注释掉了。

在我看来,方法1更透明,更容易理解。


请注意,最好使用new SecureRandom(),并让系统确定最佳的RNG。"SHA1PRNG"未定义清晰,可能因实现而异,并且已知在Android上存在实现缺陷,尤其是


因此,最终结果应该是这样的:

SecureRandom randomSecureRandom = new SecureRandom();
byte[] iv = new byte[cipher.getBlockSize()];
randomSecureRandom.nextBytes(iv);
IvParameterSpec ivParams = new IvParameterSpec(iv);
请注意,与AES块大小16字节相比,使用12字节IV的GCM模式效果更佳。

这个答案是否需要更新以适应Java 8 - kelalaka
@kelalaka 其实不用太担心, 使用默认的 RNG 应该是没问题的。你是不是有什么其它意思?顺便说一句,Java 的后续版本甚至有了 NIST DRBG 实现,所以可以选择更多的选项,并且我认为这些选项更加安全。但即使如此,选择默认选项应该是没问题的,特别是如果我们只谈论 IV 的话。 - Maarten Bodewes
不,只是谈论一般选择的更新。是的,对于IV来说应该足够了。 - kelalaka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接