拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 java.security.egd JVM选项

java.security.egd JVM选项

白鹭 - 2021-11-24 849 0 0

1.概述

启动Java虚拟机(JVM)时,我们可以定义各种属性,这些属性将改变JVM的行为。这样的属性之一就是java.security.egd.

在本教程中,我们将检查它是什么,如何使用它以及产生什么效果。

2.什么是java.security.egd

作为JVM属性,我们可以使用java.security.egd来影响SecureRandom类的初始化方式。

像所有JVM属性一样,我们在启动JVM时在命令行中-D

java -Djava.security.egd=file:/dev/urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester

通常,如果我们正在运行Java 8或更高版本,并且在Linux上运行,则我们的JVM默认情况下file:/dev/urandom

3. java.security.egd有什么作用?

当我们第一次调用从SecureRandom读取字节时,我们使它初始化并读取JVM的java.security配置文件.该文件包含securerandom.source属性

securerandom.source=file:/dev/random

安全提供程序(例如默认的sun.security.provider.Sun在初始化时会读取此属性

当我们设置java.security.egd JVM属性时,安全提供程序可以使用它来覆盖securerandom.source配置的属性。

SecureRandom生成随机数java.security.egdsecurerandom.source控制哪个entropy gathering device (EGD)作为种子数据的主要来源。

在Java 8之前,我们在$JAVA_HOME/jre/lib/security java.security ,但在以后的实现中,它在$JAVA_HOME/conf/security

egd选项是否有效取决于安全提供程序的实现。

java.security.egd可以取什么值?

我们可以使用java.security.egd ,其值如下:

  • file:/dev/random
  • file:/dev/urandom
  • file:/dev/./urandom

此设置是否有效,还是其他值有所不同,取决于我们使用的平台和Java版本以及如何配置JVM的安全性。

在基于Unix的操作系统(OS)上, /dev/random是一个特殊的文件路径,在文件系统中以普通文件的形式出现,但从中读取的内容实际上与OS的设备驱动程序进行交互以生成随机数。一些设备实现还通过/dev/urandom甚至/dev/arandom URI提供访问。

5.关于file:/dev/./urandom有何特别之处?

首先,让我们了解文件/dev/random/dev/urandom:

  • /dev/random从各种来源收集熵; /dev/random将一直阻塞,直到它具有足够的熵来满足我们的不可预测数据的读取请求为止
  • /dev/urandom将从可用的任何内容中得出伪随机性,而不会阻塞。

当我们第一次使用SecureRandom ,我们的默认Sun SeedGenerator初始化。

当我们使用特殊值file:/dev/randomfile:/dev/urandom ,我们使Sun SeedGenerator使用本机(平台)实现。

Unix上的提供程序实现可能仍通过/dev/random读取而阻塞。在Java 1.4中,发现某些实现存在此问题。该错误随后在Java 8的JDK增强建议(JEP 123)下得到修复。

file:/dev/./urandom类的URL或任何其他值,会导致SeedGenerator将其视为指向我们要使用的种子源的URL

在类似Unix的系统上,我们的file:/dev/./urandom URL解析为相同的非阻塞/dev/urandom文件。

但是,我们并不总是要使用此值。在Windows上,我们没有此文件,因此我们的URL无法解析。这触发了产生随机性的最终机制,并且可能使我们的初始化延迟约5秒钟。

SecureRandom的演变

在各种Java版本中java.security.egd的影响已经改变。

因此,让我们看一些影响SecureRandom行为的更重要的事件:

了解SecureRandom更改方式后,我们可以深入了解java.security.egd属性的可能效果。

7.测试java.security.egd

要确定JVM属性的效果,最好的方法是尝试一下。因此,让我们通过运行一些代码来创建新的SecureRandom并定时获取它需要多长时间**java.security.egd** 一些随机字节。

首先,让我们使用main()方法JavaSecurityEgdTester我们将使用System.nanoTime() secureRandom.nextBytes()调用,并显示结果:

public class JavaSecurityEgdTester {

 public static final double NANOSECS = 1000000000.0;



 public static void main(String[] args) {

 SecureRandom secureRandom = new SecureRandom();

 long start = System.nanoTime();

 byte[] randomBytes = new byte[256];

 secureRandom.nextBytes(randomBytes);

 double duration = (System.nanoTime() - start) / NANOSECS;



 System.out.println("java.security.egd = " + System.getProperty("java.security.egd") + " took " + duration + " seconds and used the " + secureRandom.getAlgorithm() + " algorithm");

 }

 }

现在,通过启动一个新的Java实例并为java.security.egd属性JavaSecurityEgdTester

java -Djava.security.egd=file:/dev/random -cp . com.baeldung.java.security.JavaSecurityEgdTester

让我们检查输出以查看测试花费了多长时间以及使用了哪种算法:

java.security.egd=file:/dev/random took 0.692 seconds and used the SHA1PRNG algorithm

由于我们的系统属性仅在初始化时读取,因此让我们在新的JVM中针对java.security.egd每个不同值启动类:

java -Djava.security.egd=file:/dev/urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester

 java -Djava.security.egd=file:/dev/./urandom -cp . com.baeldung.java.security.JavaSecurityEgdTester

 java -Djava.security.egd=baeldung -cp . com.baeldung.java.security.JavaSecurityEgdTester

在使用Java 8或Java 11的Windows上,使用值file:/dev/randomfile:/dev/urandom进行测试的时间小于2秒钟。使用其他file:/dev/./urandom ,甚至baeldung ,会使我们的测试花费5秒钟以上!

有关为什么会发生这种情况的说明,请参见我们前面的部分。在Linux上,我们可能会得到不同的结果。

8.关于SecureRandom.getInstanceStrong()呢?

Java 8引入了SecureRandom.getInstanceStrong()方法。让我们看看这如何影响我们的结果。

首先,让我们用SecureRandom. new SecureRandom() getInstanceStrong()

SecureRandom secureRandom = SecureRandom.getInstanceStrong();

现在,让我们再次运行测试:

java -Djava.security.egd=file:/dev/random -cp . com.baeldung.java.security.JavaSecurityEgdTester

在Windows上运行时, SecureRandom.getInstanceStrong() java.security.egd属性的值没有明显的作用。甚至无法识别的值也可以使我们快速响应。

让我们再次检查输出,注意不到0.01秒的时间。我们还要观察一下,该算法现在是Windows-PRNG:

java.security.egd=baeldung took 0.003 seconds and used the Windows-PRNG algorithm

请注意,算法名称中的PRNG代表伪随机数生成器。

9.播种算法

由于随机数在加密技术中大量用于安全密钥,因此它们必须不可预测。

因此,我们播种算法的方式直接影响它们产生的随机数的可预测性。

为了产生不可预测性, SecureRandom实现使用从累积的输入中收集的熵来播种其算法。这来自IO设备,例如鼠标和键盘。

在类Unix系统上,我们的熵累积在文件/dev/random

Windows上没有/dev/random文件。-Djava.security.egd设置为file:/dev/randomfile:/dev/urandom会导致默认算法(SHA1PRNG)使用本机Microsoft Crypto API播种。

10.虚拟机如何?

/dev/random收集很少或没有熵的虚拟机中运行。

虚拟机没有物理鼠标或键盘来生成数据,因此/dev/random的熵累积的速度要慢得多。这可能会导致我们的默认SecureRandom调用阻塞,直到有足够的熵使其生成不可预测的数字为止。

我们可以采取一些步骤来减轻这种情况。例如,在RedHat Linux中运行VM时,系统管理员可以配置虚拟IO随机数生成器virtio-rng 。这将从托管它的物理机读取熵。

11.故障排除技巧

如果我们的应用程序或其依赖项在生成SecureRandom编号时挂起,请考虑java.security.egd ,特别是在我们在Linux上运行以及在Java 8之前的版本上运行时。

我们的Spring Boot应用程序经常使用嵌入式**Tomcat** 。这使用SecureRandom来生成会话密钥。当我们看到Tomcat的“创建SecureRandom实例”操作花费5秒钟或更长时间时,我们应该为**java.security.egd** .

12.结论

在本教程中,我们学习了JVM属性java.security.egd是什么,如何使用它以及它具有什么作用。我们还发现,其影响可能会根据我们所运行的平台和所使用的Java版本而有所不同。

最后,我们可以在《 JCA参考指南》和“ SecureRandom API规范SecureRandom及其工作方式的更多信息,并了解有关urandom的一些神话。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *