Перейти к содержимому

Base64

Base64 — способ записать произвольные двоичные данные 64 печатными символами латиницы, цифр и пары служебных знаков. Каждые три байта превращаются в четыре символа, объём растёт примерно на треть; это кодирование, а не сжатие и не шифрование.

Три байта на выходе становятся четырьмя символами

Задача, которую решает Base64, звучит так: провести двоичный файл через канал, рассчитанный только на текст. Электронная почта, JSON, XML, заголовки HTTP, файлы конфигурации — всё это исторически работает с печатными символами, а байт со значением 0x00 или 0x1B в такой поток класть нельзя: он либо потеряется, либо будет истолкован как управляющий. Решение — переписать данные ограниченным алфавитом, который одинаково понимают все системы.

Алгоритм механический. Поток бит режется не по восемь, а по шесть: шесть бит дают ровно 64 комбинации, каждой соответствует символ алфавита из RFC 4648 — латинские A-Z (значения 0-25), a-z (26-51), цифры 0-9 (52-61), плюс (62) и косая черта (63). Три байта — это 24 бита, то есть ровно четыре шестибитных группы. Отсюда постоянное соотношение 3 к 4 и рост объёма примерно на 33%.

Когда длина исходных данных не делится на три, остаток дополняется нулевыми битами, а результат добивается знаком «=» до кратности четырём. Проверить это можно на коротких примерах: два байта «QR» превращаются в «UVI=», три байта «QRc» — в «UVJj» без всякого хвоста. Слово «Мир» в UTF-8 занимает шесть байт (по два на букву) и даёт восемь символов «0JzQuNGA». Дополнение нужно декодеру, чтобы понять, сколько бит в последней группе значащие; некоторые реализации допускают его отсутствие, если длина известна из контекста.

Соседи по семейству устроены так же, но с другим основанием: Base16 — это привычная шестнадцатеричная запись с ростом объёма ровно вдвое, Base32 использует 32 символа и удобен там, где данные диктуют вслух или печатают на бумаге, потому что в его алфавите нет пар вроде «0» и «O». Общая логика здесь одна: на входе всегда байт, на выходе — символ из фиксированного алфавита. По тому же принципу устроены кодовые страницы, только они сопоставляют числа буквам, а не байты печатным символам.

Варианты алфавита и где Base64 встречается каждый день

Классический алфавит с «+» и «/» неудобен в адресной строке: плюс превращается в пробел, косая черта режет путь на сегменты. Для этого случая существует base64url — тот же принцип, но 62-й символ заменён на дефис, 63-й на подчёркивание, а дополнение часто опускают. Именно этот вариант используется в токенах JWT и в параметрах ссылок. Почтовый стандарт MIME, наоборот, требует разбивать строку через каждые 76 символов переводом строки, иначе старые почтовые серверы обрежут длинную строку.

  • Вложения в письмах — любое приложение к письму передаётся в Base64, поэтому письмо с фотографией на 3 МБ весит на диске около 4 МБ.
  • data: URI — картинка, шрифт или иконка, встроенные прямо в HTML или CSS строкой вида data:image/png;base64,iVBORw0KGgo..., без отдельного запроса к серверу.
  • API и JSON — двоичный ответ (файл, подпись, изображение) невозможно положить в JSON как есть, поэтому его кодируют строкой.
  • Заголовок Basic Authorization — пара «логин:пароль» в Base64. Это не защита: любой декодер возвращает исходную строку за миллисекунду, безопасность здесь обеспечивает только HTTPS.
  • Ключи и сертификаты в формате PEM — тело между строками BEGIN и END записано именно так.

Чем Base64 не является: сжатием (объём растёт, а не падает), шифрованием (ключа нет, преобразование обратимо для кого угодно) и защитой от повреждений (контрольной суммы внутри нет). Единственная его функция — совместимость с текстовыми каналами.

Base64 и QR-коды: где помогает, а где мешает

Полезная сторона — доставка готовой картинки кода. Когда API генерации QR-кодов отдаёт результат в JSON, изображение приходит строкой Base64, и фронтенд подставляет её в атрибут src как data: URI. То же самое в рассылках: код, встроенный в письмо строкой, отображается даже при отключённой загрузке внешних картинок, что заметно повышает долю пользователей, увидевших код. Цена — те самые плюс 33% к весу письма.

Вредная сторона — попытка положить Base64 внутрь самого кода. QR хранит байты в байтовом режиме по восемь бит на байт, никакой упаковки при этом не происходит. Закодировав 300 байт данных в Base64, вы получите 400 символов и вместо кода версии 13 будете печатать версию 16-17: модули станут мельче, требования к качеству печати и к камере — жёстче. Если данные и так текстовые, кодировать их вторично бессмысленно; если они двоичные, их лучше положить в байтовый режим напрямую.

Практическое правило: в код кладут ссылку, а не содержимое. Файл, изображение или подпись размещают на сервере, а в символ пишут короткий адрес — это и объём payload сокращает, и позволяет менять содержимое без перепечатки. Собрать такой код можно в генераторе QR-кодов, а на длину строки стоит смотреть до печати: каждые лишние 40-50 символов обычно поднимают версию символа на одну ступень.

Частые вопросы

Зачем нужен знак «=» в конце строки?

Он показывает, что последняя группа неполная. Один остаточный байт даёт два значащих символа и два знака дополнения, два байта — три символа и один знак. Декодер по количеству «=» понимает, сколько бит в конце отбросить. Если дополнение убрали (так делают в base64url), длину приходится вычислять из общего числа символов, и некоторые парсеры на этом спотыкаются.

Base64 шифрует данные?

Нет. Преобразование не использует ключ и обратимо любым онлайн-декодером за секунду. Строку Basic Authorization, «спрятанный» токен или пароль в конфиге, записанные так, читает кто угодно. Для защиты нужны шифрование и транспорт по HTTPS, а Base64 отвечает только за то, чтобы двоичные данные прошли через текстовый канал без искажений.

Почему после кодирования файл стал больше?

Так работает арифметика: каждые 3 байта исходных данных превращаются в 4 печатных символа, то есть объём растёт примерно на треть, плюс переводы строк в почтовом варианте. Уменьшить объём можно только сжатием до кодирования — сначала архивируют, потом кодируют результат. Обратный порядок бессмысленен: строка Base64 сжимается плохо.

Можно ли положить картинку в QR-код строкой Base64?

Технически можно, практически нет. Максимум байтового режима — 2953 байта на уровне коррекции L, а после кодирования это около 2,2 КБ исходных данных: даже мелкая иконка редко укладывается, а код получается версии 40 с крошечными модулями. Рабочий сценарий — положить в код ссылку на файл, а картинку хранить на сервере.

Чем base64url отличается от обычного варианта?

Двумя символами: вместо «+» используется дефис, вместо «/» — подчёркивание, дополнение «=» обычно опускается. Причина в том, что плюс и косая черта имеют особый смысл в URL и ломают ссылку при передаче. Этот вариант описан в том же RFC 4648 и применяется в JWT, параметрах запросов и именах файлов.