В общем случае вам не нужно использовать более одного алгоритма хеширования.
Что вам нужно сделать, это:
Используйте соль: соль используется не только для того, чтобы сделать ваш пароль более безопасным , она используется для предотвращения атаки на радужный стол. Таким образом, кому-то придется потрудиться, пытаясь предварительно вычислить хэш для паролей, которые вы храните в своей системе.
Используйте несколько взаимодействий: вместо просто SHA (пароль + соль), сделайте SHA (SHA (SHA (SHA (SHA (... SHA (пароль + соль)))))). Или представить по-другому:
hash = sha(password + salt)
for i=1 , i=5000, i++ {
hash = sha(hash + salt);
}
И, наконец, выберите хорошую функцию хеширования. SHA, MD5 и т. Д. Не очень хороши, потому что они слишком быстрые . Поскольку вы хотите использовать хеш для защиты, вам лучше использовать более медленные хеши. Посмотрите на Bcrypt , PBKDF2 или Scrypt , например.
редактировать : после наблюдений давайте попробуем увидеть некоторые моменты (извините, длинное объяснение до конца, потому что это может помочь другим в поиске похожих ответов):
Если ваша система безопасна, как никто и никогда не получит доступ к сохраненному паролю, вам не понадобится хеш. Пароль будет секретным, никто не получит его.
Но никто не может заверить, что база данных с паролями будет украдена. Украсть базу, получил все пароли. Хорошо, ваша система и ваша компания пострадают от всех последствий. Таким образом, мы могли бы попытаться избежать утечки этого пароля.
ОБРАТИТЕ ВНИМАНИЕ, что на данный момент мы не беспокоимся о сетевых атаках. Для одной онлайн-атаки лучшее решение - это замедлить работу после ввода неверных паролей, заблокировать учетную запись после нескольких попыток и т. Д. И для этого не имеет значения, каким образом вы шифруете, хешируете, сохраняете и т. Д. Свой пароль. Атака онлайн - это вопрос замедления ввода пароля .
Итак, вернемся к don't let them take my plain passwords
проблеме. Ответ прост: не храните их в виде простого текста. Хорошо понял.
Как этого избежать?
Зашифруйте пароль (?). Но, как вы знаете, если вы шифруете его, вы можете расшифровать его обратно, если у вас есть соответствующий ключ. И вы столкнетесь с проблемой «где спрятать» ключ. Хм, ничего хорошего, так как они получили вашу базу данных, они могут получить ваш ключ. Хорошо, давайте не будем его использовать.
Итак, другой подход: давайте преобразуем пароль во что-то еще, что нельзя отменить, и сохраним его. И чтобы проверить правильность введенного пароля, мы снова делаем тот же процесс и проверяем, совпадают ли два преобразованных значения. Если они совпадают = хороший пароль был предоставлен.
Хорошо, пока все хорошо. Давайте используем некоторый хэш MD5 в пароле. Но ... если у кого-то есть сохраненное нами хешированное значение пароля, у него может быть много вычислительных мощностей для вычисления хеша MD5 каждого возможного пароля (грубой силы), чтобы он мог найти оригинальный пароль. Или, что еще хуже, он может хранить все MD5 из всех комбинаций символов и легко найти пароль. Итак, сделайте много итераций, HASH (HASH (HASH ())), чтобы сделать его сложнее, потому что это займет больше времени.
Но даже это можно обойти, радужный стол был создан именно для того, чтобы ускорить такую защиту.
Итак, давайте использовать немного соли над ним. Таким образом, при каждом взаимодействии соль используется снова. Тот, кто пытается атаковать ваши пароли, должен будет создать радужную таблицу, учитывая, что соль добавляется каждый раз. И когда он сгенерирует эту радужную таблицу, так как она была сгенерирована с одной солью, ему придется снова вычислять с другой солью, поэтому ему придется потратить некоторое время на каждый пароль (= каждую соль). Соль не добавит «усложнения» к паролю, она просто заставит злоумышленника терять время на создание радужной таблицы. Если вы используете одну соль для каждого пароля, таблица из одной соли бесполезна для другого пароля.
И использование более чем одного хеша поможет здесь? Нет. Человек, генерирующий определенную атаку радуги, в любом случае сможет генерировать ее, используя один или несколько хэшей.
И использование более одного хеша может привести к одной проблеме: он так же безопасен, как и самый слабый хеш, который вы используете. Если кто-то обнаружит коллизии в одном алгоритме хеширования, то именно этот хеш будет использоваться в любой точке итерационного процесса для взлома пароля. Таким образом, вы ничего не получите, используя больше алгоритмов хеширования, лучше выбрать только один хороший алгоритм. и использовать это. И если вы когда-нибудь услышите, что он сломан, подумайте, как вы измените его в своем приложении.
И зачем использовать bcrypt или что-то подобное (вы говорите, что используете): потому что злоумышленнику придется тратить больше времени на создание таблиц. Вот почему использование MD5 + wait (3 секунды) не помогает: атака в любом случае будет автономной, поэтому злоумышленник может сгенерировать таблицы без (задержка в 3 секунды).