我知道如果我们声明:
SecureRandom random=new SecureRandom();
初始化默认算法以生成随机数NativePRNG
,其中/dev/random
读取seed
以生成真正的随机seed
。现在我们有一个160位大小的真正随机random.nextBytes(bytes);
,但我很困惑当我们调用bytes
时会发生什么。它如何从seed
生成/dev/random
,是否会再次阅读{{1}}或其他内容。
感谢。
N.B。: 我在linux / MAC框中寻找java 7中的默认行为。
答案 0 :(得分:1)
来自Java API文档:
许多SecureRandom实现采用伪随机的形式 数字生成器(PRNG),这意味着它们使用确定性 算法从真随机种子产生伪随机序列。 其他实现可能产生真正的随机数,还有其他实现 可以结合使用这两种技术。
因此,nextBytes(bytes)
是否从/dev/random
返回真正的随机字节,或者它是否返回从真随机种子生成的伪随机数取决于。第二种情况意味着使用初始随机种子,通过对SecureRandom
的任何调用生成确定性但看似随机(因此,伪随机)数字序列。
Java 7允许指定可配置的PRNG源,但在Linux上,默认值为NativePRNG
,在Windows SHA1PRNG
上。您也可以在Linux上指定SHA1PRNG
,但默认选项NativePRNG
更好。 SHA1PRNG
通过使用SHA1生成PRNG位和字节。在Linux(以及可能的其他机制为“NativePRNG
”的Unix)上,算法从/dev/random
和/dev/urandom
读取,只要有足够的熵可用于其中任何一个。为了完整起见,请从random
上的Linux手册页:
来自/ dev / urandom设备的读取不会阻止等待更多 熵。结果,如果没有足够的熵 熵池,返回值理论上容易受到影响 对驱动程序使用的算法进行加密攻击。
因此,至少在Linux上,SecureRandom
会有一定数量的真正随机输出,直到/dev/random
由于熵不足而阻塞,然而如果您请求过多的随机位,它们最终将由底层/dev/urandom
机制开始生成,这些机制可能在PRNG中使用SHA1或其他加密散列算法。
最好创建一个SecureRandom
,而不是自己指定任何显式种子,因为它会自行播种(默认情况下通过/dev/random
和/dev/urandom
播放{在Linux上{1}}有一个好种子。每隔几分钟调用NativePRNG
,即使是大量字节,也几乎不会在任何情况下成为问题。即使您正在使用nextBytes(bytes)
并且它通过像SHA-1这样的东西从NativePRNG
获取伪随机字节,它的输出仍然非常难以预测。
如果你要求千兆字节的随机性,重新种子可能是好的,要么使用/dev/urandom
本身的一些输出,要么提供你自己的种子。请注意,向SecureRandom
提供任何种子都应该是安全的,因为setSeed()
通过将您提供的种子和之前的种子提供给SHA-1或其他加密哈希算法来内部增强当前种子。但是,最好在不提供种子的情况下创建初始SecureRandom
。