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

时间:2016-11-29 09:59:47

标签: 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?

2 个答案:

答案 0 :(得分:0)

基本上,最佳答案是:您不知道。您最好将选择权留给专家,然后使用new SecureRandom()。这将由优先级最高的提供者检索第一个随机数生成器。

存在哪些提供程序,哪个提供程序具有优先级取决于运行时(IBM和Android也具有Java兼容的运行时)。即使对于标准JDK,每个操作系统的运行时配置也可能有所不同。

来自the JCA documentation

  

所有Java SE实现都使用无参数构造函数SecureRandom提供默认的new SecureRandom()。该构造方法从最喜欢的提供程序开始遍历已注册的安全提供程序的列表,然后从支持SecureRandom随机数生成器(RNG)算法的第一个提供程序返回新的SecureRandom对象。如果所有提供程序都不支持RNG算法,则它将返回使用SUN提供程序中的SHA1PRNG的SecureRandom对象。


绝对不需要自己“播种”算法。调用getSeed()将尝试从运行时检索种子。就像getInstanceStrong()一样,这可能会耗尽随机池,导致您的应用程序以及其他应用程序处于阻塞状态,直到熵变得可用为止。如果您不提供种子,则SecureRandom实现将自己种子化-希望以尽可能最佳的方式。

如果使用new SecureRandom()导致阻塞,那么您需要确保您的应用程序不直接使用/dev/random,从而耗尽了熵池。如果没有,并且仍然阻塞,则/dev/random可能行为不正确。在虚拟机上,您可能需要安装特定VM管理器的特定于操作系统的客户端工具集;通常,这允许客户端操作系统从主机操作系统播种。


要检索长期密钥密钥资料,您也可以使用SecureRandom.getInstanceStrong()。您通常不应该使用它; SecureRandom应该足以应付大多数使用情况。如果您使用getInstanceStrong()方法,则可能会耗尽操作系统的熵池。


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

  

[1]不需要特定的配置类型,策略类型或SecureRandom算法;但是,必须提供特定于实现的默认值。

请注意,Android首先使用了不安全的"SHA1PRNG"实现,随后将其替换为OpenSSL本机代码。基本上,实现取决于使用RNG。问题在于,甚至Sun尚未指定SHA1PRNG的算法,因此即使默认实现似乎是安全的,也不可能依赖该算法的任何细节。

答案 1 :(得分:-1)

我相信除非你有特殊要求,否则它们都足够好。

getSeed()的文档说:

  

此方法仅用于向后兼容。呼叫者,召集者   我们鼓励使用其中一种替代的getInstance方法   获取SecureRandom对象,然后调用generateSeed方法   从该对象获取种子字节。

你当然可以完全按照说明进行操作,但我不确定你的其他例子是否有意义。

我不记得在哪里,但我很久以前就读过,最好明确地给出算法。所以我经常做

SecureRandom.getInstance("SHA1PRNG")

用于SHA1算法; PRNG用于伪随机数发生器。虽然SHA1用于一般加密目的,但我被告知,当你想将它们用于加密密钥时,随机数字仍然可以使用。