Безопасен ли этот кусок кода?
SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());
Правильно ли это пример семени безопасного случайного?
Безопасен ли этот кусок кода?
SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());
Правильно ли это пример семени безопасного случайного?
Нет, вам следует избегать конструктора 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/
Я думаю, что лучше всего оставить семестр SecureRandom. Это делается путем вызова nextBytes сразу после его создания (вызов setSeed предотвратит это).
final byte[] dummy = new byte[512];
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.nextBytes(dummy);
Вы хотите использовать SHA1PRNG, потому что он гарантирует быструю неблокирующую реализацию даже в Linux, где по умолчанию нет.
Код достаточно безопасен, потому что он не просто использует семя для семян рандомизатора.
Это не намного более случайное, чем просто использование.
SecureRandom randomizer = new SecureRandom();