Lon*_*zak 5 java security random encryption keytool
我们使用与java安装捆绑在一起的keytool来生成用于执行非对称RSA加密的密钥.根据最近发生的事件,有人问我在java keytool的引擎下发生了什么.特别是关于结果数字的随机性.(例如"为什么没有任何随机用户输入像鼠标移动或键盘输入?"
那么创建密钥的java keytool的"随机源"是什么?
我自己做了一个快速的研究,但我发现的唯一信息是2000 年的帖子:
- keytool.exe使用SecureRandom作为其随机数的基础.
- SecureRandom的Sun提供商遵循IEEE P1363标准,
- Sun SecureRandom提供商遵守NIST的FIPS PUB 140-1第4.11节.
- SecureRandom的Sun提供程序将其他熵源与线程争用进程的结果混合在一起.其中包括当前时间,VM内存使用状态,系统属性和文件系统活动.
- 在没有JIT的情况下,该算法可能表现不佳,因此我们正在考虑提供替代供应商,该供应商将利用对熵收集设备(例如/ dev/random或Pentium III热噪声RNG)的平台特定支持.
但是这已经回到了2K,所以你们中的某些人可能会对此有所了解并提供上述更新(在Java7中有所不同吗?).根据你的回答,如果你建议改用另一个像bouncycastle这样的提供商,我会被强调...
更新:我现在假设keytool使用java.security.SecureRandom(因此是默认提供程序)作为其随机数的基础.我发现了另一篇有趣的文章,它指出了控制SecureRandom API JAVA_HOME/lib/security/java.security配置的文件.
在那里它陈述如下:
选择SecureRandom的种子数据源.默认情况下,尝试使用securerandom.source属性指定的熵收集设备.如果在访问URL时发生异常,则使用传统的系统/线程活动算法.在Solaris和Linux系统上,如果指定了file:/ dev/urandom并且它存在,则默认情况下会激活特殊的SecureRandom实现.这个"NativePRNG"直接从/ dev/urandom读取随机字节.在Windows系统上,URL文件:/ dev/random和file:/ dev/urandom允许使用Microsoft CryptoAPI种子功能.
securerandom.source =文件是:/ dev/urandom的
由于我们在Windows系统上,我假设使用了Microsoft CryptoAPI.自从使用Win7以来,它就是CNG(CryptoAPI Next Generation).有没有人知道什么是'使用Microsoft CryptoAPI种子功能'.手段?最可能的方法似乎是:CryptGenRandom function
更新:Oracle似乎改进了Java 8的一些问题.
我想在这里分享我的发现:
\n\nkeytool.exe 使用 SecureRandom 作为其随机数的基础,如其源代码所示:Keytool和CertAndKeyGen。
通常,正如SecureRandom API 规定的那样:“加密的强随机数至少符合 FIPS 140-2,加密模块的安全要求,第 4.9.1 节中指定的统计随机数生成器测试。” 因此,SecureRandom 的所有实现都应符合FIPS-140-2。
安全提供程序的配置(因此也适用于 SecureRandom)在JAVA_HOME/lib/security/java.security. 默认值为(列表顶部):security.provider.1=sun.security.provider.Sun
如果不更改 3.),在 Linux 上,SecureRandom 的默认实现是NativePRNG,而在 Windows 上默认实现是SHA1PRNG。在我们的例子中,它是一个生成密钥的 Windows 电脑,因此它是SHA1PRNG。
在查看实现时,以下几点很突出:
\n\n\n“请注意,如果未提供种子,我们会尝试提供足够\n种子字节来完全随机化生成器的内部状态\n(20字节)。但是,我们的种子生成算法尚未\n彻底研究或广泛使用部署了。 ”
\n
SeedGenerator (所有 SHA1PRNG SecureRandom 对象中的单例)的“种子源”具有以下顺序:
\n\n现在发现SHA1PRNG存在以下问题:
\n\n\n“然而,对生成的 500MB 文件进行的黑盒测试表明,输出存在 15 个数量级的统计偏差。”
统计偏差 II(第 1 页)
\n\n\n\n“本文的实验结果表明,伪随机生成器 SHA1PRNG(Java 中)生成的序列可以以很高的概率与均匀选择的序列区分开来”
\n
较差的方差(第 12 页)和有限的状态大小(第 9 页)
\n\n\n“随机字节在 STS 测试中遇到了严重的困难,无法通过 Monobit、Runs 和前八个串行测试。这表明单个位和最多八位的元组的方差很差。” 并且\n “在 Java 中,向实例添加更多熵(>160 位)不会增强安全性。这种限制令人担忧,因为它使得 PRNG 对于 > 160 位的密钥生成毫无用处(例如,在 AES 情况下) ”。
\n
结果是:
\n\n因此,Java 密钥生成机制(至少在 Windows 上)可以被认为是损坏的。因此,大多数作者建议使用某些硬件,例如 HSM/ TRNG。
\n除非您使用硬件安全模块,否则我真的不会担心。关于您的随机数是否真正随机的微妙担忧逐渐消失,而主要担心您的密钥是否存在于硬盘上。
回到你的问题 - keytool 会将所有加密操作交给 JCA/JCE 提供商。每个提供商都有自己的SecureRandom实现,并且除非深入挖掘源代码,否则很难在网上找到这些实现的详细信息。您链接到的线程包含的信息比我以前看到的更多。