Что такое хеш и почему пароли никто не хранит
Хеш-функция превращает любой файл — хоть фразу, хоть фильм — в короткий отпечаток фиксированной длины. Объясняем, почему по отпечатку нельзя восстановить оригинал и как это спасает ваши пароли от утечек.
Возьмите файл любого размера, пропустите через хеш-функцию — и получите короткий отпечаток, по которому файл не восстановить, но всегда можно опознать.
Хеш — это цифровой отпечаток данных. Как и отпечаток пальца, он крошечный, уникальный и не позволяет «отрастить обратно» своего владельца.
Слово «хеш» (от английского «крошить, рубить») звучит сложно, а идея простая. Хеш-функция берёт данные любого размера — одну букву или гигабайтный фильм — и выдаёт строку фиксированной длины, например 64 шестнадцатеричных символа. Эту строку называют хешем, или отпечатком данных.
Три свойства, на которых всё держится
Чтобы хеш приносил пользу, функция должна обладать тремя качествами:
- Детерминированность. Одни и те же данные всегда дают один и тот же хеш. Иначе проверять было бы нечего.
- Лавинный эффект. Измените хоть один символ во входе — и хеш меняется до неузнаваемости, целиком. Не «немного», а полностью.
- Необратимость. По хешу нельзя восстановить исходные данные. Функция работает только в одну сторону.
Последнее свойство кажется странным: куда делась информация? Она «перемешана и обрублена» так, что разных входов, дающих один и тот же выход, бесконечно много, и угадать нужный нереально. Подумайте сами: на вход можно подать файл любого размера, а выход всегда фиксированной длины — скажем, 256 бит. Значит, разных входов несравнимо больше, чем возможных выходов, и какие-то из них неизбежно дают одинаковый хеш. Такое совпадение называют коллизией. У хорошей функции коллизии существуют лишь теоретически: специально подобрать два осмысленных файла с одинаковым хешем практически невозможно, на это не хватит и всех компьютеров планеты. Именно поэтому отпечаток можно считать уникальным на практике, хотя в теории абсолютная уникальность недостижима.
Кстати, у слова «хеш» есть и совсем другое, бытовое для программистов применение — быстрый поиск. Когда в программе нужно мгновенно находить значение по ключу, ключ прогоняют через хеш-функцию и по полученному числу кладут данные в нужную ячейку. Это сердце структуры, которую называют хеш-таблицей. Но это отдельная история; нас сейчас интересуют именно «отпечатки» данных для проверки и безопасности.
Проверка целостности: файл доехал целым?
Самое наглядное применение — убедиться, что файл не повредился при скачивании. Сайт публикует хеш дистрибутива. Вы скачиваете файл, считаете его хеш у себя и сравниваете. Совпало — файл байт в байт тот же. Не совпало — где-то потерялся или подменился хотя бы один бит, и качать надо заново.
import hashlib
for text in ["привет", "Привет", "привет."]:
h = hashlib.sha256(text.encode("utf-8")).hexdigest()
print(f"{text!r:>10} -> {h[:16]}...")Запустите — и увидите лавинный эффект: «привет» и «Привет» отличаются одной заглавной буквой, а хеши не похожи совершенно.
Почему пароли хранят как хеши
Вот главное практическое применение. Серьёзные сервисы не хранят ваши пароли в открытом виде. Вместо пароля в базе лежит его хеш. Когда вы входите, система хеширует введённое и сравнивает с сохранённым хешем. Совпало — пускаем.
Зачем так сложно? Затем, что базы данных утекают. Если бы там лежали пароли открытым текстом, утечка означала бы катастрофу. А утечка хешей менее опасна: обратно пароль из хеша не восстановишь.
Соль против хитрых злоумышленников
Правда, у атакующих есть приём: заранее посчитать хеши миллионов популярных паролей и искать совпадения в утёкшей базе. Защита называется солью — к каждому паролю перед хешированием добавляют случайную строку, своя у каждого пользователя. Тогда одинаковые пароли дают разные хеши, и заранее заготовленные таблицы бесполезны.
| Что хранит сервис | Опасность при утечке |
| пароль открытым текстом | катастрофа |
| простой хеш | средняя |
| хеш с солью | низкая |
Поэтому, когда сайт честно говорит «мы не можем напомнить ваш пароль, только сбросить», — это хороший знак. Значит, он хранит не пароль, а его необратимый отпечаток, и поступает правильно.