Java и криптографически сильные случайные числа - PullRequest
1 голос
/ 13 января 2011

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

Заранее спасибо.

Ответы [ 4 ]

9 голосов
/ 13 января 2011

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

String saltContents = Arrays.toString(bytAuthSalt);

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

4 голосов
/ 13 января 2011

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

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

Или вот это:

Arrays.toString(bytAuthSalt);

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

2 голосов
/ 12 октября 2014

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

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

1 голос
/ 13 января 2011

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

...