Кодирование меняет представление данных, чтобы их можно было передать: Base64 превращает байты в печатные символы для JSON, почты и URL; процентное кодирование — для адресов; UTF-8 — для текста. Ключа нет, раскодировать может любой. Пароль в Base64 в конфиге или заголовок Authorization: Basic без HTTPS — это открытый текст.
Шифрование превращает данные в шифротекст, который без ключа прочитать нельзя, а с ключом — можно восстановить исходное. Нужно, когда данные потом понадобятся: передача по сети (TLS), хранение номеров карт и персональных данных, бэкапы. Симметричное (AES) — один ключ, асимметричное (RSA, эллиптические кривые) — пара ключей.
Хеширование превращает вход любой длины в отпечаток фиксированной длины. Обратной операции нет. От криптографического хеша (SHA-256, SHA-3, BLAKE2) требуется:
- по хешу нельзя найти вход (стойкость к нахождению прообраза);
- нельзя найти два разных входа с одинаковым хешем (стойкость к коллизиям);
- малейшее изменение входа полностью меняет хеш (лавинный эффект).
MD5 и SHA-1 для безопасности больше не годятся — коллизии находятся.
Где хеш: проверка целостности файлов (контрольные суммы), git (адресация объектов), цифровая подпись (подписывают хеш), дедупликация, хранение паролей — но специальными медленными функциями.
HMAC — хеш от сообщения вместе с секретным ключом. Проверяет, что сообщение отправил тот, у кого есть ключ, и оно не изменено. Применения: подпись вебхуков (платёжные системы, GitHub), подпись JWT алгоритмом HS256, подпись ссылок. Сравнивать подписи нужно за постоянное время (hmac.compare_digest), иначе можно подобрать по времени ответа.
Не путать с хеш-функцией для хеш-таблицы: там нужна скорость и равномерность, а стойкость к атакам — нет (хотя для защиты от искусственных коллизий Python и Java используют рандомизацию или деревья в корзинах).