在需要重新设定

时间:2016-06-22 12:33:25

标签: java encryption random cryptography

我正在用Java实现一个应用程序,我正在使用SecureRandom来生成随机性。我需要能够加密10亿个文件。我在StackOverflow上查看了我的问题的答案,但我没有找到确切的答案。每个人都很模糊:

  • 您无需重新安装SecureRandom。它有一个“大”期。但什么是
  • 您不需要重新设置SecureRandom,因为它是“精心设计的" CSPRNG。但是什么是精心设计的 CSPRNG的时期?

所以我决定自己做数学,看看是否有人可以为我检查。我们对SecureRandom目前在Java 8中的实现了解了哪些事实?实际上我发现的来源存在争议。

我对Java的SecureRandom实现了解

  • 在内部,它通过调用nextBytes()nextInt()nextLong()等来生成随机性时使用SHA1PRNG(请参阅TersesystemsCigital

    Cigital对SecureRandom所做内容的解释与Java docs的官方解释相矛盾。 Oracle的官方文档指出,NativePRNG,NativePRNGBlocking,NativePRNGNonBlocking和Windows-PRNG始终使用本机随机源而不是Java自己的SHA1PRNG算法(此answerthis one也提到)。 Cigital的链接表明Java总是使用SHA1PRNG,但SecureRandom的类型决定了它的播种位置(/dev/random/dev/urandom等)。

    SecureRandom总是在引擎盖下使用SHA1PRNG吗?这是我在数学计算中假设的,所以如果不是这样,请纠正我。

  • 官方Oracle documents声明SHA1PRNG从完整的160位散列输出中将其输出截断为64位?查看SecureRandom的OpenJDK’s implementation,我看到SHA1输出没有截断。实际上它恰恰相反:它保存SHA1哈希中任何未使用的输出,以便将来调用engineNextBytes()。如果正式的Oracle文档是该主题的主要权威,那么为什么OpenJDK的实现会有所不同呢?这很奇怪。

  • 在SecureRandom实例上立即调用nextBytes()时,它会由操作系统的CSPRNG(Linux / Unix中的/dev/random和Windows中的CryptGenRandom)自动播种,或者当它们不可用时播种通过定制的熵生成器,如ThreadLocalRandom。但ThreadLocalRandom提供非常低和慢的熵,因此应尽可能避免。

  • 我在SecureRandom中找不到自动重播功能的证据。 Fortuna CSPRNG,如密码工程中所解释的,有一个精心设计的重播机制,我希望任何现代的CSPRNG都能从客户端抽象出逻辑并自动处理它。我不确定为什么缺乏关于CSPRNG重播的信息和理解。如果你耗尽了CSPRNG的时间,就需要发生这种情况。这个毋庸置疑。问题是这个时期是什么,它是Java中的一个真正关注点。

做数学

由于生日攻击,我们知道当我们产生内部哈希输出数量的一半输出大小时,我们通常应该发生冲突。我们知道内部哈希被截断为64位。这意味着在我们有50%的碰撞机会之前,我们最多可以产生2 ^ 32-1轮的64位随机性。这将是我们想要重新开始的时间。

每个SecureRandom种子的

(2^32-1) * 64 = 274,877,906,880个随机性

转换为我们得到的字节

每个SecureRandom种子的

(2^32 - 1) * 64 / 8 / (1024 * 1000 * 1000 ) = ~33.55 GBytes随机性。

这意味着我们通常可以预期SecureRandom的SHA1PRNG产生大约33.55GB的高质量随机性,然后再用强种子重新种植。

我的数学是否正确?

为什么这很重要?因为我的用例是加密10亿个文件。每个都需要IV(128位)和密钥(256位)或384位。在最好的情况下,这需要46.875GB的随机性。因此,如果那段时间只有33.55GB,我将耗尽SecureRandom的时间。在这种情况下需要重新安置策略,我将作为一个单独的问题发布。

我的碰撞问题和SecureRandom

我有很多关于密码学的知识,所以我的理解一直在改进。我没有找到任何关于碰撞的信息是CSPRNG的问题,但猜测生成器的内部状态是有害的(见WikiSchneir’s cryptanalysis paper on CSPRNG)。

这是我对碰撞的思路。我生成一个(2 ^ 32-1)随机,唯一的64位值的表(这大约是33.55GB,所以很容易实现)。然后我有50%的机会猜测SecureRandom的任何64位输出。例如,IV /密钥由2×64 = 128位组成。这意味着我可以猜测具有50%概率的IV / Key的前64位和具有50%概率的第二64位,而无需知道CSPRNG的内部状态。猜测完整密钥的组合概率将小于50%,但远远超过我们在处理此类加密原语时所考虑的概率。这可能导致产生弱键,这是我想要避免的。换句话说,我认为CSPRNG的64位输出对于严重的加密工作来说太小了,完全基于64位输出的冲突属性(因为生日攻击)。另一方面,如果SecureRandom使用512位SHA-2哈希并将其截断为256位输出,那么由于密钥空间的庞大规模,我在这里理论化的冲突攻击是不可能的。我有意义还是我错了?

0 个答案:

没有答案