如何处理缓慢的安全随机生成器?

2022-08-31 06:39:21

如果你想要一个 Java 中加密强的随机数,你可以使用 .不幸的是,可能非常慢。如果它在Linux上使用,它可以阻止等待足够的熵建立起来。如何避免性能损失?SecureRandomSecureRandom/dev/random

有没有人使用不常见的数学作为这个问题的解决方案?

任何人都可以确认这个性能问题已经在JDK 6中解决了吗?


答案 1

您应该能够在Linux上选择更快但安全性稍低的/dev/urandom,使用:

-Djava.security.egd=file:/dev/urandom

但是,这不适用于Java 5及更高版本(Java Bug 6202721)。建议的解决方法是使用:

-Djava.security.egd=file:/dev/./urandom

(注意额外/./)


答案 2

如果你想要真正的随机数据,那么不幸的是,你必须等待它。这包括 PRNG 的种子。不常见的数学不能比 收集真正的随机数据更快,尽管它可以连接到互联网从特定网站下载种子数据。我的猜测是,这不太可能比可用的地方更快。SecureRandomSecureRandom/dev/random

如果你想要一个PRNG,请执行如下操作:

SecureRandom.getInstance("SHA1PRNG");

支持哪些字符串取决于 SPI 提供程序,但您可以使用 和 枚举它们。SecureRandomSecurity.getProviders()Provider.getService()

Sun喜欢SHA1PRNG,所以它随处可见。随着PRNGs的发展,它并不是特别快,但PRNGs只会处理数字,而不是阻塞熵的物理测量。

例外情况是,如果在获取数据之前未调用,则 PRNG 将在您第一次调用 或 时自行播种一次。它通常会使用来自系统的相当少量的真正随机数据来执行此操作。此调用可能会阻塞,但会使随机数的来源比“将当前时间与PID一起散列,添加27,并希望最好”的任何变体都更安全。但是,如果您只需要游戏的随机数,或者如果您希望将来使用相同的种子进行测试时流是可重复的,那么不安全的种子仍然很有用。setSeed()next()nextBytes()