Безопасное семя SecureRandom в Java

Безопасен ли этот кусок кода?

 SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());

Правильно ли это пример семени безопасного случайного?

Ответ 1

Нет, вам следует избегать конструктора SecureRandom(byte[]). Это небезопасно и не переносится.

Он не переносится, поскольку он ведет себя по-разному в Windows и других операционных системах.

В большинстве ОС по умолчанию используется "NativePRNG", который получает случайные данные из ОС (обычно "/dev/random") и игнорирует предоставленное вами семя.

В Windows по умолчанию используется алгоритм "SHA1PRNG", который объединяет ваше семя с счетчиком и вычисляет хэш результата.

Это плохая новость в вашем примере, потому что вход (текущее время UTC в миллисекундах) имеет относительно небольшой диапазон возможных значений. Например, если злоумышленник знает, что RNG был засеян за последние 48 часов, они могут сузить семя до менее чем 2 28 возможных значений, т.е. У вас есть только 27 бит энтропии.

Если, с другой стороны, вы использовали конструктор по умолчанию SecureRandom() в Windows, он бы вызвал функцию native CryptoGenRandom, чтобы получить 128-битное семя. Поэтому, указав свое собственное семя, вы ослабили безопасность.

Если вы действительно хотите переопределить семя по умолчанию (например, для модульного тестирования), вы также должны указать алгоритм. Например.

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed("abcdefghijklmnop".getBytes("us-ascii"));

См. также Как решить проблему производительности с помощью Java SecureRandom?
и это сообщение в блоге: http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

Ответ 2

Я думаю, что лучше всего оставить семестр SecureRandom. Это делается путем вызова nextBytes сразу после его создания (вызов setSeed предотвратит это).

final byte[] dummy = new byte[512];
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.nextBytes(dummy);

Вы хотите использовать SHA1PRNG, потому что он гарантирует быструю неблокирующую реализацию даже в Linux, где по умолчанию нет.

Ответ 3

Код достаточно безопасен, потому что он не просто использует семя для семян рандомизатора.

Это не намного более случайное, чем просто использование.

SecureRandom randomizer = new SecureRandom();