Является ли java.secure.random достаточным выбором для игорной индустрии?
Java предоставляет криптографически безопасный генератор случайных чисел в пакете java.secure.random.
Можно ли использовать этот генератор чисел, если я рассмотрю такие вещи, как засев и циклическое повторное создание ГСЧ? Или я могу использовать генератор чисел "как есть"?
Кто-нибудь имел опыт работы с этим генератором?
РЕДАКТИРОВАТЬ: требования являются:
а) быть статистически независимым
б) быть справедливо распределенными (в пределах статистически ожидаемых границ) по всему диапазону
в) пройти различные признанные статистические тесты
г) Быть криптографически сильным.
3 ответа
Как говорят другие, защищенный ГСЧ может иметь ограниченную пропускную способность. Чтобы смягчить это, вы можете либо увеличить эту безопасную случайность, заполнив CPRNG, либо попытаться оптимизировать использование битового потока.
Например, чтобы перемешать колоду карт, вам нужно всего 226 бит, но наивный алгоритм (вызов nextInt(n)
для каждой карты), вероятно, будет использовать 1600 или 3200 бит, что приведет к потере 85% вашей энтропии и сделает вас в семь раз более восприимчивым к задержкам.
Для этой ситуации я думаю, что метод доктора Жака будет уместным.
Чтобы пойти с этим, вот некоторый анализ производительности относительно прогрессивно более дорогих источников энтропии (также содержит код):
Переработка битов для масштабирования генераторов случайных чисел
Я бы склонялся к эффективному использованию, а не к растяжению, потому что я думаю, что было бы намного легче доказать справедливость эффективного потребителя заслуживающего доверия потока энтропии, чем доказать справедливость любого метода рисования с хорошо отобранным PRNG.
РЕДАКТИРОВАТЬ2: Я действительно не знаю Java, но я собрал это:
public class MySecureRandom extends java.security.SecureRandom {
private long m = 1;
private long r = 0;
@Override
public final int nextInt(int n) {
while (true) {
if (m < 0x80000000L) {
m <<= 32;
r <<= 32;
r += (long)next(32) - Integer.MIN_VALUE;
}
long q = m / n;
if (r < n * q) {
int x = (int)(r % n);
m = q;
r /= n;
return x;
}
m -= n * q;
r -= n * q;
}
}
}
Это избавляет от жадного стандартного генератора [0,n-1] по умолчанию и заменяет его модифицированной версией Доктора Жака. Временной диапазон значений карты-тасовки показывает почти 6-кратное ускорение по сравнению с SecureRandom.nextInt(n)
,
Моя предыдущая версия этого кода (только 2-кратное ускорение) предполагала, что SecureRandom.next(b)
был эффективным, но оказалось, что вызов отбрасывал энтропию и тянул весь цикл вниз. Эта версия управляет собственным чанкингом.
Документация о SecureRandom гласит, что он может блокировать ожидание, пока система генерирует больше энтропии (например, в Linux он принимает случайные числа из /dev/random), поэтому, если вы собираетесь его использовать, возможно, вам понадобится некоторая помощь от оборудования: установите карту генератора случайных чисел (аппаратное устройство, которое генерирует реальные случайные числа, а не псевдослучайные), чтобы ваша система генерировала случайные числа с достаточной скоростью, чтобы ваша программа не блокировалась.
Ты можешь использовать java.security.SecureRandom
как вы можете использовать java.util.Random
за такие вещи.
Только знайте, что java.security.SecureRandom
может зависеть от некоторой энтропии со стороны компьютера, на котором запущена программа. Если вы получите много случайных значений, то оно может блокироваться до тех пор, пока компьютер не сгенерирует достаточно энтропии (например, в Linux). java.security.SecureRandom
использует /dev/urandom
).
Так что если вы хотите сгенерировать много случайных значений и можете использовать PRNG java.util.Random
,