Перейти к содержимому
🚀 Уже доступно 10 инструментов, бесплатно навсегда — и список растёт
Главная›Блог›Base64 простыми словами: как работают кодирование и декодирование
Руководства

Base64 простыми словами: как работают кодирование и декодирование

Как Base64 на самом деле превращает три байта в четыре символа, почему алфавитов два и когда важен каждый, зачем нужно заполнение =, почему «закодировано в Base64» — никогда не мера защиты, и как разобраться, если на выходе получается мусор.

✍ Автор — основатель и CEO, команда BuildToolForge🗓 2026-10-17⏱ 11 мин
base64encodingdecodingurl-safeutf-8
Руководство по инструменту безопасности2026

Base64
без сложностей

Как Base64 превращает байты в текст

Стандартный и URL-safe · Дополнение · UTF-8

base64 · stdin
$ echo -n "Hi!" | base64
outSGkh
$ echo -n "SGkh" | base64 -d
outHi!
✓ 3 байта становятся 4 символами · = дополняет последнюю группу
Алфавит и дополнение
A-Z
от 0 до 25
a-z
от 26 до 51
0-9
от 52 до 61
+ или -
62
/ или _
63
=
Дополнение
Стандартный алфавитВариант URL-safeПоддержка UTF-8Это не шифрование

Что такое Base64 на самом деле

Base64 — это способ записать произвольные байты, используя всего 64 безопасных символа. В этом вся идея. Это не шифрование, не сжатие и не контрольная сумма. Он решает одну узкую задачу: у вас есть двоичные данные, а канал, по которому их нужно протащить, принимает только текст.

Таким каналом может быть тело письма, поле JSON, URL, HTTP-заголовок, YAML-конфиг или файл PEM. Отправьте сырые байты — и что-нибудь по дороге их испортит: нулевой байт обрежет строку, 0x0D перепишется при конвертации переводов строк, старший байт переосмыслится в другой кодировке. Base64 обходит всё это, используя только буквы, цифры и два знака пунктуации, и каждый из них спокойно переживает обращение с ним как с текстом.

Цена — размер: выход примерно на треть больше входа. Такова сделка, и она почти всегда оправдана, потому что альтернатива — данные, которые приходят испорченными.

Как три байта становятся четырьмя символами

Base64 работает группами по три байта. Три байта — это 24 бита, а 24 ровно делится на четыре группы по шесть. Каждая 6-битная группа индексирует алфавит из 64 символов, поэтому три байта на входе дают четыре символа на выходе.

Возьмём три байта слова Man:

M = 77 = 01001101, a = 97 = 01100001, n = 110 = 01101110

Склеиваем биты и заново режем по шесть:

010011 010110 000101 101110 → 19, 22, 5, 46 → T, W, F, u

Значит Man кодируется как TWFu. Четыре символа, заполнение не понадобилось, потому что три байта разделились ровно. Именно про это «разделились ровно» и следующий раздел.

Эти 64 символа

Индексы 0–25 — это A–Z, 26–51 — a–z, 52–61 — 0–9, а 62 и 63 — те самые два, из-за которых все беды. В стандартном Base64 это + и /.

Алфавит и почему их два

+ и / совершенно нормальны в теле письма и откровенно враждебны в URL. / — разделитель пути, а + в строке запроса означает пробел, так что значение Base64, вставленное в URL, может вернуться с изменёнными байтами и без единой ошибки где-либо.

Отсюда base64url — вариант, который сохраняет первые 62 символа и меняет два последних: - вместо + и _ вместо /. Именно эта кодировка используется в JSON Web Token — если вы когда-нибудь читали JWT вручную, вы читали base64url — и во всём остальном, что едет в URL или в имени файла.

В остальном варианты идентичны, и именно это делает их смешивание опасным. Строка, в которой нет ни +, ни /, ни -, ни _, корректна в обоих и декодируется одинаково. Строка, где они есть, декодируется в другие байты в зависимости от того, какой вариант предположил декодер, и обычно без всякой ошибки. Наш кодировщик и декодер Base64 сообщает, какой алфавит он распознал, именно по этой причине.

Заполнение и почему декодеры с ним не согласны

Вход редко кратен трём байтам. Один лишний байт даёт два символа, два лишних — три, а стандартный Base64 добивает группу до четырёх знаками =:

  • 3 байта → 4 символа, без заполнения
  • 2 байта → 3 символа + =
  • 1 байт → 2 символа + ==

Заполнение не несёт данных. Оно существует, чтобы декодер, читающий склеенный поток, знал, где кончается одно закодированное значение. Если вы декодируете одну отдельную строку, оно вам вовсе не нужно — поэтому base64url обычно его отбрасывает, да и = в URL всё равно неудобен.

Практическая сторона

Некоторые декодеры требуют заполнение и наотрез отвергают строку без него. Другие принимают оба вида. Это самая частая одиночная причина, по которой токен работает на одном языке и падает на другом с сухим «invalid base64». Лечится почти всегда возвратом заполнения: добавляйте =, пока длина не станет кратной четырём. Декодер, строгий к заполнению, не сломан — и кодировщик, который его опустил, тоже: они следуют разным половинам одной спецификации.

Base64 — не шифрование

Это заслуживает отдельного раздела, потому что ошибка очень распространённая и очень дорогая. У Base64 нет ключа. Он ничего не скрывает. Обратное преобразование — один вызов функции, доступный в любом языке и на любой странице вроде этой.

Канонический пример — HTTP Basic-аутентификация. Заголовок Authorization: Basic — это не более чем логин:пароль в Base64. Он выглядит непрозрачным, и в этом как раз опасность: тому, кто ни разу его не декодировал, он читается как «зашифрованный», тогда как на деле любой, кто видит запрос, прочитает учётные данные. Поэтому Basic допустим только по HTTPS: секретность даёт транспорт, кодирование не даёт никакой.

То же касается нагрузки JWT, блока Base64 в конфиге и ключа API, который кто-то «обфусцировал» перед коммитом. Если между злоумышленником и вашим секретом стоит только Base64, между злоумышленником и вашим секретом не стоит ничего. Наше руководство по разбору и отладке JSON Web Token подробнее разбирает, что это значит именно для токенов.

Где Base64 встречается на практике

Как только узнаёшь характерный вид, видишь его повсюду:

  • Вложения в письмах. MIME переносит двоичные данные так с начала девяностых, с переносом на 76 символов в строке.
  • data: URI. Небольшая картинка, встроенная в CSS или HTML как data:image/png;base64,…: один HTTP-запрос в обмен на треть лишних байт.
  • Файлы PEM. Сертификаты и ключи между метками -----BEGIN… — это Base64 от лежащего под ними DER, с переносом на 64 символа.
  • JWT. Заголовок и нагрузка — это JSON в base64url; подпись — base64url от сырых байт.
  • Basic-аутентификация и некоторые ключи API. Как выше, с той же оговоркой.
  • Двоичные данные внутри JSON. В JSON нет типа «байт», поэтому байты едут строкой Base64.

Почему в части Base64 есть переводы строк

MIME переносит на 76 символах, PEM — на 64, потому что форматы, в которых они живут, старше длинных строк. Эти переводы не часть данных, и декодер обязан их игнорировать. Большинство игнорирует; некоторые нет, и поэтому вставка PEM-тела с переносами в строгий декодер иногда не проходит, пока переносы не убрать.

Плата за размер и когда она важна

Четыре символа на три байта — это рост в 4/3, примерно 33 %, ещё до заполнения и переносов. Для разового значения в конфиге это неважно. Для чего-либо на горячем пути — важно.

Картинка в 10 КБ, встроенная как data: URI, стоит около 13,3 КБ HTML и, в отличие от настоящей картинки, не кешируется отдельно и не загружается отложенно. Токен, уезжающий с каждым вызовом API, тащит свои накладные расходы на каждом запросе. И сжатие вас не спасёт: вывод Base64 сжимается гораздо хуже исходных байт, потому что кодирование разрушает побайтовые закономерности, которые ищет компрессор. Сначала сжимайте, потом кодируйте — никогда не наоборот.

Кодировать текст — значит кодировать байты

Base64 кодирует байты. Понятия «символ» у него нет, поэтому «закодируй эту строку в Base64» — всегда сокращение от «преврати эту строку в байты, а потом закодируй эти байты». Промежуточный шаг и есть место, где всё ломается, потому что ему нужна кодировка символов, а спецификация её за вас не выбирает.

На практике ответ — UTF-8, и современные API берут её по умолчанию. Но если одна сторона кодирует текст в UTF-16 или Latin-1, а другая декодирует как UTF-8, Base64 будет совершенно корректным, а текст на выходе — кракозябрами. Признак: не-ASCII символы переживают плохо, а чистый ASCII — прекрасно, ведь ASCII является подмножеством UTF-8.

Проверка туда и обратно

Если вы не уверены, что конвейер корректно обращается с текстом, закодируйте строку с диакритикой и нелатинским символом, декодируйте обратно и сравните. Всё, что ломает José или эмодзи, теряет информацию где-то в преобразовании в байты, а не в самом Base64.

Когда декодирование не удаётся

Четыре диагноза покрывают почти все случаи:

  • «Недопустимый символ». Внутрь попало что-то вне алфавита — чаще всего случайный пробел, кавычка, скопированная вместе со строкой, или оставшийся впереди префикс data:image/png;base64,.
  • «Недопустимая длина». После удаления пробелов длина по модулю четыре равна 1, а корректный Base64 такого дать не может. По дороге потерялся символ.
  • Декодируется, но в мусор. Либо не совпали алфавиты (base64url раскодирован как стандартный или наоборот), либо не совпала кодировка текста, как описано выше.
  • Декодируется в байты, которые вовсе не текст. Это не ошибка. Множество Base64 хранит изображение, ключ или сериализованную структуру; хороший декодер покажет вам шестнадцатеричный вид, а не сделает вид, что результат — строка.

Пройти эти пункты по порядку — символы, длина, алфавит, кодировка — решает почти всё. А когда значение просто нигде не декодируется, самое вероятное объяснение самое скучное: оно было обрезано. В Base64 нет проверки целостности, поэтому строка, потерявшая хвост, выглядит ровно так же, как строка, у которой его никогда не было.

Связанные инструменты и руководства:

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

Для чего нужен Base64?⌄

Base64 проводит двоичные данные через каналы, принимающие только текст: вложения в письмах, data: URI в CSS и HTML, сертификаты и ключи в файлах PEM, двоичные поля внутри JSON и HTTP-заголовки вроде Authorization: Basic. Там, где сырые байты были бы испорчены или отвергнуты, Base64 доставит их без изменений.

Base64 — это шифрование или кодирование?⌄

Кодирование. Ключа нет и секретности нет: раскодировать — один вызов функции, который сделает любой браузер. Base64 делает байты пригодными к передаче, а не защищёнными от чтения. Никогда не используйте его для защиты пароля, токена или ключа API.

Почему моя строка Base64 заканчивается на = или ==?⌄

Это заполнение. Base64 работает группами по три байта, и если вход не делится ровно, последняя группа добивается до четырёх символов одним или двумя знаками =. Данных заполнение не несёт; base64url обычно его опускает, а некоторые строгие декодеры его требуют — это и есть обычная причина строки, которая декодируется на одном языке и не декодируется на другом.

Чем Base64 отличается от base64url?⌄

Двумя символами и заполнением. Стандартный Base64 использует + и / на двух последних позициях алфавита; base64url вместо них берёт - и _, потому что + и / имеют в URL особый смысл, и обычно отбрасывает заполнение =. JWT используют base64url. Декодирование одного как другого молча даёт другие байты.

Насколько Base64 увеличивает данные?⌄

Примерно на 33 %: каждые три байта превращаются в четыре символа, плюс заполнение и переносы строк. Если размер важен, сжимайте до кодирования, а не после: вывод Base64 сжимается плохо, потому что кодирование разрушает побайтовые закономерности, на которые опирается компрессор.

Об авторе
Основатель и CEO, BuildToolForge
Мы в X: @Buildtoolforge

Более 15 лет практического опыта в веб-разработке и безопасности. Специализация — практическая веб-безопасность: чтобы сайты были защищёнными, надёжными и легко диагностировались. BuildToolForge создан, чтобы такие проверки были бесплатными, приватными и понятными. Инструменты по возможности работают прямо в браузере, а всё, что вы вводите в инструмент, не сохраняется.

Как мы пишем руководства: Каждое руководство основано на практическом опыте, сверено с официальными стандартами и проверено нашими инструментами на реальных доменах. Мы обновляем руководства, когда меняются стандарты или инструменты. Нашли ошибку? Напишите нам: contact@buildtoolforge.com.

Последнее обновление: 2 ноября 2026 г.