OWASP 类别: MASVS-CRYPTO:加密
概述
伪随机数生成器 (PRNG) 是一种算法,它根据称为种子的起始值生成可预测的数字序列。PRNG 生成的数字序列具有与真正随机数序列大致相同的属性,但创建速度更快,计算成本更低。
换句话说,与弱 RNG(例如 java.math.Random
)相比,PRNG 在熵分布均匀性方面具有更高的保证,从而模拟真正随机数序列。真正随机数的生成需要专门的设备,并且通常超出正常开发的范围。本文不涵盖真正随机数的生成,仅关注 PRNG,因为它们是标准的使用方法。
当开发人员将常规 PRNG 用于加密目的,而不是加密安全的 PRNG (CSPRNG) 时,就会出现弱 PRNG 漏洞。CSPRNG 具有更严格的要求,当种子未知时,它们必须使攻击者在将输出序列与实际随机序列区分开时只能获得微不足道的优势。
当可预测的种子(例如开发人员硬编码的种子)用于初始化 PRNG 或 CSPRNG 时,攻击者也可能能够猜测生成的数字序列,因为攻击者可以猜测种子,从而预测 PRNG 生成的输出。
影响
如果在身份验证等安全上下文中使用非加密安全的 PRNG,则攻击者可能能够猜测随机生成的数字并访问特权数据或功能。
缓解措施
常规
- 当存在安全隐患时,使用
java.security.SecureRandom
- 在任何其他情况下使用
java.util.Random
- 切勿使用
Math.random
!
java.security.SecureRandom
推荐用于安全用途。如果 Linux 内核版本为 5.17+ 或可接受阻塞线程,请等待足够的熵累积后再生成随机数(即使用 /dev/random
)。为此,请调用 getInstanceStrong()
Kotlin
val rand = SecureRandom.getInstanceStrong()
Java
SecureRandom rand = SecureRandom.getInstanceStrong();
否则,在 Linux 内核版本低于 5.17 且生成随机数时无法接受阻塞线程的情况下,应直接调用 SecureRandom
构造函数
Kotlin
import java.security.SecureRandom
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = SecureRandom()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
// Use rand_int for security & authentication
}
}
Java
import java.security.SecureRandom;
public class generateRandom {
public static void main(String args[])
{
// Create instance of SecureRandom class
SecureRandom rand = new SecureRandom();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
// Use rand_int for security & authentication
}
}
SecureRandom
从 /dev/urandom
获取默认种子,并在构造或获取对象时自动使用,因此无需显式播种 PRNG。通常,不建议以确定性方式使用 SecureRandom(尤其是在这会导致硬编码种子值时,任何反编译应用的人都可以看到)。希望生成可重现的伪随机输出的开发人员应使用更合适的原语,例如 HMAC、HKDF、SHAKE 等。
java.util.Random
避免用于安全/身份验证目的,适用于任何其他用途。
Kotlin
import java.util.Random
object generateRandom {
@JvmStatic
fun main(args: Array<String>) {
// Create instance of SecureRandom class
val rand = Random()
// Generate random integers in range 0 to 999
val rand_int = rand.nextInt(1000)
}
}
Java
import java.util.Random;
public class generateRandom {
public static void main(String args[])
{
// Create instance of Random class
Random rand = new Random();
// Generate random integers in range 0 to 999
int rand_int = rand.nextInt(1000);
}
}