1. введение
В этом коротком уроке мы узнаем о java.security.SecureRandom, класс, который обеспечивает криптографически сильный генератор случайных чисел.
2. Сравнение с java.util.Случайный
Стандартные реализации JDK java.util.Random используйте алгоритм Линейного конгруэнтного генератора (LCG) для предоставления случайных чисел. Проблема с этим алгоритмом заключается в том, что он не является криптографически сильным. Другими словами, сгенерированные значения гораздо более предсказуемы, поэтому злоумышленники могут использовать их для компрометации нашей системы.
Чтобы преодолеть эту проблему, мы должны использовать java.security.SecureRandom в любых решениях по безопасности . Он производит криптографически сильные случайные значения с помощью криптографически сильного генератора псевдослучайных чисел ( CSPRNG ).
Для лучшего понимания разницы между LCG и SPRING, пожалуйста, посмотрите на приведенную ниже диаграмму, представляющую распределение значений для обоих алгоритмов:
3. Генерация Случайных Значений
Наиболее распространенным способом использования SecureRandom является генерация int , long , float , double или булевых значений :
int randomInt = secureRandom.nextInt(); long randomLong = secureRandom.nextLong(); float randomFloat = secureRandom.nextFloat(); double randomDouble = secureRandom.nextDouble(); boolean randomBoolean = secureRandom.nextBoolean();
Для генерации значений int мы можем передать верхнюю границу в качестве параметра:
int randomInt = secureRandom.nextInt(upperBound);
Кроме того, мы можем генерировать поток значений для int, |/double и long :
IntStream randomIntStream = secureRandom.ints(); LongStream randomLongStream = secureRandom.longs(); DoubleStream randomDoubleStream = secureRandom.doubles();
Для всех потоков мы можем явно задать размер потока:
IntStream intStream = secureRandom.ints(streamSize);
а также исходные (включительные) и связанные (исключительные) значения:
IntStream intStream = secureRandom.ints(streamSize, originValue, boundValue);
Мы также можем сгенерировать последовательность случайных байтов . Функция nextBytes() берет предоставленный пользователем массив byte и заполняет его случайным byte s:
byte[] values = new byte[124]; secureRandom.nextBytes(values);
4. Выбор алгоритма
По умолчанию SecureRandom использует алгоритм SHA1PRNG для генерации случайных значений. Мы можем явно заставить его использовать другой алгоритм, вызвав метод getInstance() :
SecureRandom secureRandom = SecureRandom.getInstance("NativePRNG");
Создание SecureRandom с помощью оператора new эквивалентно SecureRandom.getInstance(“SHA1PRNG”) .
Все генераторы случайных чисел, доступные в Java, можно найти на официальной странице документов .
5. Семена
Каждый экземпляр SecureRandom создается с начальным семенем. Он работает как база для предоставления случайных значений и меняется каждый раз, когда мы генерируем новое значение.
Используя оператор new или вызывая SecureRandom.getInstance() будет получать начальное значение по умолчанию из /dev/urandom .
Мы можем изменить начальное значение, передав его в качестве параметра конструктора:
byte[] seed = getSecureRandomSeed(); SecureRandom secureRandom = new SecureRandom(seed);
или путем вызова метода сеттера для уже созданного объекта:
byte[] seed = getSecureRandomSeed(); secureRandom.setSeed(seed);
Помните, что если мы создадим два экземпляра SecureRandom с одним и тем же семенем и для каждого из них будет выполнена одна и та же последовательность вызовов методов, они будут генерировать и возвращать одинаковые последовательности чисел.
6. Заключение
В этом уроке мы узнали, как работает SecureRandom и как использовать его для генерации случайных значений.
Как всегда, весь код, представленный в этом учебнике, можно найти на GitHub .