java.security.egd选项是用来做什么的?

71

在我正在工作的项目中,应用程序是使用类似于以下命令启动的:

java -Djava.security.egd=file:/dev/urandom -jar app.jar

我以前从未见过java.security.egd选项。查询了一些资料,似乎它用于配置Java应用程序中的随机数生成。

这是正确的吗?它应该在什么时候被应用?

3个回答

111

简而言之

如果在支持确定性随机比特生成器(DRBG)的现代操作系统上运行Java 8,则建议使用-Djava.security.egd=file:/dev/urandom以避免意外阻塞代码。如果不确定正在使用的操作系统,请坚持最初的建议,即:-Djava.security.egd=file:/dev/./urandom。如果运行Java 11,则建议简单地使用-Djava.security.egd=file:/dev/./urandom,以确保:1.利用最强大的可用SecureRandom实现(DRBG),而不管底层平台如何;2.避免意外阻塞代码(securerandom.source=file:/dev/urandom)。Unix类操作系统有一个特殊文件/dev/random,它通过访问从设备驱动程序和其他源收集的环境噪声来提供伪随机数。但是,如果可用熵少于请求的熵,则会阻塞;/dev/urandom通常不会阻塞,即使伪随机数生成器种子未完全初始化。 SecureRandom默认情况下使用/dev/random作为种子,因此您的Java代码可能会意外阻塞。命令行调用中的选项-Djava.security.egd=file:/dev/./urandom告诉JVM改用/dev/urandom。最后,有一个神话,即/dev/urandom是伪随机数生成器(PRNG),而/dev/random是“真正”的随机数生成器。这不是真的,/dev/random/dev/urandom都由相同的CSPRNG提供。只有它们的行为不同:/dev/random根据某些估计的熵耗尽时会阻塞,而/dev/urandom则不会阻塞。建议始终使用java.security.SecureRandom类来生成加密强度的随机值。在Java 8中,SecureRandom类的SHA1PRNG和NativePRNG已经修复,以正确地遵守java.security文件中的SecureRandom种子源属性。在Java 8中,需要使用额外的/./来更改SecureRandom使用的算法。从Java 9开始,SecureRandom类实现了三种DRBG机制。当使用现代操作系统时,NativePRNG比SHA1PRNG更安全。建议仍然使用/dev/urandom作为随机源。

1
从Java 8开始,文件名中额外的"./"这个“奇怪的解决方法”不再需要了,因此您可以直接使用"/dev/urandom",请参见:https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8.html - Kamal
感谢您更新答案(特别是关于Java 9和13的更改)。根据我的理解,截至Java 8,将“熵收集设备”设置为/dev/urandom或/dev/./urandom应该产生完全相同的结果,否则修复就没有意义。从操作系统的角度来看,它们指向完全相同的文件,因此不应影响Java(在修复之前确实如此,但那是一个错误,而不是一个预期的功能)。因此,您的声明“需要额外的/ ./以影响PRNG选择。”自Java 8以来就不再正确。 - Kamal
1
感谢@Kamal的评论。我之前说的“PRNG选择”不够清晰。我已经重新表述了一下,以澄清我所说的是使用的算法:NativePRNG或SHA1PRNG。使用/dev/urandom会选择由/dev/urandom提供数据的NativePRNG,而使用/dev/./urandom则会选择由/dev/urandom提供数据的SHA1PRNG(在Java 8中)。从Java 9开始,当指定/dev/./urandom源时,DRBG优先于SHA1PRNG。 - dbaltor
1
再次感谢dbaltor。我仍然建议您更新回答的原始部分“额外的/./似乎使JVM使用SHA1PRNG...”澄清这只适用于Java 8及更早版本(据我所知,Java 8仍然很受欢迎)。此外,它的措辞让人觉得SHA1PRNG是更安全或更好的选择。虽然我不是专家,但https://tersesystems.com/blog/2015/12/17/the-right-way-to-use-securerandom/和https://dev59.com/ml4c5IYBdhLWcg3wuMJ7#27638413似乎建议让Java确定适当的PRNG,而不是强制使用在某些情况下不太安全的SHA1PRNG。 - Kamal
2
谢谢。Java 17现在是LTS版。根据规范,您对jvm 11的答案仍然适用于jvm 17。规范:https://docs.oracle.com/en/java/javase/17/security/oracle-providers.html - aholbreich
显示剩余6条评论

1
这与Linux的/dev/random/dev/urandom随机数生成器的差异有关。
取自此链接
Java Bug 6202721指出,即使指定了/dev/urandom,java.security.SecureRandom仍使用/dev/random而不是/dev/urandom,因为当时(约2004年)/dev/urandom未正常工作。该错误从未被修复,现在/dev/urandom工作得非常好。因此,您必须通过使用/dev/./urandom混淆设置来欺骗它,以强制使用SHA1PRNG而不是/dev/random。
回答你的问题:
应该在什么时候应用?
根据上面的链接,这是Java版本5及其后版本中独有的问题,由于2004年Linux系统上/dev/urandom存在问题导致。

那篇文章可能有错别字,因为Java Bug 6202721实际上是这样说的:“如果选择了/dev/urandom,这就是一个问题,因为/dev/random无法正常工作。”。因此,你的结论“由于/dev/urandom的问题导致”是不正确的。请参见被接受的答案,了解选择/dev/urandom而不是默认值(/dev/random)的解释。在大多数情况下,这是个好主意。 - Kamal

0

如果您使用JDK 8或更高版本,则不再需要此操作。

Java已经解决了这个问题,以下是一些链接:

概述

SHA1PRNG和NativePRNG已被修复,以正确地遵守java.security文件中的SecureRandom种子源属性。(不再需要使用模糊的解决方法file:///dev/urandom和file:/dev/./urandom。)

有关更多信息(在页面中搜索random):

https://docs.oracle.com/javase/8/docs/technotes/guides/security/enhancements-8.html

https://www.oracle.com/technetwork/java/javase/8-whats-new-2157071.html​​​​​​​


1
“晦涩的解决方法”只在特定情况下才需要,详见:https://bugs.java.com/bugdatabase/view_bug.do?bug_id=6202721 - Kamal
@Kamal,您发布的链接是关于Java 6及更早版本的。 - Venu
1
这正是关键所在,它在Java 8中被修复了。根据错误报告,在Java 1.4.2及以上版本中需要“晦涩的解决方法”(在文件名中添加额外的./)。我假设在Java 7中也是如此,否则它不会被提及为在Java 8中已修复。但是,如果您想使用非阻塞设备,则仍然需要将/dev/urandom设置为/dev/random。 - Kamal
2
@souser 这个问题在 OpenJDK 8 中也已经被修复了。 - Venu
1
这不正确,今天我遇到了这个问题,然后我使用了这个方法,然后它就被解决了,所以我不认为它是在Java 8上被解决的。 - Mugeesh Husain
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接