SecureRandom 会减少伪随机数据的熵吗?

Does SecureRandom reduce entropy of pseudo-random data?

我想知道 Docker 容器中的随机(或伪随机)序列生成, 但遇到了另一个有趣的行为。

直接从 /dev/urandom 读取 8000000 字节并使用 ENT 测试结果如下:

Entropy = 7.999976 bits per byte.

Optimum compression would reduce the size
of this 8000000 byte file by 0 percent.

Chi square distribution for 8000000 samples is 262.08, and randomly
would exceed this value 36.69 percent of the times.

Arithmetic mean value of data bytes is 127.5337 (127.5 = random).
Monte Carlo value for Pi is 3.139911785 (error 0.05 percent).
Serial correlation coefficient is -0.000101 (totally uncorrelated = 0.0).

但是在生成 1000000 个 DES 密钥的情况下,ENT 的输出给出以下内容:

Entropy = 6.999990 bits per byte.

Optimum compression would reduce the size
of this 8000000 byte file by 12 percent.

Chi square distribution for 8000000 samples is 8000217.63, and randomly
would exceed this value less than 0.01 percent of the times.

Arithmetic mean value of data bytes is 127.4870 (127.5 = random).
Monte Carlo value for Pi is 3.145497786 (error 0.12 percent).
Serial correlation coefficient is 0.000033 (totally uncorrelated = 0.0).

用于生成 1000000 个密钥的代码:

KeyGenerator des = KeyGenerator.getInstance("DES");
IntStream.range(0, 1_000_000).forEach(j -> {
    SecretKey secretKey = des.generateKey();
    System.out.write(secretKey.getEncoded());
});

熵较低,卡方分布表明分布不再随机。

所以我想知道 SecureRandom Java 的实现是否只是减少熵并直接从中读取值 urandom 可能是更好的选择。

这里没有任何内容表明 SecureRandom 有问题。

您将获得 DES 密钥的 "only 7 bits of entropy per byte" 结果,因为这是 DES 密钥所具有的。 DES 密钥长 8 个字节,但 64 位中只有 56 位(即每字节 7 位)是随机的。每个字节中的第 8 位保留用作该字节的奇偶校验位。奇偶校验位的值显然与其他 7 位的值高度相关,因此该位根本不是随机的。有关更多背景信息,请参阅 DES at Wikipedia

如果您使用密钥生成器为使用全随机密钥的算法再次尝试测试,您应该会得到更令人欣慰的结果,例如 "AES"。