关于java:SecureRandom.getInstance(“SHA1PRNG”,“SUN”)总是阻塞,而新的SecureRandom()不是?

SecureRandom.getInstance(“SHA1PRNG”, “SUN”) always blocking while new SecureRandom() is not?

我想请教一些关于Java中SurvivRANDOM的常见神话,关于安全性与性能权衡。

我在互联网上研究了一段时间,并把以下信息整合在一起。我希望这里的人帮助我确认我得到了什么,并希望得到一些关于实际选择什么来实现的想法。

基本上,这里有一些最受欢迎和最彻底的文章SecureRandom:

正确使用Java的SecureRandom:http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securelrandom/

使用Java的SecureRandom时的问题:http://www.cigital.com/justice-league-blog/2014/01/06/issues-when-using-java-securelrandom/

使用SecureRandom类:http://moi.vonos.net/java/securelrandom/

而且,Sun的官方"忏悔"的bug /混乱和在Java 8中提出的发布:http://openjdk.java.net/jeps/123

现在Java 8不在了,我真的不知道这实际上是如何修复的,只是看看文档:http://docs.oracle.com/javase/8/docs/api/java/security/securelrandom.html

所以毕竟,这就是我得到的(请帮助我看看我是否把它们分类了):

像amit sethi这样的人建议使用指定的实例化,比如:secureRandom sr3=secureRandom.getInstance("sha1prng","sun"),在现实中,sun告诉我们这将最终总是从/dev/random(???)这意味着它可能会对每个调用都进行阻塞。与使用新的secureRandom()相反,除非调用generateseed(),否则它将始终从/dev/urandom读取。见

http://bugs.java.com/view_bug.do?错误ID=6202721

这是否意味着"新SoCurrand"()在当前Java中仍然是首选?我发现没有多少其他文件明确地陈述了上述观点,所以我想知道这是否仍然是真的?

现在,如果选择"new secureRandom()",将导致永不阻塞调用,那么我认为我应该为定期重新播种做的是:

使secureRandom成为类中的一个静态实例,并让另一个执行器线程定期调用该实例上的generateseed(),因此即使调用被阻塞,它也不会影响我的应用程序中的主请求处理线程。这听起来是个好方法吗?

非常感谢任何Java和密码专家在这个问题上提供一些启发。谢谢!

编辑:这里的另一个有用的线程,似乎支持了我的猜测:https://bugs.openjdk.java.net/browse/jdk-4705093


编辑:首先,如果/dev/random/dev/urandom阻止,那么首先尝试解决该特定问题是有意义的。下面的解决方案是尝试在Java本身中修复EDCOX1 2的缺点,因此它不太依赖于那些特殊的设备。

Make SecureRandom a static instance in the class and let another Executor thread periodically call generateSeed() on it, thus even though the call is blocking, it's not affecting my main request handling thread in my application. Does that sound like a good way doing it?

不,在这种情况下,您应该使用nextBytes()作为内部调用generateSeed()使用种子信息的原始供应商。换句话说,您还可以创建一个单独的SecureRandom实例。请注意,只要您有一个具有足够高的状态和良好的备份算法的SecureRandom实例,就不需要经常重置(因为它不太可能创建循环)。如果需要更高的熵,每次都要生成一个新的随机类,或者使用SecureRandom.getInstanceStrong()检索到的随机类。

使用默认的new SecureRandom()可能是最好的。通常,您应该始终为加密算法(如"AES/CBC/PKCS5Padding")提供精确的算法名称,但为了安全随机功能,最好让系统找出哪种算法是最好的。如果要更改任何内容,请通过命令行结构进行更改,并确保在UNIX系统上提供/dev/urandom

如果仍然存在阻塞问题,那么创建一个中心的系统种子SecureRandom。使用nextBytes()创建新的种子材料,并使用SecureRandom(byte[] seed)构造函数将其提供给新的SecureRandom。这种方法只能在new SecureRandom()无法处理时使用。

尽管通过使用构造函数来提供初始种子现在是显式的,但构造函数本身并不保证它仅用于为RNG播种。然而,情况很可能是这样的,所以它不太可能被阻止。SecureRandom是线程安全的,因此您不需要同步对它的访问。

使用新的Java 8 EDCOX1(7)更容易阻塞。我假定他们已经添加了这些内容,以使默认实例不被阻塞。RSA密钥对的生成通常需要大量的熵,因此返回的实例可能使用对/dev/random的阻塞调用。

总之,在特殊情况下使用SecureRandom仍然相当糟糕。幸运的是,对于数量非常有限的用例来说,这只是一个问题。