Я выполнял некоторую работу с классом Java SecureRandom для создания солей для последующего шифрования и хэширования паролей (я создаю отдельные соли для каждой задачи). Код, который я использовал, выглядит следующим образом:
//Init random number generator
secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(System.nanoTime());
//Create salts
secureRandom.nextBytes(bytAuthSalt);
secureRandom.nextBytes(bytEncryptionSalt);
Теперь все было хорошо, пока я не начал проверять значения, которые у меня есть. Для нескольких последовательных исполнений приложения мои соли были:
[B@43d55dd8
[B@43d55b58
[B@43d55b50
[B@43bd0cc8
[B@43db0b08
[B@43bd0f50
Меня беспокоит тот факт, что все цифры выглядят примерно последовательно. После некоторого поиска в Интернете я повторил прогоны снова, не затравливая его на те же результаты.
Мое единственное предположение о том, что может быть причиной этого, связано с тем, что я разрабатываю платформу Android. Я знаю, что у них есть собственные криптографические провайдеры, но у меня нет никаких исключений. любые идеи?
Спасибо заранее.
Похоже, вы печатаете ссылку на массив байтов вместо его содержимого. Вот почему они последовательны, ссылка в основном дает вам местоположение в памяти JVM. Преобразуйте массив байтов в строку, прежде чем печатать.
String saltContents = Arrays.toString(bytAuthSalt);
Преобразование массива в строку с помощью Arrays покажет вам необработанные значения байтов.
Кажется, вы печатаете массив, а не фактические значения. "[B @" сообщает вам, что это массив байтов, и все после него id объекта.
Попробуйте что-то вроде этого:
System.out.println("bytAuthSalt"); for (byte b : bytAuthSalt) { System.out.print(b); } System.out.println();
Или это:
Arrays.toString(bytAuthSalt);
Это будет печатать все значения в массиве.
SHA1PRNG является настолько же безопасным, как и его семя. По этой причине использование System.nanoTime()
в качестве семени - ужасная идея. Атакующий, который может сузить диапазон времени посева в достаточной степени, может опробовать все возможные значения, пока не найдет совпадающую последовательность. Злоумышленнику помогает тот факт, что разрешение System.nanoTime()
обычно намного больше 1 наносекунды.
Намного лучше сделать new SecureRandom()
, чтобы JRE могла выбрать наилучшую возможную реализацию. На большинстве платформ это будет использовать источник энтропии, основанный на ОС, для семенного RNG, например /dev/random
.
Я бы также посоветовал не использовать для посева System.nanoTime()
, так как он не гарантировал правильную работу на всех платформах. В некоторых случаях он возвращает только "ноль", который, я полагаю, не правильный номер для высева RNG.