Java: 使用 DRBG SecureRandom 时如何设置随机数?

Java: How do I set the nonce when using DRBG SecureRandom?

Java 9引入了一种新的SecureRandom,叫做DRBG。我想用它来确定性地生成随机数。问题是它在内部使用一个随机数,它总是在变化,所以我不会为相同的种子得到相同的数字。它确实有一个内部选项来设置该随机数,但我找不到任何 public 方法可以实现这一点。我该如何更改该随机数?

SecureRandom class 仍然声明:

Additionally, SecureRandom must produce non-deterministic output.

虽然列出的 DRBG 方案是确定性的,但它们仍将由运行时环境播种,运行时环境通常从操作系统中检索熵。


在这方面,"DRBG" 的含义可能有些混淆。尽管底层算法本质上是确定性的,但这仅意味着它依赖于种子中的熵来生成比特流。这些随机位 在计算上 与随机无法区分,即使它们只包含有限数量的熵。如果对手可以猜出种子,那么整个流就会为人所知。但是如果种子包含足够的熵那么这在实践中是不可能的。

"DRBG" 只是指一种预先配置且定义明确的 NIST 标准化算法(可以在 的答案中看到)。因此它与 "SHA1PRNG" 不同; "SHA1PRNG" 是 Sun 的专有算法,完全未指定,其他实现(例如 Android 中的实现)既不同又不安全。 Java 的早期版本确实允许您从 "SHA1DRBG" 中确定性地生成安全的随机值,您在 之前播种它 您从中检索任何输出。


可以自己创建一个SecureRandomSpi确定性的,但是你会违反合同SecureRandomSpi.如果你这样做,你当然必须实施一个提供者。

实施 SecureRandomSpi 是正确的方法,但请注意,您实际上可以从 SecureRandom 继承,所以有一个捷径,如果有点 hack。

要获得快速、确定性的 "random" 实现,您可能需要在底层使用流密码。这比 DRBG 更有效,而且它没有功能,例如重新播种 你绝对可以没有。可能您还需要实施 KDF 来生成 DRBG 所需的密钥。

如果你采用这种方式,请明确指定你的协议,否则开发人员将不得不对你的代码进行逆向工程才能获得所使用的算法。