且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

SecureRandom与NativePRNG与SHA1PRNG

更新时间:2023-01-11 21:18:14

TLDR:use new SecureRandom()

TLDR: use new SecureRandom() when you're not sure and let the system figure it out.

对于随机数生成器,总是很难说哪个是***的。 Linux和大多数Unix有一个非常周详的随机数生成器,所以它不伤害使用 / dev / random / dev / urandom ,即NativePRNG。使用 / dev / random 的问题是阻塞,直到有足够的熵可用。因此,除非您对密钥生成有一些特殊要求,否则我会建议您。

With random number generators it is always hard to say which is best. Linux and most Unixes have a pretty well thought out random number generator, so it doesn't hurt to use /dev/random or /dev/urandom, i.e. "NativePRNG". Problem with using /dev/random is that it blocks until enough entropy is available. So I would advice against it unless you've got some special requirements with regards to key generation.

SHA1PRNG使用散列函数和计数器以及种子。该算法相对简单,但它没有被很好地描述。它通常被认为是安全的。因为它只是在启动期间从一个系统生成器的种子,因此需要较少的内核调用可能是较少资源密集型 - 在我的系统上运行约9倍的速度比NativePRNG / code>(配置为使用 / dev / urandom )。这两个似乎只对我的双核ubuntu笔记本电脑的一个核心(一次,它经常从一个核心切换到另一个,这可能是内核调度,这是责怪)。如果你需要高性能,选择这个,特别是如果你的 / dev / urandom 很慢。

"SHA1PRNG" uses a hash function and a counter, together with a seed. The algorithm is relatively simple, but it hasn't been described well. It is generally thought of to be secure. As it only seeds from one of the system generators during startup and therefore requires fewer calls to the kernel it is likely to be less resource intensive - on my system it runs about 9 times faster than the "NativePRNG" (which is configured to use /dev/urandom). Both seem to tax only one core of my dual core Ubuntu laptop (at a time, it frequently switched from one core to another, that's probably kernel scheduling that's which is to blame). If you need high performance, choose this one, especially if your /dev/urandom is slow.

Apache Harmony实现中的退役的中的SHA1PRNG不同于SUN提供程序中的一个(在标准Java SE实现)。雅加达的版本也在旧版本的Android中使用。虽然我无法进行全面审查,但看起来并不安全。

Note that the "SHA1PRNG" present in the retired Apache Harmony implementation is different from the one in the SUN provider (used by Oracle in the standard Java SE implementation). The version within Jakarta was used in older versions of Android as well. Although I haven't been able to do a full review, it doesn't look to be very secure.

个人我会尽量避免指定任何随机生成器。我只需去空参数构造函数: new SecureRandom(),让系统选择***的随机数生成器。如果您对Java 8中有任何特定要求,您可以使用新的可配置 SecureRandom.getInstanceStrong()。长期密钥生成。不要缓存 SecureRandom 的实例,只是让他们初始种子,让VM处理它们。我没有看到明显的操作差异。

Personally I would try and refrain from specifying any random generator at all. I would simply go for the empty argument constructor: new SecureRandom() and let the system choose the best random number generator. You can use the new configurable SecureRandom.getInstanceStrong() in Java 8 if you have any specific requirements for e.g. long term key generation. Don't cache instances of SecureRandom, just let them seed themselves initially and let the VM handle them. I did not see a noticeable difference in operation.

一般来说,指定一个提供者并不是一个好主意。指定提供程序可能会损害互操作性;不是每个Java运行时都可以访问例如SUN提供者。这也使得您的应用程序在运行时更不灵活,即您不能将提供程序在列表中更高的地方,而改为使用。

In general it's not a good idea to specifically specify a provider. Specifying a provider may hurt interoperability; not every Java runtime may have access to the SUN provider for instance. It also makes your application less flexible at runtime, i.e. you cannot put a provider higher in the list and use that instead.

如果您依赖于一个提供程序的功能。例如,如果您具有生成随机数的特定硬件设备或已通过FIPS认证的加密库,则可能需要指定提供程序。如果你必须指定一个提供者,那么为你的应用程序提供一个配置选项是一个好主意。

Only specify a provider if you are dependent on one of the features that it supplies. For instance, you might want to specify a provider if you have a specific hardware device that generates the randoms, or a cryptographic library that has been FIPS certified. It's probably a good idea to make the algorithm/provider a configuration option for your application if you have to specify a provider.

稍微关闭主题:何时不使用 SecureRandom

Slightly off topic: when not to use SecureRandom:

我强烈建议反对使用随机数发生器除了随机数生成。即使你可以自己种子,即使你选择Sun的SHA1PRNG,不要指望能够从随机数生成器提取相同的随机数序列

As a general warning I strongly advice against using the random number generator for anything other than random number generation. Even if you can seed it yourself and even if you choose Sun's SHA1PRNG, don't count on being able to extract the same sequence of random numbers from the random number generator. So do not use it for key derivation from passwords, to name one example.

如果你需要一个重复序列,那么使用它来密码导出密码。并使用种子信息作为键和IV。加密由零组成的纯文本以检索伪随机值的密钥流。或者,您可以使用可扩展输出函数(XOF),例如SHAKE128或SHAKE256(如果可用)。

If you do require a repeating sequence then use a stream cipher and use the seed information for the key and IV. Encrypt plaintext consisting of zeros to retrieve the key stream of pseudo random values. Alternatively you could use a extendable-output function (XOF) such as SHAKE128 or SHAKE256 (where available).

显然,对于不需要安全的超高速操作,不要使用 SecureRandom ;它不会像其他确定性随机数发生器那样快,例如基于Mersenne Twister算法的那些。

Obviously, for very high speed operation that doesn't require security, don't use SecureRandom; it won't be as fast as other deterministic random number generators such as those based upon the Mersenne Twister algorithm.