Как решить медленную Java `SecureRandom`? - PullRequest
148 голосов
/ 26 сентября 2008

Если вы хотите криптографически сильное случайное число в Java, вы используете SecureRandom. К сожалению, SecureRandom может быть очень медленным. Если он использует /dev/random в Linux, он может заблокировать ожидание достаточной энтропии для наращивания. Как избежать штрафа за производительность?

Кто-нибудь использовал Uncommon Maths в качестве решения этой проблемы?

Кто-нибудь может подтвердить, что эта проблема с производительностью была решена в JDK 6?

Ответы [ 17 ]

4 голосов
/ 26 сентября 2008

Использование безопасного случайного числа в качестве источника инициализации для рекуррентного алгоритма; тогда вы могли бы использовать твистер Mersenne для массовых работ вместо того, что использовался в UncommonMath, который существовал некоторое время и оказался лучше, чем другие prng

http://en.wikipedia.org/wiki/Mersenne_twister

Обязательно обновляйте время от времени безопасное случайное число, используемое для инициализации, например, вы можете создать одно безопасное случайное случайное число для каждого клиента, используя один псевдослучайный генератор mersenne twister для каждого клиента, получая достаточно высокую степень рандомизации

2 голосов
/ 15 сентября 2013

Если ваше оборудование поддерживает это, попробуйте , используя Java RdRand Utility , автором которой я являюсь.

Он основан на инструкции Intel RDRAND и примерно в 10 раз быстрее, чем SecureRandom, и не создает проблем с пропускной способностью для реализации больших объемов.


Обратите внимание, что эта реализация работает только на тех процессорах, которые предоставляют инструкцию (т. Е. Когда установлен флаг процессора rdrand). Вам нужно явно создать его экземпляр с помощью конструктора RdRandRandom(); конкретный Provider не был реализован.

2 голосов
/ 26 сентября 2008

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

Не идите на компромисс по генерации случайных чисел. Слабость там ставит под угрозу всю вашу безопасность.

Я не вижу много генераторов на основе атомного распада COTS, но есть несколько планов для них, если вам действительно нужно много случайных данных. Один сайт, на котором всегда есть интересные вещи, включая HotBits, - Fourmilab Джона Уокера.

2 голосов
/ 23 декабря 2008

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

Если вам не нужна эта полная гарантия случайности, то, вероятно, существуют соответствующие компромиссы производительности. Я склонен согласиться с ответом Дэна Дайера об AESCounterRNG от Uncommons-Maths или Fortuna (одним из его авторов является Брюс Шнайер, эксперт по криптографии). Я никогда не использовал ни один, но идеи кажутся заслуживающими доверия на первый взгляд.

Я бы подумал , что если бы вы могли генерировать начальное случайное начальное число периодически (например, один раз в день или час или что-то еще), вы могли бы использовать быстрый потоковый шифр для генерации случайных чисел из последовательных кусков потока (если потоковый шифр использует XOR, тогда просто передайте поток нулей или захватите биты XOR напрямую). Проект ECRYPT eStream содержит много полезной информации, включая показатели производительности. Это не будет поддерживать энтропию между моментами времени, когда вы его пополняете, поэтому, если кто-то знает одно из случайных чисел и алгоритм, который вы использовали, технически, возможно, с большой вычислительной мощностью, сломать потоковый шифр и угадать его внутреннее состояние, чтобы иметь возможность предсказывать будущие случайные числа. Но вам придется решить, достаточно ли этого риска и его последствий, чтобы оправдать затраты на поддержание энтропии.

Редактировать: вот некоторые заметки о криптографическом курсе по ГСЧ Я нашел в сети, которые выглядят очень актуально для этой темы.

2 голосов
/ 26 сентября 2008

Я сам не сталкивался с этой проблемой, но при запуске программы я создал поток, который немедленно попытался бы создать начальное число, а затем умер. Метод, который вы вызываете случайным образом, присоединится к этому потоку, если он жив, поэтому первый вызов блокируется только в том случае, если он происходит очень рано при выполнении программы.

1 голос
/ 04 октября 2008

Еще нужно обратить внимание на свойство securerandom.source в файле lib / security / java.security.

Может быть выигрыш в производительности при использовании / dev / urandom, а не / dev / random. Помните, что если важно качество случайных чисел, не идите на компромисс, который нарушает безопасность.

0 голосов
/ 04 ноября 2015

Вы можете попробовать проект Apache commons Math, который имеет несколько реализаций хорошо известных алгоритмов:

https://commons.apache.org/proper/commons-math/userguide/random.html

Однако будьте осторожны с производительностью. Конструктор по умолчанию RandomDataGenerator создает выделенный экземпляр Well19937c, что является очень дорогой операцией.

Согласно документации, этот класс не является потокобезопасным, но если вы можете гарантировать, что только один поток будет иметь доступ к этому классу, вы можете инициализировать только один экземпляр на поток.

...