Java keytool /使用java生成密钥的安全性(一般)

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的一些问题.

Lon*_*zak 5

我想在这里分享我的发现:

\n\n
    \n
  1. keytool.exe 使用 SecureRandom 作为其随机数的基础,如其源代码所示:KeytoolCertAndKeyGen

  2. \n
  3. 通常,正如SecureRandom API 规定的那样:“加密的强随机数至少符合 FIPS 140-2,加密模块的安全要求,第 4.9.1 节中指定的统计随机数生成器测试。” 因此,SecureRandom 的所有实现都应符合FIPS-140-2

  4. \n
  5. 安全提供程序的配置(因此也适用于 SecureRandom)在JAVA_HOME/lib/security/java.security. 默认值为(列表顶部):security.provider.1=sun.security.provider.Sun

  6. \n
  7. 如果不更改 3.),在 Linux 上,SecureRandom 的默认实现是NativePRNG,而在 Windows 上默认实现是SHA1PRNG。在我们的例子中,它是一个生成密钥的 Windows 电脑,因此它是SHA1PRNG

  8. \n
  9. 在查看实现时,以下几点很突出:

    \n\n
    \n

    “请注意,如果未提供种子,我们会尝试提供足够\n种子字节来完全随机化生成器的内部状态\n(20字节)。但是,我们的种子生成算法尚未\n彻底研究或广泛使用部署了

    \n
  10. \n
  11. SeedGenerator (所有 SHA1PRNG SecureRandom 对象中的单例)“种子源”具有以下顺序:

    \n\n
  12. \n
  13. 现在发现SHA1PRNG存在以下问题:

    \n\n
      \n
    • 不一致之处
    • \n
    • 统计偏差 I(第 152 页,法语,如果 n,请使用翻译器。)\n\n\n
      \n

      “然而,对生成的 500MB 文件进行的黑盒测试表明,输出存在 15 个数量级的统计偏差。”

    • \n
    • 统计偏差 II(第 1 页)

      \n\n\n

      \n

      “本文的实验结果表明,伪随机生成器 SHA1PRNG(Java 中)生成的序列可以以很高的概率与均匀选择的序列区分开来”

      \n
    • \n
    • 较差的方差(第 12 页)和有限的状态大小(第 9 页)

      \n\n
      \n

      “随机字节在 STS 测试中遇到了严重的困难,无法通过 Monobit、Runs 和前八个串行测试。这表明单个位和最多八位的元组的方差很差。” 并且\n “在 Java 中,向实例添加更多熵(>160 位)不会增强安全性。这种限制令人担忧,因为它使得 PRNG 对于 > 160 位的密钥生成毫无用处(例如,在 AES 情况下) ”。

      \n
    • \n
  14. \n
\n\n

结果是:

\n\n
    \n
  • 所有java windows安装的默认实现是SHA1PRNG
  • \n
  • SHA1PRNG 的行为非常不稳定
  • \n
  • SHA1PRNG 具有高度专有性 - 它不符合 FIPS-140-2(理应如此)。
  • \n
  • 不幸的是(引用实现者的话)“我们的种子生成算法尚未得到彻底研究”。但随着java的广泛分布,它现在得到了广泛的部署和使用。
  • \n
\n\n

因此,Java 密钥生成机制(至少在 Windows 上)可以被认为是损坏的。因此,大多数作者建议使用某些硬件,例如 HSM/ TRNG

\n


Dun*_*nes 0

除非您使用硬件安全模块,否则我真的不会担心。关于您的随机数是否真正随机的微妙担忧逐渐消失,而主要担心您的密钥是否存在于硬盘上。

回到你的问题 - keytool 会将所有加密操作交给 JCA/JCE 提供商。每个提供商都有自己的SecureRandom实现,并且除非深入挖掘源代码,否则很难在网上找到这些实现的详细信息。您链接到的线程包含的信息比我以前看到的更多。

  • 不明白“别担心”的评论。假设随机性来源很差——例如,基于系统时间。然后,如果我知道您的私钥是在 2013 年 10 月 1 日生成的,那么在尝试解密我作为中间人截获的流量时,我只需尝试数十亿个可能的密钥(而不是 2^1024)。即使您的私钥在某个文件系统上受到保护,也是如此。因此,除非我遗漏了什么,否则非对称密钥生成的随机性/熵源确实很重要。 (2认同)