【发布时间】:2020-03-18 09:23:54
【问题描述】:
在我正在处理的一个项目中,应用程序使用类似于以下的命令启动:
java -Djava.security.egd=file:/dev/urandom -jar app.jar
我以前从未见过java.security.egd 选项。搜了一下,好像是用来在Java应用中配置随机数生成的。
对吗?什么时候申请?
【问题讨论】:
在我正在处理的一个项目中,应用程序使用类似于以下的命令启动:
java -Djava.security.egd=file:/dev/urandom -jar app.jar
我以前从未见过java.security.egd 选项。搜了一下,好像是用来在Java应用中配置随机数生成的。
对吗?什么时候申请?
【问题讨论】:
TL;DR
如果在支持确定性随机位生成器 (DRBG) 的现代操作系统上运行 Java 8,我建议使用-Djava.security.egd=file:/dev/urandom 以避免代码被意外阻塞。如果不确定正在使用的操作系统,我的建议是坚持原来的建议,即:-Djava.security.egd=file:/dev/./urandom
如果运行 Java 11,我建议只需使用-Djava.security.egd=file:/dev/./urandom 以确保:
securerandom.source=file:/dev/urandom)继续阅读以了解详细信息。
Java 应用程序可以并且应该使用 java.security.SecureRandom 类通过使用加密强伪随机数生成器 (CSPRNG) 生成加密强随机值。 java.util.Random 类的标准 JDK 实现不被认为具有加密强度。
类 Unix 操作系统有 /dev/random,这是一个特殊文件,它提供伪随机数,访问从设备驱动程序和其他来源收集的环境噪声。但是,如果可用的熵比请求的少,它会阻塞; /dev/urandom 通常从不阻塞,即使伪随机数生成器种子在启动后没有完全用熵初始化。还有第三个特殊文件/dev/arandom,它在启动后阻塞,直到种子被安全地初始化为足够的熵,然后再也不会阻塞。
默认情况下,JVM 使用/dev/random 为 SecureRandom 类播种,因此您的 Java 代码可能会意外阻塞。用于启动 Java 进程的命令行调用中的选项 -Djava.security.egd=file:/dev/./urandom 告诉 JVM 改用 /dev/urandom。
额外的/./ 似乎使JVM 使用SHA1PRNG algorithm,它使用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 或使用 CryptoAPI
视窗。最新版本的 Linux 和 Windows 已经
支持 DRBG,但旧版本和嵌入式系统可能不支持。同时Java 11 Security Developer’s Guide 仍在读取
在 Linux 和 macOS 上,如果 java.security 中的熵收集设备 设置为
file:/dev/urandom或file:/dev/random,则NativePRNG 为 首选SHA1PRNG。否则,首选 SHA1PRNG。
为了阐明新的 DRBG 机制如何与之前的 PRNG 协同工作,我在 macOS (Darwin) 上使用 AdoptOpenJDK(build 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 作为随机源仍然是最重要的,正如我们在this very interesting post 上看到的那样:
分享
/dev/random对任何 Linux 容器技术都是一个挑战...
虚拟化服务器上的低熵问题加剧了,因为......在同一主机上运行的 Linux 容器竞争有限的熵供应。这种类型的问题有时被称为stamped herd。/dev/random设备是一种稀缺的共享系统资源,Linux 容器租户可能没有意识到他们正在共享它。当他们都试图同时使用它时,他们实际上是在互相造成拒绝服务。
【讨论】:
/dev/urandom 选择由/dev/urandom 提供的NativePRNG,而/dev/./urandom 在使用Java 8 时选择SHA1PRNG(也由/dev/urandom 提供)。从Java 9 开始,当指定/dev/./urandom 源时,DRBG 优先。
这与linux/dev/random和/dev/urandom随机数生成器的区别有关。
取自link
Java Bug 6202721 指出 java.security.SecureRandom 使用 /dev/random 而不是 /dev/urandom 即使指定了 /dev/urandom 因为当时(大约 2004 年) /dev/urandom 没有工作 适当地。既然 /dev/urandom 工作了,这个错误就再也没有被逆转过 很好。因此,您必须通过掩盖 通过使用 /dev/./urandom 来设置强制使用 SHA1PRNG 而不是 比 /dev/random。
回答你的问题
什么时候申请?
根据上面的链接,这是 Java 版本 5 所独有的,随后是 2004 年 Linux 系统上的 /dev/urandom 问题导致的。
【讨论】:
如果您使用的是 JDK 8 或更高版本,则不再需要此设置
Java 已经修复了这个问题,这里有一些链接
大纲
已修复 SHA1PRNG 和 NativePRNG 以正确尊重 java.security 文件中的 SecureRandom 种子源属性。 (不再需要使用 file:///dev/urandom 和 file:/dev/./urandom 的晦涩解决方法。)
更多信息(在页面中搜索随机):
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
【讨论】: