我想了解Java的SecureRandom对象

时间:2014-04-23 23:19:34

标签: java random cryptography

在做初学者的加密课程时,我正试图掌握Java的SecureRandom对象。我认为我理解的是:

a)无论你知道多少个随机数,都无法预测序列中的下一个随机数。

b)无论你知道多少个随机数,除了蛮力猜测之外,无法知道哪个种子被用来启动它们。

c)您可以申请各种规模的安全随机数。

d)您可以为具有各种不同大小值的新创建的SRNG播种。您创建的每个新创建的SRNG和具有相同值的种子将生成相同的随机数序列。

我应该补充一点,我假设这个代码在Windows上使用:

Random sr = SecureRandom.getInstance("SHA1PRNG", "SUN");

我的基本理解是否正确?提前谢谢。

对于在加密方面合理专家的人,我还有一些问题。它们与播种SRNG有关,而不是让它在首次使用时播种。

e)如果使用长整数而不是8字节的数组为SRNG播种,那么对生成的随机数有什么不同呢?

f)如果我使用256字节为SRNG播种,是否有任何其他种子可以产生相同的随机数序列?

g)是否有某种最佳种子大小?在我看来,这可能是一个毫无意义的问题。

h)如果我通过将SRNG播种为256字节来加密明文然后使用明文中的字节生成随机字节到XOR,那么窃听者解密生成的密文有多容易?需要多长时间?我是否正确地认为窃听者必须知道,猜测或计算256字节的种子?

我看过以前有关SecureRandom的问题,似乎没有人回答我特别关注的问题。 如果这些问题中的任何一个看起来过于愚蠢,我想重申一点,我是学习这一领域的初学者。我非常感谢任何输入,因为我想了解如何在加密中使用Java SecureRandom对象。

3 个答案:

答案 0 :(得分:2)

d)PRNG也是如此。对于CSRNG来说并非总是如此。阅读SecureRandom.setSeed()的Javadoc:“给定的种子补充,而不是替换现有的种子。因此,保证重复的呼叫永远不会减少随机性。”

任何合理的CSRNG都会拥有您无法明确控制的“隐形”熵源,通常是从操作系统级别获取的各种内部参数。因此,播种比您明确传递给RNG的任何数字都要多。

答案 1 :(得分:1)

e)我不认为这会有所作为。假设long和8字节数组包含相同的数据。

f)原则上,是的。如果您的种子大于RNG的内部状态,那么可能存在一些其他种子将导致相同的内部状态。如果种子小于状态,则不应该存在。我不知道SecureRandom的内部状态是什么样的。

g)重要的不是种子的大小;它是熵的数量。你需要在种子中至少有与你期望的RNG安全性一样多的熵;我不太清楚这里有什么最佳做法。

h)我不确定打破您建议的基于RNG的流密码是多么容易。但我建议不要在实践中使用它,因为它不是专家审查过的标准加密结构,并且具有合理的安全性证据。记住加密规则:

  1. 永远不要设计自己的加密。
  2. 永远不要实施自己的加密。
  3. 任何人都可以设计一个他们无法自拔的加密。

答案 2 :(得分:1)

好的,按顺序:

a)正确

b)正确

c)更正,您甚至可以使用nextInt(n)

请求[0,n]范围内的数字

d)和正确一样好:SHA1PRNG的实现没有被任何算法公开定义,并且有迹象表明实现已经及时更改,因此仅适用于Sun提供程序,然后仅针对特定的运行时配置

e)因为API清楚地表明使用了long中的所有字节("使用给定长种子中包含的8个字节")关于添加的熵量应该没有任何差别到州

请注意,快速检查表明setSeed(long)setSeed(byte[])的行为完全不同,主要区别在于long值的种子始终与从系统检索到的随机性混合在一起,即使它是构造SecureRandom实例后的第一个调用。

f)是 - 无限数量的种子生成相同的流;由于使用了散列函数,因此无法找到一个

g)如果你混合了额外的熵,则熵越多越好,但没有最小值;如果你使用它作为唯一的种子,那么你不应该从少于20个字节的种子开始,即:如果你想让种子保持与PRNG的内部状态相同的安全性约束

我想补充一点,如果你使用少于64个字节的熵,你肯定会处于危险区域。注意,1位熵并不总是意味着一个字节中的1位。大小为8的字节数组可能具有64位熵或更少

h)基本上是基于散列的流密码;它是安全的,所以攻击者几乎没有机会(让你不重用种子)但是它是一个非常不可靠的(见答案d)和缓慢的流密码,所以请永远不要这样做 - 使用Cipher"AES/CTR/NoPadding""AES/GCM/NoPadding"代替