我应该播种SecureRandom吗?
在我们的代码库中找到以下代码:
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
播种的字节数是否可能比其他字节更好或更差? 用于播种它的字节数是否应该与它将用于什么?
如果未调用setSeed,则对nextBytes的第一次调用将强制SecureRandom对象自行播种。 如果先前调用了setSeed,则不会发生这种自播种。 – javadoc
自播不够好吗? 它取决于它将用于什么?
注意:对于某些上下文,它在类中使用,为存储在数据库中的东西创建随机ID。
我认为这是完全不必要的,因为你引用的Javadoc明确指出:默认构造的SecureRandom
实例为自己种子。 写这篇文章的人可能不知道。
它们实际上也可能通过强制固定种子长度来降低安全性,该种子长度对于RNG实现而言可能不太理想。
最后,假设片段未经更改发布,静音exception吞咽也不是很好的编码风格。
避免使用默认算法,这是执行new SecureRandom();
时的情况new SecureRandom();
相反:
SecureRandom.getInstance("SHA1PRNG", "SUN");
如果有人更改默认算法(如@Jules所述),您将不会受到影响。
编辑为Android:
对于android,请看一下:
- https://android-developers.googleblog.com/2016/06/security-crypto-provider-deprecated-in.html
- http://www.infosecisland.com/blogview/24773-Android-N-Deprecating-Crypto-Provider-and-SHA1PRNG-Algorithm.html
- https://security.stackexchange.com/questions/128144/android-n-security-crypto-provider-is-deprecated
- 安全“加密”提供程序在Android N中已弃用
在Android上,我们不建议指定提供程序。 通常,只有在应用程序中包含提供程序或应用程序能够处理可能的ProviderNotFoundException时,才应该对指定提供程序的Java Cryptography Extension(JCE)API进行任何调用。
…
在Android N中,我们完全弃用了SHA1PRNG算法和Crypto提供程序的实现
这不仅是完全没有必要的,它实际上可能会增加SecureRandom对象生成的数字的可预测性。
没有明确种子集的SecureRandom将自行播种。 它使用高度随机的数据源来执行此操作,并且非常安全。 代码示例中的第一个SecureRandom将使用这样的种子。
第二个是通过产生256个随机位从第一个播种。 假设使用了系统默认的SHA1PRNG,这就足够了。 它使用160位状态,因此256个随机位将完全满足它的要求。 但是假设现在有人认为这还不够,并将默认值切换为SHA512PRNG(他们甚至可以通过更改java的安全属性来查看代码)。 现在你提供的种子位太少了:只需要它的一半。
摆脱它,只使用自种子对象,除非你有一个比系统可用的更好的种子数据来源。
只是这个答案的附录。 根据谷歌的说法,如果你在android中使用这个代码,你肯定应该使用像/ dev / urandom或/ dev / random这样的高熵源来获取SecureRandom。
即使是下面的post现在已经有一年了,也许这已经得到了纠正,但我无法确认是否是。
https://plus.google.com/+AndroidDevelopers/posts/YxWzeNQMJS2
编辑:
看来该类的默认行为现在是post中指定的行为,因此再次认为不需要播种:
http://developer.android.com/reference/java/security/SecureRandom.html