关于Java:我应该播种SecureRandom?

Should I seed a SecureRandom?

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

1
2
3
4
5
6
7
8
9
10
11
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){}
}

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

当为第二个生成种子时,会给出字节数,这很重要吗?使用不同字节数的SecureRandom种子是否可能更好或更差?用于种子的字节数是否应该以某种方式对应于它将用于的目的?

If setSeed is not called, the first call to nextBytes will force the SecureRandom object to seed itself. This self-seeding will not occur if setSeed was previously called. - javadoc

自我播种还不够好吗?这取决于它将用于什么目的?

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


我认为这是完全不必要的,因为正如您引用的JavaDoc清楚地指出的那样:缺省构造的SecureRandom实例本身就是种子。写这篇文章的人可能不知道。

它们还可能通过强制一个固定的种子长度来降低安全性,这对于RNG实现来说可能不太理想。

最后,假设代码片段发布时不变,无声的异常吞咽也不是很好的编码风格。


在执行new SecureRandom();时,避免使用默认算法。

而是这样做:

1
SecureRandom.getInstance("SHA1PRNG","SUN");

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

为Android编辑:

对于Android,请看:

  • https://android-developers.googleblog.com/2016/06/security-crypto-provider-deprecated-in.html
  • http://www.infoseisland.com/blogview/24773-android-n-deprecating-crypto-provider-and-sha1prng-algorithm.html
  • https://security.stackexchange.com/questions/128144/android-n-security-crypto-provider-is-已弃用
  • 安卓N中不推荐使用安全"加密"提供程序

On Android, we don’t recommend specifying the provider. In general,
any call to the Java Cryptography Extension (JCE) APIs specifying a
provider should only be done if the provider is included in the
application or if the application is able to deal with a possible
ProviderNotFoundException.

in Android N we are deprecating the implementation of the SHA1PRNG
algorithm and the Crypto provider altogether


这不仅是完全不必要的,还可能增加SecureRandom对象生成的数字的可预测性。

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

第二个通过产生256个随机位从第一个产生种子。假设使用系统默认sha1prng,这就足够好了。它使用160位的状态,所以256个随机位将完全满足它的要求。但是假设现在有人认为这是不够的,并且将默认值转换为Sa512PRNG(他们可以通过改变Java的安全属性来查看代码)。现在你给它提供的种子太少了:只有它需要的一半。

去掉它,只使用自种子对象,除非您有比系统可用的更好的种子数据源。


只是这个答案的补充。根据谷歌的说法,如果你在安卓系统中使用这段代码,你肯定应该使用高熵源(如/dev/urandom或/dev/random)来输入secureRandom。

即使是下面的帖子现在已经一岁了,也许这已经被纠正了,但我无法确认是否是。

https://plus.google.com/+androiddevelopers/posts/yxwzenqmjs2

编辑:

类的默认行为现在似乎是post中指定的行为,因此种子设定再次被认为是不必要的:

http://developer.android.com/reference/java/security/securelrandom.html