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

时间:2014-04-11 23:18:45

标签: java cryptography

我想就Java中SecureRandom的常见神话,安全性与性能权衡问题进行讨论。

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

基本上这里是SecureRandom的一些最受欢迎和最全面的文章:

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

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

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

并且,Sun的官方"坦白" Java 8中的错误/混淆和建议发布: http://openjdk.java.net/jeps/123

现在Java 8已经出来了,老实说,通过查看文档,我不确定实际修复得多好些: http://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html

毕竟,这就是我得到的(请帮助我看看我是否对它们进行了分类):

像Amit Sethi这样的人建议使用指定的实例化,例如:SecureRandom sr3 = SecureRandom.getInstance(" SHA1PRNG"," SUN"),实际上,Sun告诉我们这将结束总是从/ dev / random(???)读取,这意味着它可能会阻止每次调用。与使用新的SecureRandom()相反,它将始终从/ dev / urandom读取,除非调用generateSeed()。见

http://bugs.java.com/view_bug.do?bug_id=6202721

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

现在,如果"新的SecureRandom()"是选择,并将导致永不阻止呼叫,那么我认为我应该做的定期重播应该是:

使SecureRandom成为类中的静态实例,并让另一个Executor线程定期调用generateSeed(),因此即使调用阻塞,它也不会影响我的应用程序中的主请求处理线程。这听起来像是一种很好的方式吗?

真的很感谢任何Java和加密专家在这里阐明这个问题。 谢谢!

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

1 个答案:

答案 0 :(得分:4)


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


  

使SecureRandom成为类中的静态实例,并让另一个Executor线程定期调用generateSeed(),因此即使调用阻塞,它也不会影响我的应用程序中的主请求处理线程。这听起来像是一种很好的方式吗?

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

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

如果您仍然遇到阻止问题,请创建一个中央系统播种SecureRandom。使用nextBytes()创建新的种子材料,并使用SecureRandom(byte[] seed)构造函数将其提供给新的SecureRandom。只有new SecureRandom()无法处理这种情况时才应使用此方法。

尽管现在通过使用构造函数显式提供初始种子,但构造函数本身并不保证它仅用于为RNG播种。然而,它可能可能,因此它不太可能阻止。 SecureRandom is thread safe因此您无需同步对其的访问权限。

使用新的Java 8 SecureRandom.getInstanceStrong() 更多可能会阻止。我推测他们已经添加以使默认实例非阻塞。 RSA密钥对生成通常需要大量的熵,因此很可能返回的实例使用对/dev/random的阻塞调用。

总而言之,在特殊情况下使用SecureRandom仍然相当肮脏。幸运的是,这只是一个非常有限的用例问题。