Слабый ГПСЧ

Категория OWASP: MASVS-CRYPTO: Криптография

Обзор

Генератор псевдослучайных чисел (PRNG) — это алгоритм, который генерирует предсказуемые числовые последовательности на основе начального значения, называемого начальным числом . Числовая последовательность, сгенерированная с помощью PRNG, имеет примерно те же свойства, что и действительно случайная числовая последовательность, но ее создание выполняется быстрее и требует меньше вычислительных затрат.

Другими словами, ГПСЧ имеют более высокие гарантии, чем слабые ГСЧ (например, java.math.Random ) с точки зрения равномерности распределения энтропии, которые имитируют действительно последовательности случайных чисел. Генерация по-настоящему случайных чисел требует специального оборудования и часто выходит за рамки обычной разработки. В этом документе не рассматривается по-настоящему генерация случайных чисел, а основное внимание уделяется только ГПСЧ, поскольку они являются стандартной используемой методологией.

Слабые уязвимости PRNG возникают, когда разработчики используют обычный PRNG для криптографических целей вместо криптографически безопасного PRNG (CSPRNG). К CSPRNG предъявляются более строгие требования, и когда начальное число неизвестно, они должны давать злоумышленнику лишь незначительное преимущество в различении выходной последовательности от фактической случайной последовательности.

Злоумышленники также могут угадать сгенерированную числовую последовательность, когда предсказуемые начальные числа – например, жестко закодированные разработчиком – используются для инициализации PRNG или CSPRNG, поскольку злоумышленник может угадать начальное число и, таким образом, предсказать выходные данные, сгенерированные PRNG.

Влияние

Если некриптографически защищенный PRNG используется в контексте безопасности, например при аутентификации, злоумышленник может угадать случайно сгенерированные числа и получить доступ к привилегированным данным или функциям.

Смягчения

Общий

java.security.SecureRandom

Рекомендуется для использования в целях безопасности. Если версия ядра Linux 5.17+ или блокировка потока допустима, подождите, пока накопится достаточно энтропии, прежде чем генерировать случайные числа (т. е. используйте /dev/random ). Для этого вызовите getInstanceStrong() :

Котлин

val rand = SecureRandom.getInstanceStrong()

Ява

SecureRandom rand = SecureRandom.getInstanceStrong();

В противном случае в версиях ядра Linux до 5.17, когда блокировка потока при генерации случайных чисел недопустима, конструктор SecureRandom следует вызывать напрямую:

Котлин

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
    }
}

Ява

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.Случайный

Избегайте использования в целях безопасности/аутентификации, допускается использование для чего-либо еще.

Котлин

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)
    }
}

Ява

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);
    }
}

Ресурсы