过去一年有很多关于密码学中可利用的弱点的新闻,这些弱点源于弱随机数生成器。在某些情况下,这是开发人员的疏忽,在其他情况下,是情报组织故意破坏安全 RNG 生成的标准。
Oracle 的 JavaVM 中使用的SecureRandom随机数生成器的实现如何?当您不指定一个时,它使用什么算法?该算法及其实现是否足够安全以用于密码学?
过去一年有很多关于密码学中可利用的弱点的新闻,这些弱点源于弱随机数生成器。在某些情况下,这是开发人员的疏忽,在其他情况下,是情报组织故意破坏安全 RNG 生成的标准。
Oracle 的 JavaVM 中使用的SecureRandom随机数生成器的实现如何?当您不指定一个时,它使用什么算法?该算法及其实现是否足够安全以用于密码学?
JDK 完整源代码(不仅是标准类,还包括 Sun 特定类和 C++ 本机代码)曾经在“研究许可”下可用,我的磁盘上有一个副本,用于 JDK 1.6(我假设现在你会去 OpenJDK)。
我们看到创建一个java.security.SecureRandom
实例意味着调用默认的 PRNG,它恰好是 Sun 特定的类sun.security.provider.SecureRandom
。
PRNG 是从中播种的sun.security.provider.SeedGenerator
,反过来将尝试依赖操作系统提供的内容,即/dev/urandom
或/dev/random
在类 Unix 系统(如 Linux)CryptGenRandom()
上,Windows 上的 CryptoAPI。如果这些东西不可用(或从 JVM 的配置中停用),则将通过计时操作系统在线程之间切换上下文的速度来提取种子;这是一种后备机制,很少(如果有的话)触发。
种子使用似乎是基于 SHA-1 的自定义自制 PRNG 进行扩展。它是这样工作的:
有一种机制可以确保s在某些时候确实发生了变化;如果更新后s似乎没有改变,那么它的第一个字节被强制递增。这永远不会被调用;这种情况发生的概率是2 -160,并且用特殊的种子强制它需要打破 SHA-1 的原像抗性,我们不知道该怎么做。
从密码学上讲,这并不可怕。平均而言,它应该在大约2 80 个块之后达到一个周期,并且该周期应该具有相同的平均长度;这是很多(大约 2400 亿千兆字节),所以这很好。如果 SHA-1 是随机预言机,那么只要攻击者不能枚举 160 位空间(实际上他们不能)并且给定的种子不用于产生超过 2400 亿千兆字节(它不会,不会在任何合理甚至不合理的时间内)。我们知道 SHA-1不是随机预言机,但它看起来仍然足够随机。
就我个人而言,我不认为这个 PRNG 对加密使用有问题。它没有“魔法常数”,因此不太可能被后门。它的一个不好的部分是它是非标准的,因此未被充分研究。
如果(当)我需要在 Java 中具有对正式密码学来说足够好的随机性(即好,并且对于监管目的也明显java.security.SecureRandom
好),那么我用它来生成一个初始种子(至少 16 个字节),我然后运行 HMAC_DRBG(在NIST SP800-90A中指定)(同一出版物包含险恶名声的 Dual_EC_DRBG,但 HMAC_DRBG 仍然被密码学家认为是好的和干净的)。