弱随机数生成器

OWASP 类别: MASVS-CRYPTO:密码学

概述

伪随机数生成器 (PRNG) 是一种算法,它根据称为种子的起始值生成可预测的数字序列。PRNG 生成的数字序列具有与真正的随机数序列**近似**相同的属性,但创建速度更快且计算成本更低。

换句话说,与弱 RNG(例如 java.math.Random)相比,PRNG 在熵分布均匀性方面具有更高的保证,它们模拟真正的随机数序列。真正的随机数生成需要专门的设备,并且通常超出正常开发的范围。本文档不涵盖真正的随机数生成,而仅关注 PRNG,因为它们是正在使用的标准方法。

当开发人员将常规 PRNG 用于加密目的而不是加密安全的 PRNG (CSPRNG) 时,就会发生弱 PRNG 漏洞。CSPRNG 具有更严格的要求,并且当种子未知时,它们必须只给攻击者微不足道的优势来区分输出序列和实际的随机序列。

攻击者还可能能够猜测生成的数字序列,当可预测的种子(例如开发人员硬编码的种子)用于初始化 PRNG 或 CSPRNG 时,因为攻击者可以猜测种子并因此预测 PRNG 生成的输出。

影响

如果在身份验证等安全上下文中使用了非加密安全的 PRNG,攻击者可能会能够猜测随机生成的数字并获取对特权数据或功能的访问权限。

缓解措施

常规

java.security.SecureRandom

推荐用于安全用途。如果 Linux 内核版本为 5.17 或更高版本阻塞线程是可以接受的,请等待足够的熵累积,然后生成随机数(即使用 /dev/random)。为此,请调用 getInstanceStrong()

Kotlin

val rand = SecureRandom.getInstanceStrong()

Java

SecureRandom rand = SecureRandom.getInstanceStrong();

否则,在生成随机数时,在 5.17 之前的 Linux 内核版本上,如果阻塞线程是不可接受的,则应直接调用 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);
    }
}

资源