Как решить, какой самый безопасный способ генерировать случайные числа в Java с помощью класса SecureRandom
Мне интересно, какой из них является наилучшим способом генерирования случайного числа с высокой степенью защиты в диапазоне 0-255 и, кроме того, с быстродействием. Мне приходит в голову, что я обязательно должен использовать класс SecureRandom, но я не уверен, должен ли я использовать.getInstance(SHA1PRNG) или лучше оставить его по умолчанию без конструктора arg.
Я нахожусь между этими двумя вариантами:
Первый путь
public class RandomGenerator {
private static final String sha1prng = "SHA1PRNG";
private final SecureRandom csprng;
private final byte[] bytes = new byte[1];
public RandomGenerator() {
try {
csprng = SecureRandom.getInstance(sha1prng);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
csprng.nextBoolean();
}
protected int generateByte() {
do {
csprng.nextBytes(bytes);
} while (bytes[0] == 0);
return ((byte)(bytes[0] & 0xff) + 256) % 256;
}
}
Второй путь:
public class SomethingThatNeedsRandomBytes {
private static final int NUMBER_OF_RANDOM_BYTES = ... ;
private final SecureRandom csprng;
SomethingThatNeedsRandomBytes(SecureRandom csprng) {
if (csprng == null)
throw new IllegalArgumentException();
this.csprng = csprng;
}
void doSomethingInvolvingRandomness() {
byte[] bytes = new byte[NUMBER_OF_RANDOM_BYTES];
csprng.nextBytes(bytes);
// Do something with random bytes here.
}
}
Я видел много других ответов на этих сайтах, и большинство из них предлагают не использовать SHA1PRNG и оставить его по умолчанию, но, с другой стороны, некоторые другие ответы предлагают использовать NativePRNG (который я не предпочитаю, поскольку он не быстрый) или SHA1PRNG, Я хотел бы получить отзыв о том, какой из способов генерирует случайные числа с высокой степенью защиты, а какой является самым быстрым.
Заранее спасибо.
1 ответ
С пустым конструктором SecureRandom выберет первого зарегистрированного провайдера безопасности, который поддерживает алгоритм SecureRandom; если ничего не существует, по умолчанию используется значение SHA1PRNG. Это будет зависеть от системы. Если ваше приложение может работать в разных средах, вы должны указать алгоритм в конструкторе. Чтобы получить порядок поставщиков безопасности для SecureRandom, вы можете запустить следующее:
import java.security.Security;
import java.security.Provider;
import java.security.Provider.Service;
for (Provider provider : Security.getProviders()) {
for (Service service : provider.getServices()) {
if (service.getType().equals("SecureRandom")) {
System.out.println(service.getAlgorithm());
}
}
}
Реализация NativePRNG зависит от операционной системы, но обычно использует энтропию, генерируемую событиями оборудования или операционной системы, для получения случайных значений. Часто это должно ждать генерации энтропии, прежде чем можно будет вернуть значение. В абсолютном выражении это более безопасно, чем SHA1PRNG; однако практически вы вряд ли заметите разницу. Если скорость алгоритма важна для приложения, SHA1PRNG, как правило, будет быстрее, чем NativePRNG, и оба алгоритма предоставляют достаточно случайные значения для криптографических операций. Следует отметить, что для таких приложений, как хеширование паролей, более предпочтительным является более медленный алгоритм.
Смотрите: https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html