Поправьте меня, если я не прав, но, насколько я понимаю, если перец не используется, то на сегодняшний день оптимальное решение это
bcrypt($password)
(случайная соль, cost=10). При этом будут использованы только первые 72 символа пароля, что допустимо. Возможные вариации -
scrypt($password)
если есть вероятность, что ломать будут всерьёз на спец.железе либо
sha256($password . $salt)
если есть опасность, что использование bcrypt может привести к DoS атаке вашего сервиса из-за отсутствия адекватной защиты от перебора паролей.
А вот с перцем всё не настолько однозначно. Он должен быть достаточно большим, поэтому если просто добавить его к паролю, это сильно снизит количество используемых символов пароля. Чтобы этого избежать, нужно использовать комбинацию из bcrypt и HMAC, и вот тут есть варианты, разница между которыми с точки зрения криптографии мне не ясна:
bcrypt(hmac_sha256($pepper, $password))
hmac_sha256($pepper, bcrypt($password))
Какой из этих вариантов лучше?
Ещё один вопрос - в качестве примера часто используют
hmac_sha256($password, $pepper)
но мне кажется что логичнее первым параметром (в качестве ключа) передавать перец:
hmac_sha256($pepper, $password)
Есть ли между этими вариантами какая-то разница с точки зрения криптографии?
P.S. Да, подразумевается что hmac_sha256() возвращает результат в base64 - иначе могут возникнуть проблемы из-за нулевого байта в некоторых реализациях bcrypt.