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

dav*_*ooh 56 java jvm

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

java -Djava.security.egd=file:/dev/urandom -jar app.jar
Run Code Online (Sandbox Code Playgroud)

我以前从未见过这个java.security.egd选项。搜索了一下,好像是用来在Java应用程序中配置随机数生成的。

这样对吗?应该什么时候应用?

dba*_*tor 87

TL; 博士

如果在支持 Deterministic Random Bit Generator (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)

请继续阅读以了解详细信息。


Java 应用程序可以并且应该使用java.security.SecureRandom类通过使用加密强伪随机数生成器 ( CSPRNG )生成加密强随机值。java.util.Random类的标准 JDK 实现不被认为是加密强的。

类 Unix 操作系统有/dev/random一个特殊文件,它提供伪随机数访问从设备驱动程序和其他来源收集的环境噪声。但是,如果可用的熵少于请求的熵它就会阻塞/dev/urandom通常从不阻塞,即使伪随机数生成器种子自启动以来没有完全用熵初始化。还有第三个特殊文件,/dev/arandom它在启动后阻塞,直到种子被安全初始化并具有足够的熵,然后再不会阻塞。

默认情况下,JVM使用为SecureRandom类设定种子/dev/random,因此 您的 Java 代码可能会意外阻塞-Djava.security.egd=file:/dev/./urandom用于启动 Java 进程的命令行调用中的选项告诉 JVM 改为使用/dev/urandom

额外的/./似乎使JVM使用SHA1PRNG算法,该算法使用SHA-1作为PRNG(伪随机数生成器)的基础。它比/dev/urandom指定时使用的 NativePRNG 算法更强。

最后,有一个神话/dev/urandom是伪随机数生成器 PRNG/dev/random是“真”随机数生成器。这是不正确的,这两个/dev/random/dev/urandom由相同CSPRNG(密码安全伪随机数发生器)被馈送。只有它们的行为不同:/dev/random根据某些估计,当其随机池耗尽熵时阻塞,而/dev/urandom不会。

低熵系统呢?没那么糟糕。

事实证明,“看起来随机”是一些加密组件(例如网络服务器的临时会话密钥)的基本要求。如果您采用加密散列的输出,它与随机字符串无法区分,因此密码将接受它。这就是使用 SHA1PRNG 算法的原因,因为它使用散列函数和计数器以及种子。

应该什么时候申请?

总是,我会说。

资料来源:
https://gist.github.com/svrc/5a8accc57219b9548fe1
https://www.2uo.de/myths-about-urandom


编辑 09/2020:
我已更改此更新以反映以下测试:
现代操作系统上的 -Java 8
-Java 11,因为它是当前的长期支持 (LTS) 版本。

一条评论提到了Java 8 中SecureRandom类的行为的变化。

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

上面“来源”部分中引用的测试已经指出了这一点。将Java 8 中SecureRandom/./使用的算法从 NativePRNG 更改为 SHA1PRNG 需要额外的内容。 我同意 NativePRNG 比 SHA1PRNG 更安全,但仅限于在现代操作系统上运行时。因此,我相应地更新了我的结论并将其移至顶部。

但是,我确实有一些消息要分享。根据JEP-273,自 Java 9 以来,SecureRandom类实现了NIST 800-90Ar1 中描述的三个确定性随机位生成器 (DRBG)机制。这些机制实现了与 SHA-512 和 AES-256 一样强大的现代算法。

JDK 以前有两种SecureRandom实现:

  • 一种是平台相关的,基于本机调用或操作系统设备,例如/dev/{u}random在 Unix 上阅读或在 Windows 上使用 CryptoAPI。最新版本的 Linux 和 Windows 已经支持 DRBG,但较旧的版本和嵌入式系统可能不支持
  • 另一种是纯 Java 实现,它使用旧的基于 SHA1 的 RNG 实现,它不如已批准的 DRBG 机制使用的算法强大。

同时Java 11 Security Developer's Guide仍然阅读

在 Linux 和 macOS 上,如果 java.security 中的熵收集设备设置为file:/dev/urandomfile:/dev/random,则 NativePRNG 优先于 SHA1PRNG。否则,首选 SHA1PRNG。

为了阐明新的 DRBG 机制如何与以前的 PRNG 一起使用,我在 macOS(达尔文)上使用 AdoptOpenJDK(构建 11.0.7+10)进行了一些测试。结果如下:


-Djava.security.egd=file:/dev/random这等于默认选项
默认算法:NativePRNG
提供者:SecureRandom.NativePRNG 算法来自:SUN

-Djava.security.egd=file:/dev/urandom
默认算法:NativePRNG
提供者:SecureRandom.NativePRNG 算法来自:SUN

-Djava.security.egd=file:/dev/./urandom
默认算法:DRBG
提供者:SecureRandom.DRBG 算法来自:SUN


最后,/dev/urandom即使在使用现代操作系统时,作为随机源的使用点仍然是最重要的,正如我们在这篇非常有趣的文章中所读到

共享/dev/random对于任何 Linux 容器技术都是一个挑战……
虚拟化服务器上​​的低熵问题加剧了因为……运行在同一主机上的 Linux 容器竞争有限的熵供应。这种类型的问题有时被称为蜂群。该/dev/random设备是一种稀缺的共享系统资源,Linux Container 租户可能没有意识到他们正在共享。当他们都试图同时使用它时,他们实际上导致了对彼此的拒绝服务。

来源: https :
//www.openssl.org/blog/blog/2017/08/12/random/

  • 谢谢。Java 17 现在是 LTS。根据规范,您对 jvm 11 的答案对于 jvm 17 规范仍然有效:https://docs.oracle.com/en/java/javase/17/security/oracle-providers.html (2认同)