RHE 7 не соблюдая java безопасное случайное семя
У меня на руках затруднение. Я создал сервис AES для шифрования / дешифрования конфиденциальной информации. Ключ AES генерируется случайным образом с использованием Java SecureRandom
, У меня есть защищенный файл, в котором хранится начальное число, и после вызова службы начальное число заполняется в класс Secure Random.
Чтобы убедиться, что это работает, у меня есть следующая логика:
private boolean secureRandom(final String seed) {
SecureRandom sr1 = new SecureRandom(seed.getBytes(UTF8_CHARSET));
SecureRandom sr2 = new SecureRandom(seed.getBytes(UTF8_CHARSET));
//Two secure random with the same seed should generate the same results
boolean secureRandomWorks = sr1.nextLong() == sr2.nextLong();
if (!secureRandomWorks) {
System.err.println("Secure random not supported. Defaulting to old key");
}
return secureRandomWorks;
}
Идея здесь в том, что я должен иметь возможность создавать два безопасных случайных объекта с одинаковым начальным числом, и они оба должны возвращать одно и то же значение при вызове nextLong()
Когда я развертываю свое приложение на машине с Windows, это работает нормально, но когда я развертываю его на машине с RHEL 7, я получаю ошибку.
У меня сложилось впечатление, что до тех пор, пока начальное число одинаковое, оба экземпляра всегда будут давать одинаковый результат. Это похоже на случай с Windows, но не тогда, когда я тестировал его на RHEL 7, похоже, что это не так.
Я создал этот простой тест для проверки:
SecureRandom sr1 = new SecureRandom("encryptionKey".getBytes("UTF-8"));
SecureRandom sr2 = new SecureRandom("encryptionKey".getBytes("UTF-8"));
for (int i = 0; i < 1000; i++) {
System.out.println(sr1.nextLong() == sr2.nextLong());
}
И на окнах каждый вывод был верным, в то время как на 7-м RHEL это было ложным
Есть какие-нибудь идеи относительно того, что может привести к тому, что RHEL 7 игнорирует семя?
2 ответа
Оказывается, что RHEL 7 (и машины Linux в целом) использует другой алгоритм по умолчанию, чем Windows. Linux использует NativePRNG
в то время как Windows использует SHA1PRNG
,
Linux использует встроенный /dev/random
или же /dev/urandom
с использованием NativePRNG
,
Имея это в виду, я смог изменить способ инициализации объекта SecureRandom.
private static final String ALGORITHM = "SHA1PRNG";
private static final String PROVIDER = "SUN";
private SecureRandom getSecureRandom(String seed) throws NoSuchAlgorithmException, NoSuchProviderException {
SecureRandom sr = SecureRandom.getInstance(ALGORITHM, PROVIDER);
sr.setSeed(seed.getBytes(UTF8_CHARSET));
return sr;
}
Из документации getInstance
не сеет объект, таким образом, он делает так, как мне нужно.
Возвращенный объект SecureRandom не был заполнен. Чтобы заполнить возвращаемый объект, вызовите метод setSeed. Если setSeed не вызывается, первый вызов nextBytes заставит объект SecureRandom заполнить себя. Это самозаполнение не произойдет, если ранее был вызван setSeed.
Теперь он вынужден использовать то, что мне нужно, и у меня не должно быть проблем с RHEL 7.
Я не нахожу документацию, которая запрещает поведение, которое вы наблюдаете на RHEL 7.
JavaDoc для java.util.Random
прямо заявляет
Если два экземпляра Random создаются с одним и тем же начальным числом, и для каждого выполняется одинаковая последовательность вызовов методов, они будут генерировать и возвращать идентичные последовательности чисел.
JavaDoc для java.security.SecureRandom
не содержит аналогичного утверждения.
Напротив, он упоминает (в документации для setSeed()
метод)
Пересевает этот случайный объект. Данное семя дополняет, а не заменяет существующее семя. Таким образом, повторные вызовы гарантированно никогда не уменьшат случайность.