带有NativePRNG和SHA1PRNG的SecureRandom

ovu*_*tin 35 java random cryptography prng

我需要生成加密强大的随机数和字节数组.为此,我正在使用Java的SecureRandom类.但我不确定在加密强度方面选择哪种PRNG算法.

以下哪个实例会产生更难以预测的数字?或者他们是平等的?

SecureRandom nativePrng = SecureRandom.getInstance("NativePRNG")
SecureRandom sha1Prng = SecureRandom.getInstance("SHA1PRNG")
Run Code Online (Sandbox Code Playgroud)

此外,我们能够使用"SUN"提供程序(例如SecureRandom.getInstance("SHA1PRNG", "SUN"))生成这些实例.这会有所作为吗?

提前致谢.

Maa*_*wes 56

TL; DR:new SecureRandom()当你不确定时使用,让系统搞清楚.可能SecureRandom.getInstanceStrong()用于长期密钥生成.

不要指望随机数生成器在运行时应用程序中生成特定的输出序列,即使您自己播种也不行.


对于随机数生成器,总是很难说哪个是最好的.Linux和大多数的Unix有一个很深思熟虑的随机数生成器,所以它不会伤害到使用/dev/random/dev/urandom,即"NativePRNG".使用问题/dev/random是它会阻塞,直到有足够的熵可用.所以除非你对密钥生成有一些特殊要求,否则我会反对它.


"SHA1PRNG"使用哈希函数和计数器以及种子.该算法相对简单,但尚未得到很好的描述.通常认为它是安全的.由于它只是在启动期间来自其中一个系统生成器的种子,因此需要较少的内核调用,因此可能会减少资源消耗 - 在我的系统上运行速度比"NativePRNG"(配置使用/dev/urandom)快9倍.两者似乎只对我的双核Ubuntu笔记本电脑的一个核心征税(一次,它经常从一个核心切换到另一个核心,这可能是内核调度,这是应该责备的).如果您需要高性能,请选择此项,特别是如果/dev/urandom设备在特定系统配置上运行缓慢.

请注意,已废弃的 Apache Harmony实现中的"SHA1PRNG"现有内容与SUN提供程序中的内容不同(Oracle在标准Java SE实现中使用).雅加达的版本也用于旧版本的Android.虽然我无法进行全面审查,但它看起来并不十分安全.

编辑:我是不是错了一半这个,SHA1PRNG已经被证明不是伪随机的版本<4.2.2在这里.

要注意的是"SHA1PRNG"不是对Java SE的实现要求.在大多数运行时它将存在,但直接从代码中引用它将使您的代码更不便携.


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

因此,只有在您依赖其提供的某项功能时才指明提供商.例如,如果您具有生成randoms的特定硬件设备,或者已获得FIPS认证的加密库,则可能需要指定提供程序.如果必须指定提供程序,那么为算法/提供程序提供应用程序的配置选项可能是个好主意.

Android开发人员安全博客中也提供了不指定提供程序的想法.


所以尽量不要选择任何特定的随机发生器.相反,只需转到空参数构造函数:"DRBG"让系统选择最佳随机数生成器.SecureRandom如果您对长期密钥生成有任何特定要求,则可以使用Java 8及更高版本中的新配置.

不要缓存实例new SecureRandom(),只是让它们最初自己播种并让VM处理它们.我没有看到明显的操作差异.


何时不使用SecureRandom.getInstanceStrong():

作为一般性警告,我强烈建议不要将随机数生成器用于除随机数生成之外的任何其他内容.即使你可以自己播种它,即使你选择Sun的SHA1PRNG,不要指望能够从随机数发生器抽取随机数的相同的序列.因此,不要将它用于密码的密钥派生,仅举一个例子.

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

您可能需要考虑一个不同的,非安全的随机数生成器,而不是SecureRandom如果可用的RNG提供的性能不足以及安全性不是问题.没有SecureRandom实现将像非安全随机数生成器一样快,例如Mersenne Twister算法或SecureRandom类实现的算法.这些已针对简单性和速度而非安全性或质量进行了优化.

  • 如果你只是盲目地信任系统选择的任何SecureRandom服务,它不会打开安全漏洞吗? (3认同)
  • 不,不是真的。如果系统不可信,随机数生成器只是问题的一小部分。除此之外,其他随机数生成器通常由操作系统的随机数生成器播种。所以他们还是依赖于系统RNG的安全性。解决这个问题的唯一方法是拥有自己的熵源。较新的英特尔芯片具有 RDRAND 指令,但在 Java 的情况下,您首先需要在使用它之前进入本机。 (2认同)
  • @MaartenBodewes答案很棒,但我更喜欢查看自己的来源,这里是JDK8源代码:[sun.security.provider.SecureRandom](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/ tip/src/share/classes/sun/security/provider/SecureRandom.java),[sun.security.provider.NativePRNG](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip /src/solaris/classes/sun/security/provider/NativePRNG.java),[sun.security.provider.SeedGenerator](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/ SRC /共享/班/阳光/安全/供应商/ SeedGenerator.java) (2认同)
  • @FrederickNord 1)算法是未知的并且可能(并且确实)在实现之间改变并且种子可能不被用作仅对状态的输入,算法可以由操作系统预先播种.2)使用PBKDF2,功能构建到Java/JCE中. (2认同)
  • @Brice正如已经指出的那样 - **未指定算法的实现可能会在版本**之间发生变化.您最终必须依赖JCE和JavaDoc文档.在您不这样做之后,请务必查看源代码,看看它是否已按预期实现.购买汽车时,你最初不会在引擎盖下测量CC,对吧?那么,除了大众汽车当然. (2认同)

nit*_*gar 5

作为参考。在这里

Solaris / Linux的本机PRNG实现。它与/ dev / random和/ dev / urandom交互,因此仅在存在那些文件的情况下可用。否则,将使用SHA1PRNG代替此类。

SUN提供者可被用作默认(主要取决于其存在的提供者的数量级上)。