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

2022-01-16 00:00:00 jvm java

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

In a project I'm working on, the application is launched using a command similar to this:

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

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

I've never seen the java.security.egd option before. Searching a bit, it seems to be used to configure random number generation in a Java application.

对吗?什么时候申请?

推荐答案

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

If running Java 8 on modern OSes with support to Deterministic Random Bit Generator (DRBG), I'd recommend using
-Djava.security.egd=file:/dev/urandom to avoid getting the code blocked unexpectedly. If not sure about the OS being used, my suggestion is to stick with the original recommendation, namely:
-Djava.security.egd=file:/dev/./urandom

If running Java 11, I'd recommend simply using
-Djava.security.egd=file:/dev/./urandom to make sure of:

  1. 利用可用的最强大的 SecureRandom 实施 (DRBG),无论基础平台如何
  2. 避免代码被意外阻止 (securerandom.source=file:/dev/urandom)
  1. leveraging the strongest SecureRandom implementation available (DRBG) regardless the underpinning platform
  2. avoiding getting the code blocked unexpectedly (securerandom.source=file:/dev/urandom)

继续阅读以了解详细信息.

Read on to know the details.

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

Java applications can and should use java.security.SecureRandom class to produce cryptographically strong random values by using a cryptographically strong pseudo-random number generator (CSPRNG). The standard JDK implementations of java.util.Random class are not considered cryptographically strong.

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

Unix-like operating systems have /dev/random, a special file which serves pseudo random numbers accessing environmental noise collected from device drivers and other sources. However, it blocks if there is less entropy available than requested; /dev/urandom typically never blocks, even if the pseudorandom number generator seed was not fully initialized with entropy since boot. There still is a 3rd special file, /dev/arandom which blocks after boot until the seed has been securely initialized with enough entropy, and then never blocks again.

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

By default, the JVM seeds the SecureRandom class using /dev/random, therefore your Java code can block unexpectedly. The option -Djava.security.egd=file:/dev/./urandom in the command line invocation used to start the Java process tells the JVM to use /dev/urandom instead.

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

The extra /./ seems to make the JVM to use the SHA1PRNG algorithm which uses SHA-1 as the foundation of the PRNG (Pseudo Random Number Generator). It is stronger than the NativePRNG algorithm used when /dev/urandom is specified.

最后,有一个神话,/dev/urandom 是一个伪随机数生成器,一个 PRNG,而 /dev/random 是一个真"随机数生成器.这根本不是真的,/dev/random/dev/urandom 都由同一个 CSPRNG(加密安全伪随机数生成器)提供.只是它们的行为不同:根据某种估计,当随机池耗尽熵时,/dev/random 会阻塞,而 /dev/urandom 不会.

Finally, there is a myth that /dev/urandom is a pseudo random number generator, a PRNG, whilst /dev/random is a "true" random number generator. This is simply not true, both /dev/random and /dev/urandom are fed by the same CSPRNG (cryptographically secure pseudorandom number generator). Only their behaviour differs: /dev/random blocks when its randomness pool runs out of entropy according to some estimate, whilst /dev/urandom does not.

低熵系统呢?还不错.

事实证明,看起来随机"是几个加密组件的基本要求,例如网络服务器的临时会话密钥.如果您获取加密哈希的输出,它与随机字符串无法区分,因此密码将接受它.这就是使用 SHA1PRNG 算法的原因,因为它使用哈希函数和计数器,以及种子.

It turns out that "looking random" is the basic requirement for several cryptographic components such as webserver's ephemeral session keys. And if you take the output of a cryptographic hash, it is indistinguishable from a random string so that ciphers will accept it. That's the reason of using the SHA1PRNG algorithm, as it uses a hash function and a counter, together with a seed.

什么时候申请?

我会说总是.

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

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

EDIT 09/2020:
I have changed this update to reflect the tests with:
-Java 8 on modern OSes
-Java 11 as it is the currently long-term support (LTS) version.

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

A comment mentions a change on SecureRandom class' behaviour in Java 8.

已修复 SHA1PRNG 和 NativePRNG 以正确尊重 java.security 文件中的 SecureRandom 种子源属性.(不再需要使用 file:///dev/urandom 和 file:/dev/./urandom 的晦涩解决方法.)

SHA1PRNG and NativePRNG were fixed to properly respect the SecureRandom seed source properties in the java.security file. (The obscure workaround using file:///dev/urandom and file:/dev/./urandom is no longer required.)

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

This had already been pointed out by the tests referenced on the Sources section above. The extra /./ is required to change the algorithm used by SecureRandom in Java 8 from NativePRNG to SHA1PRNG.
I agree that NativePRNG is more secure than SHA1PRNG, but only when running on modern OSes. I have therefore updated accordingly my conclusion and moved it to the top.

不过,我确实有一些消息想分享.根据 JEP-273,从 Java 9 开始,SecureRandom 类实现确定性随机位生成器 (DRBG) 机制rel="noreferrer">NIST 800-90Ar1.这些机制实现了与 SHA-512 和 AES-256 一样强大的现代算法.

However, I do have some news that I'd like to share. As per the JEP-273, since Java 9 the SecureRandom class implements the three Deterministic Random Bit Generator (DRBG) mechanisms described in NIST 800-90Ar1. These mechanisms implement modern algorithms as strong as SHA-512 and AES-256.

JDK 之前有两种 SecureRandom 实现:

The JDK previously had two kinds of SecureRandom implementations:

  • 一个是平台相关的,基于本机调用或操作系统设备例如在 Unix 上读取 /dev/{u}random 或在视窗.最新版本的 Linux 和 Windows 已经支持 DRBG,但旧版本和嵌入式系统可能不支持.
  • 另一种是纯 Java 实现,它使用较旧的基于 SHA1 的 RNG 实现,不如经批准的 DRBG 机制使用的算法.
  • One is platform-dependent and based on native calls or OS devices such as reading /dev/{u}random on Unix or using the CryptoAPI on Windows. The latest releases of Linux and Windows already support DRBG, but older releases and embedded systems might not.
  • The other kind is a pure Java implementation that uses an older SHA1-based RNG implementation, which is not as strong as the algorithms used by approved DRBG mechanisms.

同时 Java 11 安全开发者指南 仍然是

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

On Linux and macOS, if the entropy gathering device in java.security is set to file:/dev/urandom or file:/dev/random, then NativePRNG is preferred to SHA1PRNG. Otherwise, SHA1PRNG is preferred.

为了阐明新的 DRBG 机制如何与之前的 PRNG 协同工作,我在 macOS (Darwin) 上使用 AdoptOpenJDK(build 11.0.7+10)进行了一些测试.结果如下:

To clarify how the new DRBG mechanisms play together with the previous PRNGs, I ran some tests on macOS (Darwin) with AdoptOpenJDK (build 11.0.7+10). Here are the results:

-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 作为随机源仍然是最重要的,正如我们可以在 这篇非常有趣的帖子:

Finally, the point of using /dev/urandom as source of randomness still remains paramount even when using modern OSes, as we can read on this very interesting post:

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

Sharing /dev/random is a challenge for any Linux container technology...
The low amount of entropy on virtualized servers problem is exacerbated because ... Linux Containers running on the same host compete for a limited supply of entropy. This type of problem is sometimes referred to as a stampeding herd. The /dev/random device is a scarce shared system resource that Linux Container tenants likely have not realised they are sharing. When they all try to use it at the same time they are effectively causing a denial of service on each other.

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

相关文章