Вопрос-ответ

How to deal with a slow SecureRandom generator?

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

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

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

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

Переведено автоматически
Ответ 1

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

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

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

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

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

Ответ 2

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

Если вам нужен PRNG, сделайте что-то вроде этого:

SecureRandom.getInstance("SHA1PRNG");

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

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

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

Ответ 3

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

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

AESCounterRNG примерно в 10 раз быстрее, чем SHA1PRNG, а IIRC сам по себе в два или три раза быстрее, чем NativePRNG.

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

Ответ 4

Многие дистрибутивы Linux (в основном на базе Debian) настраивают OpenJDK на использование /dev/random для энтропии.

/dev/random по определению является медленным (и даже может блокировать).

Отсюда у вас есть два варианта, как его разблокировать:


  1. Улучшить энтропию, или

  2. Снизить требования к случайности.

Вариант 1, повышение энтропии

Чтобы увеличить энтропию /dev/random, попробуйте демон haveged. Это демон, который непрерывно собирает избыточную энтропию, а также работает в виртуальной среде, потому что для этого не требуется никакого специального оборудования, только сам процессор и часы.

В Ubuntu / Debian:

apt-get install haveged
update-rc.d haveged defaults
service haveged start

На RHEL / CentOS:

yum install haveged
systemctl enable haveged
systemctl start haveged

Вариант 2. Снизить требования к случайности

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

Чтобы сделать это глобально, отредактируйте файл jre/lib/security/java.security в вашей установке Java по умолчанию для использования /dev/urandom (из-за другой ошибки его необходимо указать как /dev/./urandom).

Вот так:

#securerandom.source=file:/dev/random
securerandom.source=file:/dev/./urandom

Тогда вам никогда не придется указывать это в командной строке.


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

java performance