我应该播种SecureRandom吗?

Svi*_*ish 25 java random

在我们的代码库中找到以下代码:

public static final int DEFAULT_LENGTH = 16;
private static SecureRandom SR;
static
{
   try
   {
      SecureRandom sd0 = new SecureRandom();
      SR = new SecureRandom(sd0.generateSeed(DEFAULT_LENGTH * 2));
   }
   catch (Exception e){}
}
Run Code Online (Sandbox Code Playgroud)

这里SecureRandom创建了一个默认值,然后用于为另一个创建一个种子,该种子将在稍后的类中使用.这真的有必要吗?第二个是否比第一个更好,因为这样做了?

当第二个生成种子时,给出了字节数,这个重要吗?一个能SecureRandom以不同的量要比其它字节的种子可能是好还是坏?用于播种它的字节数是否应该与它将用于什么?

如果未调用setSeed,则对nextBytes的第一次调用将强制SecureRandom对象自行播种.如果先前调用了setSeed,则不会发生这种自播种.- javadoc

自播不够好吗?它取决于它将用于什么?


注意:对于某些上下文,它在类中使用,为存储在数据库中的东西创建随机ID.

dds*_*dso 21

我认为这是完全不必要的,因为你引用的Javadoc清楚地说明:默认构造的SecureRandom实例自己种子.写这篇文章的人可能不知道.

它们实际上也可能通过强制固定种子长度来降低安全性,该种子长度对于RNG实现而言可能不太理想.

最后,假设片段未经更改发布,静音异常吞咽也不是很好的编码风格.

  • 实际上这并不完全正确.它一旦设置就永远不会取代种子,但是如果没有设置明确的种子,那么仅在第一次调用生成随机数时才会发生自播种(这是必要的,否则您无法设置SecureRandom来生成一组特定的输出数字). (5认同)
  • 是的,它永远不会替换它的种子,您只能用您输入的内容来增强它。 (2认同)

ale*_*xbt 6

这样做时避免使用默认算法 new SecureRandom();

相反:

SecureRandom.getInstance("SHA1PRNG", "SUN");
Run Code Online (Sandbox Code Playgroud)

如果有人更改默认算法(如@Jules所述),您将不会受到影响.


编辑为Android:

对于android,请看一下:

在Android上,我们不建议指定提供程序.通常,只有在应用程序中包含提供程序或应用程序能够处理可能的ProviderNotFoundException时,才应该对指定提供程序的Java Cryptography Extension(JCE)API进行任何调用.

...

在Android N中,我们完全弃用了SHA1PRNG算法和Crypto提供程序的实现

  • 实际上,建议使用默认实现,因此这个答案与建议相反。我不明白这样做的理由。您希望默认算法不断改进,以便将来获得更好的安全性。 (2认同)

Jul*_*les 5

这不仅是完全没有必要的,它实际上可以提高SecureRandom对象生成的数字的可预测性.

没有显式种子集的SecureRandom将自行播种.它使用高度随机的数据源来执行此操作,并且非常安全.代码示例中的第一个SecureRandom将使用这样的种子.

第二个是通过产生256个随机位从第一个播种.假设使用了系统默认的SHA1PRNG,这就足够了.它使用160位状态,因此256个随机位将完全满足它的要求.但是假设现在有人认为这还不够,并将默认值切换为SHA512PRNG(他们甚至可以通过更改java的安全属性来查看代码).现在你提供的种子位太少了:它只需要它的一半.

摆脱它,只使用自种子对象,除非你有比系统更好的种子数据来源.

  • 更糟糕的是 - 代码完全荒谬.自播是足够安全的 - 然后就没有必要播种了.或者它不是 - 那么代码也没有改善问题,因为它依赖于sd0为SR提供种子的自播种.8-() (4认同)