Прекратите использовать MD5 и SHA-1!
Недавно в социальных сетях прошло несколько интересных обсуждений, вызванных предлагаемым устареванием функций md5()
, sha1()
, md5_file()
и sha1_file()
.
Устаревание этих методов не помешало бы вам использовать MD5 и SHA-1 в своём коде, речь идёт только о конкретных вспомогательных псевдонимах. В PHP есть методы hash($algo, $value)
и hash_file($algo, $filename)
, предоставляющие доступ ко всем поддерживаемым алгоритмам хеширования. Фактически, это единственный способ использовать безопасные алгоритмы хеширования, поэтому MD5 и SHA-1 по-прежнему используются так часто!
К сожалению, похоже, что голосование провалится, и они не будут объявлены устаревшими. Но поскольку я всё ещё выступаю за устаревание этих функций, думаю, это хорошая возможность взглянуть на более безопасные альтернативы MD5 и SHA-1.
Хеши паролей
MD5 и SHA-1 никогда не следует использовать для хэширования паролей, даже если они солёные. Фактически, ни один алгоритм хэширования не должен использоваться для паролей. Их слишком легко взломать методом перебора, даже если они солёные, и они не обеспечивают практически никакой защиты.
Используйте bcrypt
, специализированный алгоритм хэширования паролей, либо фасад Hash
в Laravel, либо непосредственно метод password_hash()
в PHP. Если всё ещё используются пароли без bcrypt
, их следует перехешировать, чтобы сохранить безопасность.
return Hash::make($password);
Контрольные суммы
И MD5, и SHA-1 уязвимы к коллизиям хэша (когда два разных ввода дают один и тот же хэш), что может позволить злоумышленнику заменить легитимные файлы, проверенные по контрольной сумме, на вредоносные файлы с такой же контрольной суммой.
Используйте SHA-256 (или SHA-512) для генерации безопасного хэша с помощью функции hash_file()
:
return hash_file('sha256', 'example.txt');
Если не нужен безопасный хэш, а просто метод проверки на повреждение файла или уникальное значение для очистки кэша, то MD5/SHA-1 подойдут, но в идеале следует использовать специальный алгоритм контрольной суммы, например CRC-32, для быстрого расчёта контрольной суммы:
return hash_file('crc32b', 'example.txt');
(Криптографические) Подписи
MD5 и SHA-1 не должны использоваться для каких-либо криптографических целей и не подходят для любой формы криптографической подписи. Они уязвимы к коллизиям и перебору, и им нельзя доверять защиту значений.
Используйте Код Аутентификации Сообщения на основе Хэша (HMAC) с SHA-256 для создания безопасного хэша:
return hash_hmac($algo, $plaintext, $secretKey);
Уникальные ключи
MD5/SHA-1 безопасен для такого использования, поскольку нужна только уникальность, а не безопасность, однако алгоритм xxHash предоставляет гораздо более быструю альтернативу, способную повысить производительность приложения. (Это также причина, по которой следует использовать crc32 для контрольных сумм).
Переходите на XXH128, чтобы повысить скорость работы кода:
return hash('xxh128', $value);
Случайные строки
MD5/SHA-1 никогда не следует использовать для генерации случайных строк, и особенно с такими кодами, как md5(time())
, md5(rand())
, substr(md5($user->email), 8, 16)
и т. д. (Да, я видел такое…)
Используйте криптографически безопасную случайность с помощью random_bytes()
, Str::random()
, PHP класса Randomizer
или моего пакета Random
.
return Str::random(32);
Поддержка легаси
Если необходимо поддерживать системы сторонних разработчиков, избегать внесения изменений или поддерживать преемственность между легаси и современными системами, то, возможно, пока стоит придерживаться MD5/SHA-1. Это актуально для таких вещей, как сторонние API, использующие MD5 для проверки веб-хуков (это очень распространено).
Если всё ещё используете MD5 или SHA-1, спланируйте безопасный путь обновления до безопасных и/или более быстрых альтернатив (например, перехэширование паролей), чтобы можно было отказаться от использования MD5 и SHA-1 в коде. Также, если работаете со сторонними разработчиками, которым нужны эти функции, напомните им о необходимости перехода на безопасную альтернативу.