关于随机:我想了解Java的SecureRandom对象

I'd like to understand Java's SecureRandom object

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

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

b)无论你知道一系列随机数有多长,除了粗暴的猜测外,没有办法知道是哪种种子启动了它们。

c)您可以请求各种大小的安全随机数。

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

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

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

我的基本理解正确吗?事先谢谢。

对于任何一个在密码方面相当专业的人,我还有更多的问题要问。它们涉及到播种SRNG,而不是让它自己在第一次使用时播种。

e)如果您使用长整数而不是8个字节的数组来输入srng,它对生成的随机数有什么区别?

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

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

h)如果我通过输入一个SRNG(例如256字节)来加密明文,然后让它生成随机字节到XOR(明文中的字节),那么窃听者解密产生的密文有多容易?需要多长时间?我是否认为窃听者必须知道、猜测或计算256字节的种子?

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


d)这对于PRNG是正确的。对CSRNG来说并不总是这样。读一读JavaDoc for SecureRandom.setSeed():"给定的种子补充剂,而不是取代现有的种子。因此,重复的呼叫保证永远不会减少随机性。"

任何合理的CSRNG都将具有"不可见"的熵源,您无法明确地控制这些熵源,通常是从操作系统级别获取的各种内部参数。因此,种子设定比您显式传递给RNG的任何数字都要多。


好的,按顺序:

a)正确

b)正确

c)正确,您甚至可以使用nextInt(n)请求范围[0,n]内的数字。

d)尽可能正确:sha1prng的实现没有被任何算法公开定义,并且有迹象表明实现已及时更改,因此这仅适用于Sun提供程序,然后仅适用于特定的运行时配置。

e)由于api清楚地表明使用了long中的所有字节("使用给定long seed中包含的八个字节"),因此添加到状态的熵量不应存在任何差异。

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

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

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

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

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


e)我认为这没什么区别。假设long和8字节数组包含相同的数据。

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

g)重要的不是种子的大小,而是其中的熵。你需要在你的种子中至少有和RNG期望的安全一样多的熵;我不太确定这里有什么最佳实践。

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

  • 永远不要设计自己的密码。
  • 永远不要实现自己的加密。
  • 任何人都可以设计他们自己无法破解的密码。