在 Java 中仅使用 /dev/random

2022-09-03 06:23:08

我有一个 HRNG,它在 Debian Wheezy 中提供 /dev/random。它很快,所以阻止不会成为问题。现在,在我的Java代码中,我想确保我在/dev/random中使用熵,并且只使用该熵。我没有兴趣使用/dev/urandom中的任何东西。

我想强制Java的SecureRandom只从/dev/random获取熵。根据我对目前实现的理解,当调用getBytes()时,它使用/dev/urandom,但是当调用generationSeed()时,它使用/dev/random。我不明白为什么。

据我所知,从 /dev/urandom 中阅读的唯一原因是,如果你更喜欢速度而不是安全性。我想要最高质量的熵。/dev/urandom 就是做不到。

那么,如何强制 SecureRandom 仅使用 /dev/random(由 HRNG 提供),并且从不接触来自劣质 PRNG 的任何内容(如 /dev/urandom)?

谢谢。


答案 1

这个答案假设你知道自己在做什么。在其他情况下,应尽量减少使用 /dev/random

/dev/random行为类似于普通文件,因此任何可以读取任何文件的程序都可以从 中读取。您可能知道直接从它输出随机数据,如果它这样做的速度足够快,您可能实际上想要使用它。因此,如果其他所有方法都失败了,您将始终能够直接读取该文件.../dev/randomcat /dev/random

因此,如果您查看SecureRandom的来源,您会发现它使用SecureRandomSpi进行实际工作。事实证明,NativePRNG.Blocking可以做你想要的:

一个类似 NativePRNG 的类,它对种子和随机材料使用 /dev/random。请注意,它不尊重egd属性,因为我们无法知道这些品质是什么。这与外部 NativePRNG 类非常相似,可最大程度地减少对现有实现的序列化的任何中断。起始时间:1.8

问题可能是 ,如果您还不能使用 Java 8,则可以将其向后移植到较早的平台。源代码毕竟是可用的。Since 1.8

所以,现在让我们把它放在代码中:

我们必须选择要使用的特定实现。为了找到确切的名称,我们使用以下行输出所有可用的服务:

for (Provider p: Security.getProviders()) p.getServices().forEach(System.out::println);

然后我们在那里搜索,我们找到愚蠢的条目:Native

SUN: SecureRandom.NativePRNGBlocking -> sun.security.provider.NativePRNG$Blocking

这意味着我们可以像下面这样实例化对象以执行所需的操作:SecureRandom

SecureRandom sr = SecureRandom.getInstance("NativePRNGBlocking", "SUN");

一个简单的测试

byte[] b = new byte[10000];
sr.nextBytes(b);
System.out.println(Arrays.toString(b));

需要很长时间,我不得不降低读取字节的数量。如果它对您有用,恭喜您,您正在阅读!/dev/random

但请注意,此类位于包中,但不能保证在任何地方都可用。例如,它可能无法在Android上运行。如果这很好,那么这个解决方案将起作用,否则你应该直接把它作为一个文件读取。sun.security.provider

不要在 Android 上从 /dev/random 中读取。请。


答案 2

推荐