javax.crypto.KeyGenerator是否使用/ random或/ urandom来生成密钥?

时间:2018-01-06 16:33:39

标签: java random cryptography virtual-machine entropy

考虑以下代码片段,我使用AES-256生成加密密钥 - 运行以下代码段的线程被阻止。我怀疑这是否是由于没有达到足够的熵的问题。因此,线程可以暂停(或)看起来悬挂,直到系统收集到足够的熵。

我在虚拟机上运行它,而不是在物理机器上运行,我使用的是Java8。

SNIPPET A

KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey key = keyGen.generateKey();

以下article推断SecureRandom实例获取时为

SecureRandom secureRandom = new SecureRandom();

默认情况下用于生成熵的NativePRNG算法称为SHA1PRNG,默认情况下使用/dev/urandom,因此不会发生线程阻塞。

我会说到为什么我要谈论这些东西。这条线

keyGen.init(256);
上面代码段中的

在内部执行以下操作。

 public final void init(int paramInt) {
     init(paramInt, JceSecurity.RANDOM);
 }

这个JceSecurity.RANDOM的含义是这个

static final SecureRandom RANDOM = new SecureRandom();

意味着它应该使用/dev/urandom,并且在未收集熵时不应该阻止(或)挂起。

我在这里分享我的java.security文件。

有人可以透露一下运行SNIPPET A块的上述线程的原因吗?

1 个答案:

答案 0 :(得分:1)

最后,随机数发生器将始终依赖于操作系统的熵源,如果仅用于播种;毕竟,从非随机环境中生成随机数是不可能的。

我可以想象,如果只有一次,具有有限数量的熵源的VM无法填充入口池。解决此问题的最佳方法是确保您的VM安装了最新的客户端添加项。那些可以/应该使主机RNG可用于客户机。

可以创建一个SecureRandom实例并将其作为参数传递给各种init()方法。但是,这不会解决在开始时阻止它,并且它会使代码变得不必要地复杂化。最后,您永远不会知道哪个库或模块仍然实例化另一个SecureRandom实例。

所以我专注于修复客户端VM的RNG而不是Java代码。

请注意NativePRNG直接使用OS RNG;它不使用"SHA1PRNG"SecureRandom()使用包含类实现的第一个提供程序;如果使用默认PRNG,请确保您没有包含PRNG缓慢的提供商。