如果你想在Java中使用加密强大的随机数,你可以使用SecureRandom
.不幸的是,SecureRandom
可能会很慢.如果它/dev/random
在Linux上使用,它可以阻止等待足够的熵建立.你如何避免性能损失?
有没有人使用Uncommon Maths作为解决这个问题的方法?
任何人都可以确认JDK 6中已经解决了这个性能问题吗?
您应该能够在Linux上选择速度更快但安全性稍差的/ dev/urandom使用:
-Djava.security.egd=file:/dev/urandom
但是,这不适用于Java 5及更高版本(Java Bug 6202721).建议的解决方法是使用:
-Djava.security.egd=file:/dev/./urandom
(注意额外的/./
)
如果你想要真正的随机数据,那么不幸的是你必须等待它.这包括SecureRandom
PRNG 的种子.SecureRandom
尽管可以连接到互联网从特定网站下载种子数据,但不常见的数学不能以更快的速度收集真正的随机数据.我的猜测是,这不可能比/dev/random
现有的更快.
如果你想要一个PRNG,做这样的事情:
SecureRandom.getInstance("SHA1PRNG");
支持哪些字符串取决于SecureRandom
SPI提供程序,但您可以使用Security.getProviders()
和枚举它们Provider.getService()
.
Sun喜欢SHA1PRNG,所以它广泛使用.它并不像PRNG那样特别快,但PRNG只会处理数字,而不是阻止熵的物理测量.
例外情况是,如果您setSeed()
在获取数据之前未进行呼叫,则PRNG将在您第一次呼叫时自行播种next()
或nextBytes()
.通常使用来自系统的相当少量的真随机数据来做到这一点.此调用可能会阻止,但会使您的随机数源比"将当前时间与PID一起散列,添加27,并希望获得最佳"的任何变量更安全.如果您需要的只是游戏的随机数,或者如果您希望将来使用相同的种子进行测试时可重复使用流,则不安全的种子仍然有用.
在Linux上,默认实现SecureRandom
是NativePRNG
(这里是源代码),这往往非常慢.在Windows上,默认值是SHA1PRNG
,正如其他人指出的那样,如果明确指定,也可以在Linux上使用.
NativePRNG
不同于SHA1PRNG
和Uncommons Maths的AESCounterRNG,因为它不断地从操作系统接收熵(通过读取/dev/urandom
).其他PRNG在播种后不会获得任何额外的熵.
AESCounterRNG的速度比SHA1PRNG
IIRC 快10倍,而IIRC本身的速度要快2到3倍NativePRNG
.
如果您需要更快的PRNG,在初始化后获取熵,请查看是否可以找到Fortuna的Java实现.Fortuna实现的核心PRNG与AESCounterRNG使用的相同,但也有一个复杂的熵池和自动重播系统.
许多Linux发行版(主要是基于Debian的)将OpenJDK配置为/dev/random
用于熵.
/dev/random
根据定义是慢的(甚至可以阻止).
从这里你有两个选项来解锁它:
改善熵,或
降低随机性要求.
选项1,改善熵
要获得更多的熵/dev/random
,请尝试使用hasged守护进程.它是一个持续收集HAVEGE熵的守护进程,也可以在虚拟化环境中工作,因为它不需要任何特殊硬件,只需要CPU本身和时钟.
在Ubuntu/Debian上:
apt-get install haveged update-rc.d haveged defaults service haveged start
在RHEL/CentOS上:
yum install haveged systemctl enable haveged systemctl start haveged
选项2.降低随机性要求
如果由于某种原因上面的解决方案没有帮助,或者你不关心加密强随机性,你可以切换到/dev/urandom
相反,这保证不会阻止.
要全局执行此操作,请编辑jre/lib/security/java.security
要使用的默认Java安装中的文件/dev/urandom
(由于需要将其指定为另一个错误/dev/./urandom
).
像这样:
#securerandom.source=file:/dev/random securerandom.source=file:/dev/./urandom
然后,您将不必在命令行上指定它.
注意:如果您进行加密,则需要良好的熵.一个例子 - android PRNG问题降低了比特币钱包的安全性.
我SecureRandom
在无头Debian服务器上一次调用阻塞大约25秒时遇到了类似的问题.我安装了haveged
守护进程以确保/dev/random
在无头服务器上保持充足,你需要这样的东西来生成所需的熵.我SecureRandom
现在的电话可能需要几毫秒.
如果你想要真正"加密强"的随机性,那么你需要一个强大的熵源./dev/random
很慢,因为它必须等待系统事件收集熵(磁盘读取,网络数据包,鼠标移动,按键等).
更快的解决方案是硬件随机数生成器.您的主板可能已经内置了一个; 查看hw_random文档,了解有关确定是否拥有它以及如何使用它的说明.rng-tools包中包含一个守护进程,它将硬件生成的熵提供给/dev/random
.
如果您的系统上没有HRNG,并且您愿意牺牲熵强度以获得性能,那么您将希望为PRNG提供数据/dev/random
,并让PRNG完成大部分工作.SP800-90中列出了几个经NIST批准的PRNG, 它们很容易实现.
您所参考的问题/dev/random
不在于SecureRandom
算法,而在于它使用的随机性来源。两者是正交的。您应该找出两者中的哪一个正在减慢您的速度。
您明确链接的“罕见的数学”页面提到它们没有解决随机性的问题。
您可以尝试使用不同的JCE提供程序,例如BouncyCastle,以查看它们的实现SecureRandom
是否更快。
简短的搜索还显示了用Fortuna替换默认实现的Linux补丁。我对此了解不多,但是欢迎您进行调查。
我还应该提到,虽然使用执行SecureRandom
不当的算法和/或随机性源非常危险,但是您可以使用的自定义实现来滚动自己的JCE Provider SecureRandomSpi
。您将需要与Sun进行合作,以使您的提供商签名,但是实际上非常简单。他们只需要您传真给他们一张表格,说明您知道美国对加密库的出口限制。
有一个工具(至少在Ubuntu上)可以将人工随机性输入系统.命令很简单:
rngd -r /dev/urandom
你可能需要前面的sudo.如果您没有rng-tools软件包,则需要安装它.我试过这个,这绝对帮助了我!
来源:亚光vs世界
我遇到了同样的问题.在使用正确的搜索条款进行Google搜索之后,我在DigitalOcean上看到了这篇精彩的文章.
我只是引用了这篇文章中的相关部分.
基于HAVEGE原理,并且之前基于其相关联的库,hasged允许基于处理器上的代码执行时间的变化来生成随机性.由于一段代码几乎不可能花费相同的执行时间,即使在同一硬件上的相同环境中,运行单个或多个程序的时间也应该适合种子随机源.在反复执行循环后,使用处理器的时间戳计数器(TSC)中的差异,伪造的实现会使系统的随机源(通常为/ dev/random)变为种子
请按照本文中的步骤操作.https://www.digitalocean.com/community/tutorials/how-to-setup-additional-entropy-for-cloud-servers-using-haveged
我在这里贴了它