javax.crypto.KeyGenerator 是否使用 /random 或 /urandom 生成密钥?
Does javax.crypto.KeyGenerator uses /random or /urandom to generate keys?
考虑以下代码片段,我在其中使用 AES-256 生成密钥进行加密 - 运行以下代码片段被阻止的线程。我怀疑这是否可能是由于未达到足够熵的问题。因此,线程可以暂停(或)看起来挂起,直到系统收集到足够的熵。
我 运行 这是在虚拟机上而不是在物理机上,我正在使用 Java8。
片段 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
阻塞的线程吗?
最终,随机数生成器将始终依赖于操作系统的熵源,即使只是为了播种;毕竟从非随机环境中生成随机数是不可能的。
我可以想象,熵源数量有限的 VM 很难填满条目池,即使只有一次。解决此问题的最佳方法是确保您的 VM 安装了最新的客户端。这些可以/应该使主机 RNG 可用于客户端计算机。
可以创建一个 SecureRandom
实例并将其作为参数传递给各种 init()
方法。但是,这并不能解决一开始就阻止它的问题,而且它会不必要地使代码复杂化。最后,您永远不会知道哪个库或模块仍在实例化另一个 SecureRandom
实例。
所以我会专注于修复客户端 VM 的 RNG 而不是 Java 代码。
注意 NativePRNG
直接使用 OS RNG;它不使用 "SHA1PRNG"
。 SecureRandom()
使用包含 class 实现的第一个提供者;如果使用默认 PRNG,请确保您没有包含具有慢 PRNG 的提供程序。
考虑以下代码片段,我在其中使用 AES-256 生成密钥进行加密 - 运行以下代码片段被阻止的线程。我怀疑这是否可能是由于未达到足够熵的问题。因此,线程可以暂停(或)看起来挂起,直到系统收集到足够的熵。
我 运行 这是在虚拟机上而不是在物理机上,我正在使用 Java8。
片段 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
阻塞的线程吗?
最终,随机数生成器将始终依赖于操作系统的熵源,即使只是为了播种;毕竟从非随机环境中生成随机数是不可能的。
我可以想象,熵源数量有限的 VM 很难填满条目池,即使只有一次。解决此问题的最佳方法是确保您的 VM 安装了最新的客户端。这些可以/应该使主机 RNG 可用于客户端计算机。
可以创建一个 SecureRandom
实例并将其作为参数传递给各种 init()
方法。但是,这并不能解决一开始就阻止它的问题,而且它会不必要地使代码复杂化。最后,您永远不会知道哪个库或模块仍在实例化另一个 SecureRandom
实例。
所以我会专注于修复客户端 VM 的 RNG 而不是 Java 代码。
注意 NativePRNG
直接使用 OS RNG;它不使用 "SHA1PRNG"
。 SecureRandom()
使用包含 class 实现的第一个提供者;如果使用默认 PRNG,请确保您没有包含具有慢 PRNG 的提供程序。