Java 与NativePRNG vs SHA1 PRNG的安全随机性

Java 与NativePRNG vs SHA1 PRNG的安全随机性,java,random,cryptography,prng,Java,Random,Cryptography,Prng,我需要生成加密强随机数和字节数组。为此,我使用Java的SecureRandom类。但我不确定根据密码强度选择哪种PRNG算法 以下哪种情况会产生更不可预测的数字?或者他们是平等的 SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG") SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG") 此外,我们能够使用“SUN”提供程序生成这些实例(例如,Secu

我需要生成加密强随机数和字节数组。为此,我使用Java的
SecureRandom
类。但我不确定根据密码强度选择哪种PRNG算法

以下哪种情况会产生更不可预测的数字?或者他们是平等的

SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")
此外,我们能够使用“SUN”提供程序生成这些实例(例如,
SecureRandom.getInstance(“SHA1PRNG”、“SUN”)
)。这有区别吗

提前谢谢

从参考号开始:

Solaris/Linux的本机PRNG实现。它与 /dev/random和/dev/urandom,因此只有当这些文件 我们在场。否则,将使用SHA1PRNG而不是此类

SUN
提供程序可以用作默认提供程序(主要取决于提供程序的顺序)

TL;DR:当你不确定时使用,让系统来解决。可能用于长期密钥生成

不要期望随机数生成器在运行时应用程序中生成特定的输出序列,即使您自己为其设定种子也是如此


使用随机数生成器,总是很难说哪一个是最好的。Linux和大多数Unix都有一个经过深思熟虑的随机数生成器,因此使用
/dev/random
/dev/urandom
,也就是说。使用
/dev/random
的问题是它会阻塞,直到有足够的熵可用。所以我建议不要使用它,除非您对密钥生成有一些特殊要求


“SHA1PRNG”
使用哈希函数和计数器以及种子。该算法相对简单,但尚未得到很好的描述。一般认为它是安全的。由于它在启动期间只从一个系统生成器中进行种子培育,因此需要较少的内核调用,因此资源密集度可能较低-在我的系统上,它的运行速度大约是
“NativePRNG”
(配置为使用
/dev/uradom
)的9倍。两者似乎都只对我的双核Ubuntu笔记本电脑的一个内核征税(一次,它经常从一个内核切换到另一个内核,这可能是内核调度造成的)。如果您需要高性能,请选择此选项,特别是当
/dev/uradom
设备在特定系统配置中运行缓慢时

请注意,
“SHA1PRNG”
在已退役的Apache Harmony实现中与SUN provider中的不同(Oracle在标准Java SE实现中使用)。雅加达的版本也在旧版本的Android中使用。虽然我还没有能够做一个全面的审查,但它看起来不是很安全

编辑:我在这一点上没有半点错

请注意,
“SHA1PRNG”
不是Java SE的实现要求。在大多数运行时,它都会出现,但从代码中直接引用它会降低代码的可移植性


如今(Java 9以后的版本),OpenJDK和Oracle JDK还包含多个实现,它们被简单地称为
“DRBG”
。这实现了NIST在SP-108中指定的动态随机位生成器列表。这些也不是Java实现需求。但是,如果需要符合FIPS标准的随机数生成器,则可以使用它们

但是,他们不会改变这里的建议;如果开发人员认为这些比默认实现更好,那么他们只会将其作为默认实现。
SecureRandom
的契约不会改变:只需生成随机数即可。过去已经对默认算法进行了更改


一般来说,要求特定的提供者也不是一个好主意。指定提供者可能会损害互操作性;例如,并不是每个Java运行时都可以访问SUN提供程序——Android肯定没有。它还降低了应用程序在运行时的灵活性,也就是说,您不能将提供程序放在列表的更高位置并使用它

因此,仅当您依赖于某个提供者提供的功能时,才指示该提供者。例如,如果您有生成随机数的特定硬件设备,或者有经过FIPS认证的加密库,则可能需要指定提供程序。如果必须指定提供程序,那么最好将算法/提供程序作为应用程序的配置选项

本文还提出了不指定提供者的想法


因此,尽量避免选择任何特定的随机发生器。相反,只需使用空参数构造函数:让系统选择最佳的随机数生成器。如果您对长期密钥生成等有任何特定要求,可以使用Java 8及更高版本中的新可配置密钥

不要缓存的实例,只是让它们自己先进行种子设定,然后让VM来处理它们。我没有看到手术中有明显的不同


完全不使用
SecureRandom
时:

作为一般警告,我强烈建议不要将随机数生成器用于随机数生成以外的任何用途。即使你可以自己播种,即使你选择了Sun的Sha1PNG,也不要指望能够从随机数生成器中提取相同的随机数序列。因此,举一个例子,不要将它用于从密码派生密钥

如果确实需要重复序列,则使用流密码并使用密钥的种子信息和IV.加密由零组成的明文以检索伪随机值的密钥流。或者,您可以使用可扩展输出函数(XOF),如SHAKE128或SHAKE256(如果可用)