Разговор о безопасности данных почти всегда начинается с путаницы. Один специалист говорит "данные зашифрованы в Base64", другой "хешируем пароли в MD5, значит всё надёжно", третий просит "расшифровать SHA-256". Все три фразы содержат ошибку, и ошибка не терминологическая, а архитектурная. Хеширование, шифрование и кодирование решают три разные задачи, построены на трёх разных гарантиях и ломаются тремя разными способами. Кодирование обратимо без ключа любым желающим, шифрование обратимо только владельцем ключа, хеширование необратимо вообще. Кто перепутал столп с соседним, тот получает систему, где пароли читаются вручную, а "защита" распадается от одного перехода по ссылке.
Кодирование это представление байтов а не защита
Главное свойство кодирования: обратимость по опубликованной спецификации, без всякого секрета. Base64 берёт каждые три байта входа и раскладывает их на четыре шестибитных значения, которые отображаются в алфавит из латинских букв, цифр и двух знаков. Из-за схемы 3 в 4 объект всегда раздувается примерно в 4/3 от исходного размера, плюс хвост-выравнивание из символов "=". Это не плата за секретность, это плата за транспорт: двоичные данные нужно протащить через канал, который понимает только печатный текст.
Зачем такое вообще нужно - вложения в письмах, картинки внутри JSON, точка-блоки PEM-сертификатов, тела JWT. Везде Base64 делает одно и то же: гарантирует, что байты доедут неизменными сквозь текстовую трубу. Никто не проектировал Base64 как защиту, и заголовок "Basic" в HTTP тому подтверждение: связка логин-пароль там кодируется в Base64, и любой, кто видит трафик без TLS, раскодирует её одной командой.
Побочное следствие расширения в 4/3 тоже практическое: прикреплённый к письму мегабайтный файл превращается примерно в полтора мегабайта трафика, а огромный Base64 внутри конфигурационного JSON раздувает и хранилище, и время разбора. Кодирование выбирают не из любви к тексту, а из вынужденной совместимости, и за эту совместимость платят размером.
Ловушка из практики выглядит так. Менеджер проекта докладывает "наши банковские реквизиты на витрине зашифрованы". Открываешь страницу - там строка с характерным хвостом "=", раскодируется в читаемый текст за секунду на любом онлайн-декодере. Это не взлом, это чтение по спецификации. Правило проверяется мгновенно: если "расшифровка" не потребовала ключа, значит шифрования не было, было кодирование.
Шифрование это обратимость исключительно с ключом
Шифрование - единственная из трёх операций, чья обратимость защищена: превратить шифртекст обратно в открытый текст может только тот, у кого есть ключ. Без ключа корректный шифртекст неотличим от осмысленного шума. Отсюда задача шифрования - конфиденциальность, секретность содержимого против посторонних глаз.
Симметричные схемы вроде AES-256 используют один ключ на шифрование и расшифровку. Они быстрые, их ставят на диск, на архив, на поток данных. Но круг замыкается на доставке ключа: как передать ключ собеседнику, если канал подслушивают.
Асимметричные схемы вроде RSA держат пару ключей: открытый шифрует и проверяет подпись, закрытый расшифровывает и подписывает. Они решают проблему обмена и доверия, но медленные и ограничены по размеру данных. Поэтому практические протоколы комбинируют: TLS в начале соединения с помощью асимметрии и обмена ключами договаривается о сеансовомAES-ключе, а сами гигабайты трафика гоняются симметричным шифром. Асимметрия открывает дверь, симметрия возит мебель.
Зеркало ловушки с Base64 - когда имитацию секретности маскируют шифрованием. Кастомный XOR с фиксированным байтом, "шифр" перестановкой, AES в режиме ECB, где одинаковые блоки данных дают одинаковые блоки шифртекста и сквозь экранирование проступает структура картинки. Формально это шифрование, практически защита нулевая. Доморощенные криптосхемы в проде запрещены: берутся проверенные библиотеки и стандартные режимы с аутентификацией вроде GCM.
Хеширование необратимо по построению
Хеш-функция вроде SHA-256 принимает вход любой длины и выдаёт фиксированные 256 бит. Три свойства определяют её поведение. Детерминизм: один и тот же вход всегда даёт один и тот же хеш. Лавинный эффект: изменение одного бита на входе перетасовывает примерно половину битов выхода, следовательно "почти такой же" вход узнать по хешу нельзя. Необратимость: по хешу исходный вход не восстановить ни вычислением, ни формулой, остаётся только перебор кандидатов с проверкой "совпал ли хеш".
Это и отличает хеш от шифра. Вопрос "как расшифровать хеш" не имеет ответа в принципе: расшифровывать нечего, обратного преобразования не существует. Можно лишь угадать вход и сверить. Именно поэтому быстрые хеши опасны там, где входы предсказуемы: GPU считает миллиарды SHA-256 в секунду и угадывает типовые пароли пачками.
И здесь вторая громкая ловушка. MD5 до сих пор всплывает "для безопасности" в старых системах, хотя коллизии для него генерируются практически мгновенно - два разных файла с одинаковым MD5 создаются на домашнем ноутбуке. Коллизионностойкость сломана, и подделка под чужую "цифровую печать" технически выполнима. MD5 допустим разве что как контрольная сумма против случайной порчи, и то по привычке. Для задач безопасности он выведен из обращения, как и SHA-1.
Пароли хешируют с солью и тормозами
Синтез трёх столпов доходит до крайности на паролях. Закодировать пароль - значит отдать его любому читателю таблицы. Зашифровать - значит, что ключ от всех паролей лежит где-то рядом, и утечка ключа открывает всю базу целиком, к тому же администратор с ключом может читать пароли пользователей. Остаётся хешировать: системе никогда не нужен сам пароль, ей нужно только проверять совпадение, сравнивая хеш предъявленного пароля с хранимым.
Но одного SHA-256 мало. У одинаковых паролей одинаковые хеши, и тут на сцену выходят радужные таблицы - заранее просчитанные гигантские словари "хеш -> пароль" для популярных входов. Ответ - соль: уникальная случайная строка на каждого пользователя, которая подмешивается к паролю перед хешированием и хранится рядом в открытом виде. Соль не секрет, её дело другое: два одинаковых пароля дают разные хеши, а радужная таблица превращается в бесполезный хлам, потому что перебирать придётся заново под каждую соль.
Вторая половина защиты - медленная функция. SHA-256 спроектирован быстрым, что подарок для атакующего со словарём. Argon2 и bcrypt проектировались наоборот: они намеренно сжигают процессорное время, а Argon2дополнительно требует большого объёма памяти, что режет параллелизм на GPU-фермах. Для легитимного логина лишние сто миллисекунд незаметны, для перебора триллионов вариантов - приговор. Формула хранения паролей в проде едина: уникальная соль плюс медленная функция с современными параметрами, быстрые хеши запрещены.
Подписи TLS и цепочки доверия
Красивее всего связка трёх операций видна в цифровой подписи и сертификатах TLS. Подпись не "зашифровывает документ". Сначала документ сворачивается хешем в короткий дайджест, затем закрытым ключом владельца совершается асимметричная операция именно над хешем. Проверяющий берёт открытый ключ владельца, проверяет подпись и независимо считает хеш документа. Совпало - документ цел и исходит от держателя ключа. Хеш ужал данные, асимметрия привязала владельца.
TLS-сертификат сайта - та же конструкция, только документом служит открытый ключ сайта, подписанный удостоверяющим центром. Центр в свою очередь подписан промежуточным, промежуточный корневым, а корневой зашит в хранилище доверенных сертификатов операционной системы и браузера. Цепочка доверия проступает как лестница подписей поверх хешей: доверие укоренено локально, проверено математикой, не нуждается в обращении наружу. Сломай хеш-функцию в основании - и появится возможность подделать цепочку, что и стало исторической причиной вывода MD5 и SHA-1 из доверенных подписей.
Целостность секретность транспорт и HMAC
Разбор сводится к трём вопросам, которые надо задавать вместо одного "а защищено ли". Целостность - не поменяли ли объект по дороге: отвечает хеш, например SHA-256 рядом с инсталлятором вендора. Секретность - видит ли содержимое только свой: отвечает шифрование с ключом. Транспорт - доедут ли байты сквозь текстовый канал: отвечает кодирование. Три задачи часто идут вместе одним файлом: инсталлятор подписан и сверен по хешу для целостности, архив с данными лежит под AES для секретности, токен летит в заголовке в Base64 для транспорта, при этом сам токен подписан.
Отдельно стоит HMAC - конструкция "хеш плюс секретный ключ". Обычный хеш файла доказывает случайную целостность, но злоумышленник пересчитает хеш для подменённого файла. HMAC подмешивает ключ внутрь хеширования, поэтому сфабриковать корректное значение может лишь держатель ключа: получается доказательство целостности и подлинности без асимметрии. На HMAC строятся подписи вебхуков, проверка сообщений между сервисами, принцип "шифруй и аутентифицируй" вместо голого шифра.
Мини-примеры из консоли Windows
Закрепить разницу помогают две живые команды. Контроль целостности файла без всяких ключей:
certUtil -hashfile installer.exe SHA256
Скачанный файл считается хешем за пару секунд, результат сверяется с опубликованным у вендора - совпадение говорит, что побито тот самый файл, несовпадение отправляет файл в корзину. Это чистое хеширование, здесь нет ни секрета, ни восстановления.
Шифрование с ключом ближе к PowerShell:
$s = ConvertTo-SecureString "Pa55w0rd" -AsPlainText -Force
Строка превращается в защищённый объект, который через ConvertFrom-SecureString разворачивается в шифртекст под ключом, привязанным к учётной записи и машине. Файл с выводом бесполезен в чужих руках, а под своей учёткой скрипт разворачивает секрет обратно - Обратимость держится на ключе, ровно по определению шифрования. Для конtrastа: encode в Base64 той же строки cmdlet Convert даёт декодируемый всеми текст, декодирование не спросит ни учётку, ни ключ.
Финальная шпаргалка коротка. Закодировано - восстановит любой по спецификации. Зашифровано - восстановит только владелец ключа. Захешировано - не восстановит никто, только сверяется. Кто держит эти три предложения в голове, тот не назовёт Base64 шифрованием, не сохранит пароль в MD5 и не попросит расшифровать хеш на собеседовании - а собеседы, кстати, этим вопросом и открываются.
Соль и перец как экономика взлома. Даже медленный хеш не спасает словарный пароль, если вся база посолена одинаково: задача соли - не усилить каждый пароль, а разоружить атакующего против массового сравнения. При разной соли общеизвестный словарь доводится до каждой записи отдельно, и экономика меняется на порядки: вместо одной таблицы на весь парк нужен полный перебор для каждого пользователя. Перец - серверный секрет, хранящийся отдельно от базы хэшей, - добавляет уровень: без него украденная база не покупает ничего. Практический вывод звучит странно только в первый раз: защита паролей определяется не стойкостью хэша к перебору, а тем, сколько стоит каждый вариант перебора в условиях конкретного сервера.
Общий снимок посада для занятого читателя. Кодирование перемещает данные через системы, не меняя смысл; шифрование делает смысл недоступным без ключа; хеширование уничтожает вход и оставляет росчерк целостности. Смешение любых двух граней в одном слове всегда рождает архитектурную ошибку: пароль, который «зашифрован» - это пароль, который ещё можно достать обратно, хэш, который «функция без коллизий», - это хэш, которого ещё не добрались вычислительные мощи. Поэтичное мышление путает имена, инженерное мышление смотрит, что именно уничтожается и что именно передаётся.