Справочник · Данные и форматы
Хеширование: какие функции для чего подходят
Свойства криптографических хешей, сравнение MD5, SHA-1, SHA-2, SHA-3 и BLAKE, хранение паролей, HMAC и проверка файлов.
Хеш-функция превращает данные любой длины в строку фиксированной длины. Один и тот же вход всегда даёт один и тот же хеш, а малейшее изменение входа меняет результат до неузнаваемости. На этом построены проверка целостности файлов, git, подписи, кэши и хранение паролей. Но для каждой задачи подходит своя функция, и ошибка в выборе стоит дорого.
Свойства криптографического хеша
| Свойство | Что значит | Зачем нужно |
|---|---|---|
| необратимость | по хешу нельзя найти вход | хеш не раскрывает данные |
| стойкость ко второму прообразу | по данному входу нельзя подобрать другой с тем же хешем | нельзя подменить файл |
| стойкость к коллизиям | нельзя найти любые два входа с одинаковым хешем | подписи и сертификаты |
| лавинный эффект | изменение одного бита меняет около половины бит хеша | похожие входы не выдают себя |
Коллизии существуют всегда: входов бесконечно много, а хешей конечное число. Стойкость означает, что найти их вычислительно невозможно.
sha256("hello") = 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
sha256("hello.") = 1589999b0ca6ef8814283026a9f166d51c70a910671c3d44049755f07f2eb910Сравнение алгоритмов
| Алгоритм | Длина, бит | Hex-символов | Статус |
|---|---|---|---|
| MD5 | 128 | 32 | сломан: коллизии находятся за секунды |
| SHA-1 | 160 | 40 | сломан: практическая коллизия показана в 2017 году |
| SHA-224 | 224 | 56 | надёжен, редко нужен |
| SHA-256 | 256 | 64 | надёжен, стандарт по умолчанию |
| SHA-384 | 384 | 96 | надёжен |
| SHA-512 | 512 | 128 | надёжен, на 64-битных процессорах часто быстрее SHA-256 |
| SHA3-256 | 256 | 64 | надёжен, другая внутренняя конструкция |
| BLAKE2b | до 512 | до 128 | надёжен, быстрый |
| BLAKE3 | 256 и больше | 64 | надёжен, очень быстрый, параллелится |
MD5 и SHA-1 до сих пор годятся там, где нет злоумышленника: найти случайно испорченный при копировании файл, ключ для кэша, поиск дубликатов. Для подписей, сертификатов и всего, где кто-то может специально подобрать данные, — только SHA-256 и новее.
Проверка файлов
sha256sum ubuntu.iso # посчитать
sha256sum -c SHA256SUMS --ignore-missing # сверить со списком
shasum -a 256 file.zip # то же на macOS
md5sum file # быстро найти битую копию
b2sum file # BLAKE2b
certutil -hashfile file.zip SHA256 # Windows
Get-FileHash file.zip -Algorithm SHA256 # PowerShellСверка хеша защищает от повреждения при скачивании. От подмены она защищает, только если сам хеш получен из надёжного источника или подписан: злоумышленник, подменивший файл на сервере, подменит и файл с хешами.
Хранение паролей
Обычные хеш-функции созданы быстрыми. Для паролей это плохо: видеокарта перебирает миллиарды вариантов SHA-256 в секунду, и короткий пароль из утёкшей базы восстанавливается за минуты. Поэтому для паролей используют специальные медленные функции с солью.
| Функция | Статус | Параметры |
|---|---|---|
| Argon2id | рекомендуется первой | память, число проходов, параллелизм |
| scrypt | хороший выбор | N, r, p — память и время |
| bcrypt | надёжен, широко поддерживается | стоимость 10–12 и выше; учитывает только первые 72 байта пароля |
| PBKDF2-SHA256 | допустим, если других нет | от 600 000 итераций |
| SHA-256, MD5, с солью или без | нельзя | слишком быстрые |
Соль — случайная строка, уникальная для каждого пользователя. Она хранится рядом с хешем и не секретна. Её задача — чтобы одинаковые пароли давали разные хеши и чтобы нельзя было заранее посчитать таблицу хешей для всех паролей сразу.
# pip install argon2-cffi
from argon2 import PasswordHasher
ph = PasswordHasher()
stored = ph.hash("correct horse battery staple") # в строке уже есть соль и параметры
ph.verify(stored, "correct horse battery staple") # True или исключениеДлинный случайный пароль надёжнее любых хитростей с хешированием. Его можно сделать в генераторе паролей.
HMAC: хеш с ключом
Если нужно убедиться, что сообщение пришло от того, кто знает секрет, используют HMAC. Его считают для вебхуков, подписанных ссылок, токенов вроде JWT с алгоритмом HS256.
printf '%s' '{"event":"paid"}' | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET"import hmac, hashlib
sig = hmac.new(secret, body, hashlib.sha256).hexdigest()
hmac.compare_digest(sig, received_sig) # сравнение без утечки по времениНекриптографические хеши
Для хеш-таблиц, шардирования и контрольных сумм нужна скорость, а не стойкость.
| Функция | Где встречается |
|---|---|
| CRC32 | zip, PNG, Ethernet: ловит случайные ошибки передачи |
| xxHash | быстрая проверка больших файлов, базы данных |
| MurmurHash, SipHash | хеш-таблицы в языках программирования |
| FNV-1a | простые случаи, легко написать самому |
Их можно подобрать специально, поэтому для безопасности они не годятся.
Частые ошибки
- Хеш — не шифрование. Его нельзя «расшифровать». Если сервис может прислать вам ваш пароль, он хранит его не хешем.
- Хеш — не Base64. Base64 обратим и ничего не скрывает, это просто запись байт текстом.
- Хеш текста зависит от кодировки и переводов строк. Строка с
\r\nи\nдаст разные хеши, как и одна строка в UTF-8 и Windows-1251. При сравнении хешей между системами сначала договоритесь о байтах. echoдобавляет перевод строки.echo hello | sha256sumсчитает хеш отhello\n. Используйтеprintf '%s' helloилиecho -n.