有很多问题问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?
2条答案
按热度按时间8ehkhllq1#
基本上,最好的答案是:你不知道。你最好把选择权留给Maven,使用
new SecureRandom()
。这将由具有随机数生成器的最高优先级提供者检索第一个随机数生成器。哪个提供程序存在以及哪个提供程序具有优先级取决于运行时(IBM和Android也有Java兼容的运行时)。每个操作系统的运行时配置也可能不同,即使是标准JDK。
在虚拟机上,您应该安装特定VM管理器的操作系统特定客户端工具集;这通常允许客户端操作系统从主机操作系统播种。
SecureRandom
通常依赖于主机来提供种子甚至随机数据。但是,如果主机不能成功地播种自己,则Java运行时也不能,并且在虚拟主机上创建的“随机数据”可能会重复。来自JCA文档:
所有Java SE实现都使用无参数构造函数提供默认
SecureRandom
:new SecureRandom()
。此构造函数从最首选的提供程序开始遍历已注册安全提供程序的列表,然后从支持SecureRandom
随机数生成器(RNG)算法的第一个提供程序返回新的SecureRandom
对象。如果所有提供程序都不支持RNG算法,则它从SUN提供程序返回使用SHA1 PRNG的SecureRandom
对象。完全不需要自己给算法“播种”,调用
getSeed()
将尝试从运行时检索种子,这可能会耗尽随机池,就像getInstanceStrong()
一样。从而导致应用程序 * 以及其他应用程序 * 的一个块,直到熵变得可用。SecureRandom
实现将自己播种-希望以最好的方式-如果你不提供种子,注意在大多数(现代)实现中,所提供的种子被混合到随机池中,随机池最初是由操作系统来播种的;你不应该****假设两个被提供了相同种子的示例会生成相同的随机序列,即使在测试期间也是如此,即使你显式地指定了"SHA1PRNG"
也是如此。如果使用
new SecureRandom()
导致阻塞,那么你需要确保你的应用没有直接使用/dev/random
,耗尽熵池,如果没有,并且仍然阻塞,那么/dev/random
可能是行为不当。为了检索长期密钥材料,你也可以使用
SecureRandom.getInstanceStrong()
。但是你一般不应该使用这个;SecureRandom
对于大多数用例应该足够强大。如果使用getInstanceStrong()
方法,可能会耗尽操作系统的熵池。请注意,在较新的系统上,这种情况不太可能发生。例如,在Linux上,/dev/random
和/dev/urandom
指向相同的伪随机数生成器。最好不要使用
"SHA1PRNG"
。即使所有运行时都有一个实现,但它 * 不是 * 一个实现需求:[1]不需要特定的配置类型、策略类型或SecureRandom算法;但是,必须提供特定于实现默认值。
请注意,Android首先使用了不安全的
"SHA1PRNG"
实现,随后被OpenSSL本机代码取代。基本上,实现取决于使用了哪些RNG。问题是,Sun甚至没有指定SHA1 PRNG的算法,因此不可能依赖于算法的任何细节,即使默认实现看起来是安全的。3lxsmp7m2#
我相信,除非你有特殊要求,所有的都足够好了。
getSeed()
的文档说明:包含此方法只是为了向后兼容。建议调用方使用备用getInstance方法之一获取SecureRandom对象,然后调用generateSeed方法从该对象获取种子字节。
当然,您可以完全按照说明操作,但我不确定您的其他示例是否有意义。
我不记得是在哪里,但是我很久以前读到过,最好是显式地给予算法,所以我通常是这样做的
对于SHA1算法;PRNG是伪随机数生成器。虽然SHA1在一般加密用途上越来越过时,但我被告知它仍然适用于随机数,当你想将它们用作密钥时也是如此。