我需要生成加密强大的随机数和字节数组。为此,我使用了Java的SecureRandom
类。但我不确定在加密强度方面选择哪种PRNG算法。
以下哪个实例会产生更难以预测的数字?或者他们是平等的?
SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")
此外,我们可以使用" SUN"生成这些实例。提供者(例如SecureRandom.getInstance("SHA1PRNG", "SUN")
)。这会有所作为吗?
提前致谢。
答案 0 :(得分:52)
TL; DR:如果您不确定,请使用new SecureRandom()
让系统弄明白。可能使用SecureRandom.getInstanceStrong()
进行长期密钥生成。
不要指望随机数生成器在运行时应用程序中生成特定的输出序列,即使您自己播种也不行。
使用随机数生成器总是很难说哪个是最好的。 Linux和大多数Unix都有一个经过深思熟虑的随机数生成器,所以使用/dev/random
或/dev/urandom
,即"NativePRNG"
并不会有什么坏处。使用/dev/random
的问题在于它会阻塞,直到有足够的熵可用。所以除非你对密钥生成有一些特殊要求,否则我会反对它。
"SHA1PRNG"
使用哈希函数和计数器以及种子。该算法相对简单,但尚未得到很好的描述。通常认为它是安全的。由于它只是在启动期间来自其中一个系统生成器,因此需要较少的内核调用,因此可能会减少资源密集度 - 在我的系统上运行速度比"NativePRNG"
快9倍(配置为使用/dev/urandom
)。两者似乎只对我的双核Ubuntu笔记本电脑的一个核心征税(一次,它经常从一个核心切换到另一个核心,这可能是应该责备的内核调度)。如果您需要高性能,请选择此项,特别是如果/dev/urandom
设备在特定系统配置上运行缓慢。
请注意,已淘汰 Apache Harmony实施中的"SHA1PRNG"
与SUN提供程序中的"SHA1PRNG"
不同(Oracle在标准Java SE实现中使用)。雅加达的版本也用于旧版本的Android。虽然我还没有能够进行全面审查,但它看起来并不安全。
编辑:我对此没有错,SHA1PRNG has been shown not to be pseudo-random for versions < 4.2.2以及更多here。
请注意SecureRandom
不是Java SE的实施要求。在大多数运行时它将存在,但直接从代码引用它将使您的代码不那么便携。
一般来说,要求特定的提供商也不是一个好主意。指定提供商可能会损害互操作性;并非每个Java运行时都可以访问SUN提供商 - 例如Android肯定没有。它还使您的应用程序在运行时不太灵活,即您不能将提供程序放在列表中更高的位置并使用它。
因此,如果您依赖其提供的某项功能,则仅指明提供商。例如,如果您具有生成randoms的特定硬件设备,或者已获得FIPS认证的加密库,则可能需要指定提供程序。如果您必须指定提供者,那么为算法/提供者提供应用程序的配置选项可能是个好主意。
未指定提供者的想法也存在于此Android developer Security Blog。
中所以尽量不要选择任何特定的随机发生器。相反,只需转到空参数构造函数:new SecureRandom()
并让系统选择最佳随机数生成器。如果您对Java 8及更高版本有任何特定要求,则可以在Java 8及更高版本中使用新的可配置SecureRandom.getInstanceStrong()
。长期密钥生成。
不要缓存SecureRandom
的实例,让他们最初自己播种并让VM处理它们。我没有看到明显的操作差异。
完全不使用SecureRandom
时:
作为一般性警告,我强烈建议不要将随机数生成器用于除随机数生成之外的任何其他内容。即使您可以自己播种,即使您选择了Sun的SHA1PRNG,也不能指望能够从随机数生成器中提取相同的随机数序列。因此,不将其用于密码的密钥派生,仅举一例。
如果确实需要重复序列,则使用流密码并使用密钥和IV的种子信息。加密由零组成的明文以检索伪随机值的密钥流。或者,您可以使用可扩展输出功能(XOF),例如SHAKE128或SHAKE256(如果可用)。
如果可用的RNG提供的性能不足且安全性不是问题,您可能需要考虑使用不同的非安全随机数生成器而不是SecureRandom
。没有SecureRandom
实现将与非安全随机数生成器一样快,例如Mersenne Twister算法或Random
类实现的算法。这些已针对简单性和速度而非安全性或质量进行了优化。
可以扩展{{1}}类并将确定性的种子随机实现插入到库调用中。这样,库就会检索具有良好定义输出的伪随机数生成器。然而,应该注意,随机数发生器可以通过算法以不同的方式使用。例如。 RSA可以切换到更好的查找素数的方法,并且可以使用经过调整或直接计算的奇偶校验位生成DES密钥。
答案 1 :(得分:4)
来自参考。 here:
Solaris / Linux的本机PRNG实现。它与...互动 / dev / random和/ dev / urandom,因此只有那些文件才可用 存在。否则,使用SHA1PRNG而不是此类。
SUN
提供程序可能用作默认值(主要取决于提供程序的存在顺序)。