Как иметь дело с медленным генератором SecureRandom?

NullPointerException s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException. Они наиболее распространены, но другие способы перечислены на странице NullPointerException javadoc.

Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException, be:

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }

}

В первой строке внутри main я явно устанавливаю ссылку Object obj равной null. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.

(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)

157
задан Stephen C 1 October 2019 в 04:51
поделиться

11 ответов

Если Вы хотите истинные случайные данные, то, к сожалению, необходимо ожидать их. Это включает семя для SecureRandom PRNG. Редкая Математика не может собрать истинные случайные данные немного быстрее, чем SecureRandom, хотя это может соединиться с Интернетом для загрузки данных семени из конкретного веб-сайта. Мое предположение - то, что это вряд ли будет быстрее, чем /dev/random, где это доступно.

, Если Вы хотите PRNG, сделайте что-то вроде этого:

SecureRandom.getInstance("SHA1PRNG");

то, Какие строки поддерживаются, зависит от SecureRandom поставщик SPI, но можно перечислить их использующий Security.getProviders() и Provider.getService().

Sun любит SHA1PRNG, таким образом, это широко доступно. Это не особенно быстро, когда PRNGs идут, но PRNGs будет просто производить подсчеты, не блокируясь для физического измерения энтропии.

исключение - то, что, если Вы не звоните setSeed() прежде, чем получить данные, тогда PRNG отберет себя однажды в первый раз, когда Вы звоните next() или nextBytes(). Это будет обычно делать это использование довольно небольшого количества истинных случайных данных из системы. Этот вызов может заблокироваться, но сделает Ваш источник случайных чисел намного более безопасным, чем какой-либо вариант "хеша текущим временем вместе с PID, добавить 27, и надежда на лучшее". Если все, в чем Вы нуждаетесь, является случайными числами для игры, тем не менее, или если Вы хотите, чтобы поток был повторяем в будущем с помощью того же семени для тестирования, небезопасное семя все еще полезно.

74
ответ дан Nathan 23 November 2019 в 21:44
поделиться

Что-то еще для взгляда на является свойством securerandom.source в файле lib/security/java.security

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

1
ответ дан Diastrophism 23 November 2019 в 21:44
поделиться

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

, Если Вам не нужна эта полная гарантия случайности тогда, существуют, вероятно, соответствующие компромиссы производительности. Я был бы склонен соглашаться с ответ Dan Dyer о AESCounterRNG от Математики несвободного городского населения, или Fortuna (одним из ее авторов является Bruce Schneier, эксперт в криптографии). Я никогда не использовал ни одного, но идеи кажутся уважаемыми на первый взгляд.

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

Редактирование: вот являются [приблизительно 112] криптографическими примечаниями курса по RNG, который я нашел в 'сети, которые выглядят очень относящимися к этой теме.

2
ответ дан Community 23 November 2019 в 21:44
поделиться

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

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

я не вижу много COTS atomic-decay– основанные генераторы, но существует несколько планов там относительно них при реальной необходимости в большом количестве случайных данных. Один сайт, который всегда имеет интересные вещи посмотреть на, включая HotBits, Fourmilab John Walker.

2
ответ дан erickson 23 November 2019 в 21:44
поделиться

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

2
ответ дан Nick 23 November 2019 в 21:44
поделиться

Проблема, на которую Вы сослались [приблизительно 110], не с SecureRandom алгоритм, а с источником случайности, которую это использует. Эти два являются ортогональными. Необходимо выяснить, какой из этих двух замедляет Вас.

страница Uncommon Maths, что Вы связали явно упоминания, что они не обращаются к источнику случайности.

можно судить различных поставщиков JCE, таких как BouncyCastle, чтобы видеть, быстрее ли их реализация SecureRandom.

резюме А поиск также показывает патчи Linux, которые заменяют реализацию по умолчанию Fortuna. Я не знаю намного больше об этом, но Вы можете заняться расследованиями.

я должен также упомянуть, что, в то время как очень опасно использовать плохо реализованный SecureRandom алгоритм и/или источник случайности, Вы можете самокрутка Поставщик JCE с пользовательской реализацией SecureRandomSpi. Необходимо будет пройти процесс с Sun для подписывания поставщика, но это на самом деле довольно просто; им просто нужны Вы, чтобы отправить факсом им форму, заявляя, что Вы знаете об американских ограничениях экспорта на crypto библиотеки.

5
ответ дан Nathan 23 November 2019 в 21:44
поделиться

Если Вы хотите действительно "криптографически сильную" случайность, то Вам нужен сильный энтропийный источник. /dev/random является медленным, потому что это должно ожидать системных событий для сбора энтропии (чтение с диска, сетевые пакеты, движение мыши, нажатия клавиш, и т.д.).

А более быстрым решением является аппаратный генератор случайных чисел. У Вас может уже быть одно встроенное к Вашей материнской плате; проверьте hw_random документация для получения инструкций относительно выяснения, если у Вас есть он, и как использовать его. Пакет rng-инструментов включает демона, который будет питаться, аппаратные средства генерировали энтропию в /dev/random.

, Если HRNG не доступен в Вашей системе, и Вы готовы пожертвовать энтропийной силой за производительность, Вы захотите отобрать хороший PRNG с данными от /dev/random и позволить PRNG сделать объем работы. Существует несколько утвержденных NIST PRNG's, перечисленные в SP800-90, которые просты для реализации.

11
ответ дан Nathan 23 November 2019 в 21:44
поделиться

На Linux реализация по умолчанию для SecureRandom NativePRNG (исходный код здесь ), который имеет тенденцию быть очень медленным. В Windows значение по умолчанию SHA1PRNG, который, поскольку другие указали, что можно также использовать на Linux при определении его явно.

NativePRNG отличается от SHA1PRNG и Математика Несвободного городского населения AESCounterRNG, в котором она непрерывно получает энтропию от операционной системы (путем чтения от /dev/urandom). Другие PRNGs не получают дополнительной энтропии после отбора.

AESCounterRNG о 10x быстрее, чем SHA1PRNG, который IIRC самостоятельно в два или три раза быстрее, чем NativePRNG.

при необходимости в более быстром PRNG, который получает энтропию после инициализации, посмотрите, можно ли найти реализацию Java [1 110] Fortuna. Базовый PRNG реализации Fortuna идентичен используемому AESCounterRNG, но существует также сложная система объединения энтропии и автоматического пересева.

34
ответ дан Nathan 23 November 2019 в 21:44
поделиться

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

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

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

3
ответ дан Lorenzo Boccaccia 23 November 2019 в 21:44
поделиться

Согласно [1 123] документация , различные алгоритмы, используемые SecureRandom, в порядке предпочтения:

  • На большинстве *ОТКЛОНЯЮТ системы
    1. NativePRNG
    2. SHA1PRNG
    3. NativePRNGBlocking
    4. NativePRNGNonBlocking
  • [1 139] В системах Windows
    1. Windows-PRNG

Since SHA1PRNG , который Вы спросили о Linux, я игнорирую реализацию Windows и также SunPKCS11, который только действительно доступен на Солярисе, если Вы не установили его сами — и затем Вы не будете спрашивать это.

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

, отбор Начальной буквы SHA1PRNG
в настоящее время делается через комбинацию системных атрибутов и java.security сборочного устройства энтропии.

использование NativePRNG
nextBytes() /dev/urandom
generateSeed() использование /dev/random

NativePRNGBlocking
nextBytes() и generateSeed() использование /dev/random

NativePRNGNonBlocking
nextBytes() и generateSeed() использование /dev/urandom

, Который означает, используете ли Вы SecureRandom random = new SecureRandom(), это спускается по тому списку, пока это не находит тот, который работает, который обычно будет NativePRNG. И это означает, что отбирает себя от [1 112] (или использование, что, если Вы явно генерируете семя), затем использует /dev/urandom для получения следующих байтов, ints, дважды, булевских переменных, what-have-yous.

С тех пор /dev/random блокируется (это блокируется, пока это не имеет достаточно энтропии в энтропийном пуле), который может препятствовать производительности.

Одно решение этого использует что-то как haveged для генерации достаточной энтропии, другое решение использует /dev/urandom вместо этого. В то время как Вы могли установить это для всего jvm, лучшее решение делает его для этого определенного экземпляра [1 116], при помощи [1 117]. Обратите внимание, что тот метод может бросить NoSuchAlgorithmException если NativePRNGNonBlocking, так быть подготовленным к нейтрализации к значению по умолчанию.

SecureRandom random;
try {
    random = SecureRandom.getInstance("NativePRNGNonBlocking");
} catch (NoSuchAlgorithmException nsae) {
    random = new SecureRandom();
}

Также примечание, которые на другом *отклоняют системы, /dev/urandom, может вести себя по-другому .

<час>

/dev/urandom достаточно случайны?

Расхожее мнение имеет его, что только [1 120] достаточно случайны. Однако некоторая речь отличается. В [1 125] "Правильный Способ Использовать SecureRandom" и "Мифы о/dev/urandom" , утверждается, что /dev/urandom/ так же хорошо.

пользователи на стеке Information Security соглашаются с этим . В основном, если необходимо спросить, /dev/urandom хорошо для цели.

1
ответ дан 23 November 2019 в 21:44
поделиться

Вы должны иметь возможность выбрать более быстрый, но немного менее безопасный / dev / urandom в Linux, используя:

-Djava.security.egd=file:/dev/urandom

Однако это не работает с Java 5 и более поздние версии ( Ошибка Java 6202721 ). Предлагаемый обходной путь заключается в использовании:

-Djava.security.egd=file:/dev/./urandom

(обратите внимание на дополнительный /./ )

174
ответ дан 23 November 2019 в 21:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: