《Java编码指南:编写安全可靠程序的75条建议》—— 指南14:确保SecureRandom正确地选择随机数种子...

    xiaoxiao2024-05-21  103

    本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.14节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F.Sutherland(迪恩 F.萨瑟兰), David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

    指南14:确保SecureRandom正确地选择随机数种子

    随机数的生成取决于熵的来源,如信号、设备或硬件输入等。《The CERT® Oracle® Secure Coding Standard for Java™》[Long 2012]的“MSC02-J. Generate strong random numbers”解决了安全随机数的生成。

    java.security.SecureRandom类被广泛用于生成密码强随机数。根据Java运行时环境的lib/security文件夹中,java.security文件的描述[API 2013]:

    为SecureRandom种子数据选择来源。默认情况下尝试使用securerandom. source属性所指定的熵收集装置。如果访问URL时发生异常,那么传统的系统/线程活动算法将会派上用场。

    在Solaris和Linux系统中,如果file:/dev/urandom被指定且是存在的,那么会默认激活一个特殊的SecureRandom实现。这种“NativePRNG”直接从/dev/urandom读取随机数字节。在Windows系统中,file:/dev/random和file:/dev/urandom这个`URL启用了微软CryptoAPI种子功能。

    攻击者不应该能够从给出的几个随机数字的样本中确定原始随机种子。如果违反了这一限制,之后所有随机数都可以被攻击者成功地预测出来。

    违规代码示例

    下面的违规代码示例通过具有指定种子字节的种子构造了一个安全的随机数生成器。

    SecureRandom random = new SecureRandom(  String.valueOf(new Date().getTime()).getBytes() );``` 这个构造函数搜索注册的安全提供程序并返回第一个支持安全随机数生成的提供程序。如果不存在这样的提供程序,那么会选择一个默认的特定实现。此外,系统提供的默认种子会被程序员提供的种子所覆盖。使用当前系统时间作为种子是可以被预测的,会导致使用不足够的熵来产生随机数。 ####合规解决方案 使用SecureRandom类的无参构造函数更好,该函数使用了特定于系统的种子值来生成128字节长的随机数。

    byte[] randomBytes = new byte[128];SecureRandom random = new SecureRandom();random.nextBytes(randomBytes);`指定确切的随机数生成器和提供者也是一个好的实践,这样会带来更好的可移植性。

    适用性

    不够安全的随机数会使得攻击者能够在它们被使用的上下文中获得特定的信息。

    不安全的随机数在一些没有安全要求的情况下也是有用的。这些随机数在“MSC02-J. Generate strong random numbers”[Long 2012]的一些例外中有提到。

    最新回复(0)