java - 创建 "good"SecureRandom 的最佳方法是什么?

标签 java security random-seed java-security secure-random

有很多问题询问 SecureRandom 的特定启动是否“好”,但我找不到经验法则。

创建“好的”随机 SecureRandom 的最佳方法是什么?

// Fast
// Is it a good random?
SecureRandom secureRandom = new SecureRandom()?

// Freezes for a few seconds after being used several times - until getting a random enough seed.
// See http://stackoverflow.com/questions/137212/how-to-solve-performance-problem-with-java-securerandom#comment68934647_137212
// Is it a good random?
SecureRandom secureRandom = new SecureRandom(SecureRandom.getSeed(20))?

// Freezes for a very long time. Waited minutes and still no return :(
SecureRandom secureRandom = new SecureRandom.getInstanceStrong()?

Other?

最佳答案

基本上,最好的答案是:你不知道。您最好将选择权留给专家并使用 new SecureRandom() .这将检索具有最高优先级的提供者的第一个随机数生成器。
存在哪些提供程序以及哪个提供程序具有优先级取决于运行时(IBM 和 Android 也有与 Java 兼容的运行时)。运行时配置也可能因操作系统而异,即使对于标准 JDK。
在虚拟机上,您应该安装特定 VM 管理器的操作系统特定客户端工具集;这通常允许客户端操作系统从主机操作系统播种。 SecureRandom通常取决于主机提供种子甚至随机数据。但是,如果主机无法成功地为自己设定种子,那么 Java 运行时也将无法进行,并且在虚拟主机上创建的“随机数据”可能会重复。
来自 the JCA documentation :

All Java SE implementations provide a default SecureRandom using the no-argument constructor: new SecureRandom(). This constructor traverses the list of registered security providers, starting with the most preferred provider, then returns a new SecureRandom object from the first provider that supports a SecureRandom random number generator (RNG) algorithm. If none of the providers support a RNG algorithm, then it returns a SecureRandom object that uses SHA1PRNG from the SUN provider.



绝对不需要自己“播种”算法。调用 getSeed()将尝试从运行时检索种子。这可能会耗尽随机池,就像 getInstanceStrong() ,导致您的应用程序和可能的其他应用程序的块,直到熵可用。 SecureRandom如果您不提供种子,则实现将自行播种 - 希望以最好的方式进行。请注意,在大多数(现代)实现中,提供的种子混合到随机池中,最初由例如操作系统;你应该不是 假设提供相同种子的两个实例将生成相同的随机序列,即使在测试期间也不行,即使您明确指定 "SHA1PRNG" 也不行。 .
如果使用 new SecureRandom()导致阻塞,那么您需要确保您的应用程序不使用 /dev/random直接消耗熵池。如果没有,并且仍然阻塞,则 /dev/random可能是行为不端。

要检索长期 key Material ,您还可以使用 SecureRandom.getInstanceStrong() .不过,您通常不应该使用它; SecureRandom对于大多数用例来说应该足够强大。如果您使用 getInstanceStrong()方法可能会耗尽操作系统的熵池。

最好不要使用 "SHA1PRNG" .即使所有运行时都有一个实现,it is not an implementation requirement :

[1] No specific Configuration type, Policy type or SecureRandom algorithm is required; however, an implementation-specific default must be provided.


请注意,Android 首先使用了一个不安全的 "SHA1PRNG"实现,随后被 OpenSSL native 代码取代。基本上实现取决于使用了哪个 RNG。问题是 SHA1PRNG 的算法甚至没有被 Sun 指定,所以不可能依赖算法的任何细节,即使默认实现似乎是安全的。

关于java - 创建 "good"SecureRandom 的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40862857/

相关文章:

python - 如何在 Python 中设置全局随机种子

java - 检查元素是否验证条件

java - JDBC 中 Types.NULL 的使用

java - 在较长时间段内监控 Java 中的代码指标

java - 使用 Hibernate 时内存使用率高

c# - 单一方法的管理员权限

java - 根据安全策略限制动态加载的类和 jar

security - Laravel 4 : how to protect assets folder?

python - 如何检索 NumPy 随机数生成器的当前种子?

python - python和c++中类似的随机数生成但得到不同的输出