Много иетераций хэши: каждый раз добавляйте соль?

Я использовал unsalted md5/sha1 в течение длительного времени, но поскольку этот метод не является действительно безопасным (и с течением времени становится еще менее безопасным), я решил переключиться на соленое sha512. Кроме того, я хочу замедлить генерацию хеша, используя множество итераций (например, 100).

Мой вопрос: должен ли я добавлять соль на каждой итерации или только один раз в начале. Вот два возможных кода:

Добавить каждый раз:

// some nice big salt
$salt = hash($algorithm, $salt);

// apply $algorithm $runs times for slowdown
while ($runs--) {
    $string = hash($algorithm, $string . $salt, $raw);
}

return $string;

Добавить один раз:

// add some nice big salt
$string .= hash($algorithm, $salt);

// apply $algorithm $runs times for slowdown
while ($runs--) {
    $string = hash($algorithm, $string, $raw);
}

return $string;

Сначала я хотел использовать вторую версию (добавить один раз), но затем нашел несколько скриптов, добавляющих соль каждый раз.

Итак, я задаюсь вопросом, добавляет ли он каждый раз добавление некоторой силы в хеш. Например, возможно ли, что злоумышленник нашел какой-то умный способ создать функцию 100timesSha512, которая была быстрее, чем просто выполнить sha512 100 раз?

Ответ 1

Короче: Да. Идите с первым примером... Хеш-функция может потерять энтропию, если она возвращается к себе, не добавляя исходные данные (я не могу найти ссылку сейчас, я буду продолжать искать).

И для записи, я поддерживаю хеширование несколько раз.

Хэш, который занимает 500 мс для генерации, не слишком медленный для вашего сервера (учитывая, что генерация хэшей обычно не выполняется подавляющим большинством запросов). Однако хэш, который длится так долго, значительно увеличит время, которое потребуется для создания таблицы радуги...

Да, это подвергает уязвимость DOS, но также предотвращает атаки грубой силы (или, по крайней мере, делает их чрезмерно медленными). Существует абсолютно компромисс, но некоторые преимущества превышают риски...

Ссылка (больше похоже на обзор) на весь процесс: Укрепление ключей

Что касается вырождающихся столкновений, единственным источником, который я смог найти до сих пор, является это обсуждение...

И еще несколько обсуждений по теме:

И еще несколько ссылок:

Есть тонны результатов. Если вы хотите больше, Google hash stretching... Там тонны хорошей информации там...

Ответ 2

В дополнение к повторному хешированию его несколько раз, я использовал бы другую соль для каждого пароля/пользователя. Хотя я думаю, что 5000 итераций слишком много, попробуйте меньшее число. Там компромисс здесь; вам придется настроить его в соответствии с вашими потребностями и оборудованием.

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

Как всегда, здесь рекомендуется прочитать для этого: Простое хэширование далеко не достаточно

EDIT: Итеративное хеширование - это отлично действующая тактика. Есть компромиссы, но у них все есть. Если вы беспокоитесь о времени вычисления, почему бы просто не хранить пароль открытого текста?

Ответ 3

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

Соленые хэши в OpenSSL

Ответ 4

Причина итеративного хеширования заключается в том, чтобы сделать процесс как можно медленнее. Таким образом, вы можете сделать еще лучше: используйте разные соли для каждой итерации. Это можно сделать, зашифровав исходные данные снова и снова на каждой итерации с помощью фиксированного ключа и XORing со значением соли.

Ответ 5

Я предпочитаю идти с двойным sha1 с двумя разными солями и предотвращать задержку ответа DoS поэтапно (простым проглатыванием) для каждой неверной проверки пароля.