【问题标题】:What java.security.egd option is for?java.security.egd 选项的用途是什么?
【发布时间】:2020-03-18 09:23:54
【问题描述】:

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

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

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

对吗?什么时候申请?

【问题讨论】:

    标签: java jvm


    【解决方案1】:

    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 以确保:

    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 使用/dev/randomSecureRandom 类播种,因此您的 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 实现:

    • 一个是平台相关的,基于本机调用或操作系统设备 例如在 Unix 上阅读 /dev/{u}random 或使用 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 (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 容器租户可能没有意识到他们正在共享它。当他们都试图同时使用它时,他们实际上是在互相造成拒绝服务。

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

    【讨论】:

    • 从 Java 8 开始,不再需要文件名中额外 ./ 的“晦涩解决方法”,因此您可以使用“/dev/urandom”,请参阅:docs.oracle.com/javase/8/docs/technotes/guides/security/…
    • 感谢您更新答案(特别是关于 Java 9 和 13 中的更改)。不过,根据我的理解,从 Java 8 开始,将“熵收集设备”设置为 /dev/urandom 或 /dev/./urandom 应该会产生完全相同的结果,否则修复将没有意义。从操作系统的角度来看,它们指向同一个相同的文件,因此不应该影响 Java(它在修复之前就已经影响了,但这是一个错误,而不是预期的功能)。因此,您的声明“需要额外的 /./ 来影响 PRNG 选择。”从 Java 8 开始,应该不再是真的。
    • 感谢@Kamal 你的cmets。我之前的短语“PRNG selection”不够清楚。我已经改写它以澄清我在谈论使用的算法:NativePRNG 或 SHA1PRNG。使用/dev/urandom 选择由/dev/urandom 提供的NativePRNG,而/dev/./urandom 在使用Java 8 时选择SHA1PRNG(也由/dev/urandom 提供)。从Java 9 开始,当指定/dev/./urandom 源时,DRBG 优先。
    • 再次感谢 dbaltor。我仍然建议更新答案的原始部分“额外的 /./ 似乎使 JVM 使用 SHA1PRNG ...”,澄清它仅适用于 Java 8 及更早版本(Java 8 仍然很流行 AFAIK)。此外,它的措辞方式听起来好像 SHA1PRNG 是一个更安全或更好的选择。我不是专家,但 tersesystems.com/blog/2015/12/17/…stackoverflow.com/a/27638413/279726 似乎建议将其留给 Java 来确定适当的 PRNG,而不是强制 SHA1PRNG,这在某些情况下不太安全。
    • 附言。 “SecureRanom”中的小错字; )
    【解决方案2】:

    这与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 问题导致的。

    【讨论】:

    • 那篇文章中可能有一个错字,因为 Java 错误 6202721 实际上指出“如果选择 /dev/urandom 会出现问题,因为 /dev/random 无法正常工作。”。因此,您的结论“由 /dev/urandom 的问题引起”是不正确的。有关选择 /dev/urandom 而不是默认值 (/dev/random) 的解释,请参阅接受的答案。在大多数情况下,这是个好主意。
    【解决方案3】:

    如果您使用的是 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​​​​​​​​

    【讨论】:

    • 我不相信这是正确的。对于背景:tersesystems.com/blog/2015/12/17/… Java 8 中的修复只说他们现在尊重 java.security 文件中的 SecureRandom 种子源属性。但默认情况下,它仍然包含:securerandom.source=file:/dev/random “晦涩的解决方法”是指文件名中的额外 ./ ,此处接受(且投票最多)的答案也提到了。
    • 只有在特定情况下才需要“晦涩的解决方法”,请参阅:bugs.java.com/bugdatabase/view_bug.do?bug_id=6202721
    • @Kamal 您发布的链接指的是 Java 6 及更早版本,
    • 正是这一点,它已在 Java 8 中修复。根据错误报告,Java 1.4.2 和之后需要“晦涩的解决方法”(在文件名中添加额外的 ./)最多 6 个。我也假设在 Java 7 中,否则它不会在 Java 8 中被提及为已修复。但是,如果您想使用非阻挡装置。
    • @souser 它也已在 openjdk 8 中修复
    猜你喜欢
    • 2018-11-05
    • 2020-04-30
    • 2019-09-17
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    相关资源
    最近更新 更多