【问题标题】:How to properly use setSeed() method in SecureRandom to generate RSA primes如何在 SecureRandom 中正确使用 setSeed() 方法生成 RSA 素数
【发布时间】:2014-12-04 05:11:00
【问题描述】:

我想为 RSA 密钥生成生成两个素数。我认为为了增加两个素数的随机性,随机可能会生成如下:

SecureRandom r = SecureRandom.getInstance("SHA1PRNG");
r.setSeed(1232);
p = BigInteger.probablePrime(1024, r);
q = BigInteger.probablePrime(1024, r);

我的问题是:你认为使用SecureRandom 会增加pq 的随机性吗?如果是这样,我如何随机设置setSeed()的值而不是使其成为固定值(这里我选择了1232)?

【问题讨论】:

  • 我永远不会打电话给setSeedSecureRandom 会在您不调用 setSeed 时自动播种。

标签: java random cryptography rsa


【解决方案1】:

正如 CodesInChaos 已经表明的那样,SUN 提供程序的默认实现使用系统随机数生成器自动为自己播种。由于 Java 本身没有(显式)熵源,因此它的种子或多或少依赖于系统。

在从 SUN 提供程序中的 "SHA1PRNG" 检索数据之前,您永远不应调用 setSeed,因为这会使您的 RNG(随机数生成器)成为确定性 RNG - 它使用给定种子而不是将种子添加到状态。换句话说,它总是会生成相同的伪随机位或值流。

setSeed 的初始调用可能因提供商而异。有时它会将种子用作唯一的种子,但它也可能只是将种子添加到当前状态。在更高的 Android 版本(4.2 及更高版本)上,种子只是添加到随机状态,因此 "SHA1RNG" 将保持完全随机。

生成随机数生成器的最佳方式可能就是

SecureRandom r = new SecureRandom();

让 Java 运行时找出最好的那个。


如果您想使用显式算法(但是,SUN/Oracle 对该算法的描述不正确),那么您可以使用:

SecureRandom r = SecureRandom.getInstance("SHA1PRNG");

就像在你的代码中一样。

现在,还可以使用 NIST 算法,使用 "DRBG" 作为算法描述,然后您可以使用安全属性为 VM 配置。

"SHA1PRNG""DRBG" 都不是实现要求,并且每个运行时/提供者使用哪种算法或如何播种可能会有所不同。我永远不会使用它们来重新生成先前生成的字节或值流;请为此使用流密码。例如,您可以将密码实例 Cipher 用于 "AES/CTR/NoPadding" 并加密零值字节以获取密钥流。


如果要添加熵,请使用:

// just used to make sure that the SecureRandom is seeded by the OS
r.nextBytes(new byte[8]);
r.setSeed(1232);

一个常数值或文字不包含太多(如果有的话)熵。通常的熵来源是当前时间(甚至更好,System.nanoTime())、鼠标移动等。


对于 Java 8,有一个新方法 getInstanceStrong(),其描述如下:

返回使用在 securerandom.strongAlgorithms 安全属性中指定的算法/提供程序选择的 SecureRandom 对象。

某些情况需要强随机值,例如在创建 RSA 公钥/私钥等高价值/长期存在的机密时。为了帮助指导应用程序选择合适的强 SecureRandom 实现,Java 发行版在 securerandom.strongAlgorithms 安全属性中包含了一个已知强 SecureRandom 实现的列表。

应该用它来代替对构造函数的调用。请注意,这可能会返回一个阻塞 RNG,即:一个可能会阻塞您的线程直到足够的熵可用的RNG。它还可能会耗尽您的操作系统熵池阻塞其他应用程序,因此请谨慎使用它。

【讨论】:

  • 嘿,迈克,您似乎从未接受过这个答案;有什么遗漏的吗?
猜你喜欢
  • 2018-11-21
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 2017-12-28
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多