SecureRandom.ints()安全吗?

Ya *_*iao 54 java security random

众所周知,SecureRandom类为生成的随机数提供了强大的加密安全性。java.util.Random对于需要加密安全性的情况是不安全的。的典型用法SecureRandom是:

SecureRandom random = new SecureRandom();
byte bytes[] = new byte[20];
random.nextBytes(bytes);
Run Code Online (Sandbox Code Playgroud)

但是,我遇到了一个案例:

SecureRandom random = new SecureRandom();
int number = random.ints();
Run Code Online (Sandbox Code Playgroud)

该方法ints()java.util.Random类继承。当SecureRandom哪个安全随机数生成器使用从不安全随机数生成器继承的方法时,我感到困惑,它是否安全?

Ste*_*n C 33

是的,它是安全的。

java.util.Random显示的代码检查ints()创建了一个拆分器,该拆分器internalNextInt(...)用于生成随机整数。这反过来又要求nextInt()this。在的情况下java.security.SecureRandomnextInt()被覆盖以生成“安全的”随机数1

您可以通过查看源代码自行确认。


1-当然,将整数或整数序列称为“安全”实际上没有任何意义。在某些情况下,SecureRandom可能没有您需要的属性。(这取决于类使用的实际RNG或PRNG实现,提供的种子或系统提供的熵源的质量,等等。)但是SecureRandom :: ints()会生成具有相同属性的整数序列就像您在同一对象上进行了一系列SecureRandom :: nextInt()调用一样。如果后一种序列适合您的目的(无论它们是什么),那么前一种序列也是如此。


And*_*ner 14

Random.ints()是一个返回的方法IntStream。An IntStream既不安全也不安全:它是数字流。

该方法返回的int序列的“安全性”取决于该方法的实现。SecureRandom生成比更为安全的“随机”值Random。它们共享相同的API,因此您可以根据需要在给定的上下文中使用它们。

因此,它从不安全的类继承的事实与安全性无关:您可以合理地相信,SecureRandom该类与文档所述的一样安全。


考虑一个类比HashSet这不能保证迭代器的顺序;但是,LinkedHashSet的子类HashSet 确实可以保证迭代器的顺序。的保证LinkedHashSet与的保证是一致的HashSet,因为特定的排序是可以用“没有保证的排序”观察到的可能排序之一(毕竟,您必须以某种顺序返回元素)。

同样,Random不保证返回的int序列的安全性;SecureRandom做出更强有力的保证。但是,没有理由为什么巧合地SecureRandom也无法从a 返回整数的序列Random

  • @LutzHorn。我不同意。您不只是想要正确类型的`ints()`方法(或`iterator()`方法)。您还希望有具体的实施保证。 (3认同)

小智 10

是, SecureRandom

提供了加密强度高的随机数生成器(RNG)。

安全的RNG的一个重要因素是种子。

因此,传递给SecureRandom对象的任何种子材料都必须是不可预测的,并且所有SecureRandom输出序列必须具有加密强度,如RFC 4086:安全性的随机性要求中所述。

继续使用它。如果您对这些细节感兴趣,请阅读JavaDoc,其中描述了实现所使用的各种方法。

  • 您的断言“安全的RNG的重要因素是种子,而不是算法”。是错误的,并且有危险的误导。种子和算法都至关重要。如果将种子输入粗糙的LCG或Mersenne Twister或其他非加密RNG算法中,则种子的熵源有多好都没有关系。 (7认同)

Maa*_*wes 5

整数方法

是的,它是安全的,只要nextInt()是安全的(对于从流中检索的整数数量)。

根据Random#ints()方法文档

int生成一个伪随机值,就好像它是调用方法的结果一样nextInt()

现在反过来Random#nextInt

该方法nextInt由类实现,Random就像通过(返回)next(32)

next(int) 是一种不能调用的受保护方法,但可以在实现类时覆盖它。

这反过来又被实现,就好像您使用的是而不是的实例SecureRandom.next(32) SecureRandomRandom

生成一个包含用户指定数量的伪随机位(右对齐,前导零)的整数。此方法覆盖一个java.util.Random方法,并用于为从该类继承的所有方法(例如nextIntnextLong、 和nextFloat提供随机位源

所以最后SecureRandom调用了一个方法,如果这是安全的,那么随机数流就是安全的。现在老实说,该语句是错误的,因为它不用于nextBytes,但它肯定用于任何返回数字值的方法。

SecureRandom 实现

如果您已经确定SecureRandom您使用的 是安全的,那么您可以停止阅读此处。

现在你会认为它会在这里结束,但SecureRandom它本身并没有实现随机生成器。相反,它仅依赖于已配置的提供者中实现的特定服务类SecureRandomSpi(Spi 表示服务提供者接口,提供者必须实现的抽象类以将安全的随机数据传递给 的实例SecureRandom)。所以最后必须调用SecureRandomSpi#nextBytes()willSecureRandom#next(int)来检索实际位。


正如Random#next(int)其他需要数字或数字流的方法所说的那样- 最后 - 都应该调用这个特定的方法。现在,如果这是真实的情况取决于实施RandomSecureRandom。结果是否安全取决于算法和由 提供的种子SecureRandomSpi,即使用的实际随机位生成器。


我已经在上面证明了结果应该是真正的密码随机,假设它SecureRandom是密码随机的。最后,只需要对Java 的每个实现和版本进行完整的代码审查以证明它是安全的。不过,这超出了 StackOverflow 的范围,您可能需要来自 Oracle、IBM 或 Google 等的支持来检索测试文档和评论,当然,您也可以自己为特定实现执行此类审查。大部分——如果不是全部——毕竟是开源的。