Хорошо. Видя, что мне нужно писать об этом снова и снова , я сделаю один последний канонический ответ на одном только перце.
Кажущийся перевернутый перец
Кажется совершенно очевидным, что перцы должны сделать хеш-функции более безопасными. Я имею в виду, что если злоумышленник получит только вашу базу данных, то пароли ваших пользователей должны быть в безопасности, верно? Кажется логичным, верно?
Вот почему так много людей считают, что перец - хорошая идея. Это имеет смысл".
Реальность перца
В сферах безопасности и криптографии «иметь смысл» недостаточно. Что-то должно быть доказуемым и иметь смысл, чтобы это считалось безопасным. Кроме того, он должен быть осуществим в поддерживаемом виде. Самая безопасная система, которую нельзя обслуживать, считается небезопасной (потому что, если какая-либо часть этой защиты выходит из строя, вся система разваливается).
И перцы не соответствуют ни доказуемым, ни обслуживаемым моделям ...
Теоретические проблемы с перцем
Теперь, когда мы подготовили почву, давайте посмотрим, что не так с перцем.
Подача одного хэша в другой может быть опасной.
В вашем примере вы делаете hash_function($salt . hash_function($pepper . $password))
.
Из прошлого опыта мы знаем, что «просто» добавление одного хеш-результата в другую хеш-функцию может снизить общую безопасность. Причина в том, что обе хеш-функции могут стать целью атаки.
Вот почему такие алгоритмы, как PBKDF2, используют специальные операции для их объединения (в этом случае hmac).
Дело в том, что, хотя это не имеет большого значения, это также не тривиальная вещь, чтобы просто бросить вокруг. Криптосистемы предназначены для того, чтобы избежать дел «должны работать», и вместо этого сосредоточиться на делах «предназначены для работы».
Хотя это может показаться чисто теоретическим, на самом деле это не так. Например, Bcrypt не может принимать произвольные пароли . Таким образом, передача bcrypt(hash(pw), salt)
может действительно привести к гораздо более слабому хешу, чем bcrypt(pw, salt)
если бы hash()
возвращает двоичную строку.
Работать против дизайна
Bcrypt (и другие алгоритмы хеширования паролей) предназначены для работы с солью. Понятие перца никогда не было введено. Это может показаться мелочью, но это не так. Причина в том, что соль не секрет. Это просто значение, которое может быть известно злоумышленнику. С другой стороны, перец по определению является криптографической тайной.
Текущие алгоритмы хэширования паролей (bcrypt, pbkdf2 и т. Д.) Предназначены для того, чтобы принимать только одно секретное значение (пароль). Добавление еще одного секрета в алгоритм вообще не изучалось.
Это не значит, что это небезопасно. Это означает, что мы не знаем, безопасно ли это. И общая рекомендация по безопасности и криптографии: если мы не знаем, это не так.
Поэтому, пока алгоритмы не будут разработаны и проверены криптографами для использования с секретными значениями (перцами), современные алгоритмы не должны использоваться с ними.
Сложность - враг безопасности
Хотите верьте, хотите нет, но сложность - враг безопасности . Создание алгоритма, который выглядит сложным, может быть безопасным или нет. Но шансы довольно значительны, что это не безопасно.
Значительные проблемы с перцем
Это не ремонтопригодно
Ваша реализация перца не позволяет поворачивать ключ перца. Поскольку перец используется на входе в одностороннюю функцию, вы никогда не сможете изменить перец в течение срока действия значения. Это означает, что вам нужно придумать несколько хитрых хаков, чтобы заставить его поддерживать поворот ключей.
Это чрезвычайно важно, так как это требуется всякий раз, когда вы храните криптографические секреты. Отсутствие механизма поворота ключей (периодически и после нарушения) является огромной уязвимостью безопасности.
И ваш текущий подход перца потребовал бы, чтобы каждый пользователь либо полностью утратил свой пароль при ротации, либо подождал, пока его следующий логин не сменится (что может быть никогда)
Что делает ваш подход незамедлительным.
Это требует от вас, чтобы свернуть свой собственный крипто
Поскольку ни один из существующих алгоритмов не поддерживает концепцию перца, он требует от вас либо составления алгоритмов, либо изобретения новых для поддержки перца. И если вы не можете сразу понять, почему это действительно плохо:
Любой, от самого невежественного любителя до лучшего криптографа, может создать алгоритм, который он сам не сможет сломать.
НИКОГДА не катите свой собственный крипто ...
Лучший путь
Итак, из всех проблем, описанных выше, есть два способа справиться с ситуацией.
Просто используйте алгоритмы, как они существуют
Если вы используете bcrypt или scrypt правильно (с высокой стоимостью), все пароли словаря, кроме самых слабых, должны быть статистически безопасными. Текущая запись для хеширования bcrypt со стоимостью 5 составляет 71 тыс. Хешей в секунду. При такой скорости даже 6-символьный случайный пароль взламывается годами. А учитывая, что моя минимальная рекомендуемая стоимость равна 10, это уменьшает число хэшей в секунду в 32 раза. Таким образом, мы будем говорить только о 2200 хэшах в секунду. При этом даже некоторые словарные фразы или модификации могут быть безопасными.
Кроме того, мы должны проверять эти слабые классы паролей за дверью и не допускать их. По мере того, как взлом паролей становится все более сложным, также должны соблюдаться требования к качеству паролей. Это все еще статистическая игра, но с надлежащей техникой хранения и надежными паролями все должны быть практически в безопасности ...
Зашифруйте выходной хэш до хранения
В области безопасности существует алгоритм, разработанный для обработки всего, что мы сказали выше. Это блочный шифр. Это хорошо, потому что это обратимо, поэтому мы можем вращать ключи (ууу! Ремонтопригодность!). Это хорошо, потому что используется по назначению. Это хорошо, потому что это не дает пользователю никакой информации.
Давайте посмотрим на эту строку снова. Допустим, злоумышленник знает ваш алгоритм (который необходим для безопасности, иначе это безопасность через неизвестность). При традиционном перцовом подходе злоумышленник может создать сторожевой пароль, и, поскольку он знает соль и результат, он может перебить перец. Хорошо, это длинный выстрел, но это возможно. С шифром злоумышленник ничего не получает. И так как соль рандомизирована, пароль дозорного даже не поможет ему / ей. Таким образом, лучшее, что у них осталось, это атаковать зашифрованную форму. Это означает, что они сначала должны атаковать ваш зашифрованный хеш, чтобы восстановить ключ шифрования, а затем атаковать хэши. Но есть много исследований по атаке шифров, поэтому мы хотим положиться на это.
TL / DR
Не используйте перец. Есть множество проблем с ними, и есть два лучших способа: не использовать какой-либо секрет на стороне сервера (да, это нормально) и шифровать выходной хэш с использованием блочного шифра перед хранением.