15

我正在为 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);

方法#2:

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

ivParams = new IvParameterSpec(iv2);
4

1 回答 1

19

我会使用方法 #1Cipher.init() ,因为 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);

请注意,GCM 模式最适合 12 字节 IV 而不是 16 字节 IV - AES 的块大小。

于 2015-03-25T22:39:46.250 回答