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