Java и криптографически сильные случайные числа

1

Я выполнял некоторую работу с классом 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. Я знаю, что у них есть собственные криптографические провайдеры, но у меня нет никаких исключений. любые идеи?

Спасибо заранее.

Теги:
encryption
salt

4 ответа

9
Лучший ответ

Похоже, вы печатаете ссылку на массив байтов вместо его содержимого. Вот почему они последовательны, ссылка в основном дает вам местоположение в памяти JVM. Преобразуйте массив байтов в строку, прежде чем печатать.

String saltContents = Arrays.toString(bytAuthSalt);

Преобразование массива в строку с помощью Arrays покажет вам необработанные значения байтов.

  • 3
    Если я не ошибаюсь, это будет интерпретировать байты, используя набор символов по умолчанию, вместо того, чтобы распечатывать необработанные байты. Разве OP не хочет сырые байты, а не эквивалентные ASCII символы?
  • 1
    @ RD01 - Но, тем не менее, он даст ОП хорошее представление о случайности значений.
Показать ещё 5 комментариев
4

Кажется, вы печатаете массив, а не фактические значения. "[B @" сообщает вам, что это массив байтов, и все после него id объекта.
Попробуйте что-то вроде этого:

System.out.println("bytAuthSalt");
  for (byte b : bytAuthSalt) {
    System.out.print(b);
  }
  System.out.println();

Или это:

Arrays.toString(bytAuthSalt);

Это будет печатать все значения в массиве.

  • 3
    или Arrays.toString (byte [])
  • 0
    Ой ну спасибо! Не знал этого.
Показать ещё 2 комментария
2

SHA1PRNG является настолько же безопасным, как и его семя. По этой причине использование System.nanoTime() в качестве семени - ужасная идея. Атакующий, который может сузить диапазон времени посева в достаточной степени, может опробовать все возможные значения, пока не найдет совпадающую последовательность. Злоумышленнику помогает тот факт, что разрешение System.nanoTime() обычно намного больше 1 наносекунды.

Намного лучше сделать new SecureRandom(), чтобы JRE могла выбрать наилучшую возможную реализацию. На большинстве платформ это будет использовать источник энтропии, основанный на ОС, для семенного RNG, например /dev/random.

1

Я бы также посоветовал не использовать для посева System.nanoTime(), так как он не гарантировал правильную работу на всех платформах. В некоторых случаях он возвращает только "ноль", который, я полагаю, не правильный номер для высева RNG.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню