在做初学者的加密课程时,我正试图掌握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对象。
答案 0 :(得分:2)
d)PRNG也是如此。对于CSRNG来说并非总是如此。阅读SecureRandom.setSeed()
的Javadoc:“给定的种子补充,而不是替换现有的种子。因此,保证重复的呼叫永远不会减少随机性。”
任何合理的CSRNG都会拥有您无法明确控制的“隐形”熵源,通常是从操作系统级别获取的各种内部参数。因此,播种比您明确传递给RNG的任何数字都要多。
答案 1 :(得分:1)
e)我不认为这会有所作为。假设long和8字节数组包含相同的数据。
f)原则上,是的。如果您的种子大于RNG的内部状态,那么可能存在一些其他种子将导致相同的内部状态。如果种子小于状态,则不应该存在。我不知道SecureRandom的内部状态是什么样的。
g)重要的不是种子的大小;它是熵的数量。你需要在种子中至少有与你期望的RNG安全性一样多的熵;我不太清楚这里有什么最佳做法。
h)我不确定打破您建议的基于RNG的流密码是多么容易。但我建议不要在实践中使用它,因为它不是专家审查过的标准加密结构,并且具有合理的安全性证据。记住加密规则:
答案 2 :(得分:1)
好的,按顺序:
a)正确
b)正确
c)更正,您甚至可以使用nextInt(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"
代替