[СРАВНЕНИЕ] Base64, Base64URL и Base32
Три кодирования, один RFC. Здесь разбирается, чем они отличаются на самом деле — алфавит, накладные расходы, читаемость, чувствительность к регистру — и как выбрать подходящее для URL, имён файлов, писем, QR-кодов и кодов, произносимых вслух.
// БЫСТРАЯ ТАБЛИЦА СРАВНЕНИЯ
Base64 Base64URL Base32
(RFC 4648 §4) (RFC 4648 §5) (RFC 4648 §6)
────────────────────────────────────────────────────────────────
Alphabet size 64 64 32
Bits per char 6 6 5
Characters used A-Z a-z 0-9 A-Z a-z 0-9 A-Z 2-7
+ / - _ (+ = for pad)
Padding = (required) = (optional) = (optional)
Case-sensitive Yes Yes No (A = a)
Size overhead ~33% ~33% ~60%
URL-safe No Yes Yes
Filename-safe No Yes Yes
DNS-safe No Yes Yes
Human-readable Medium Medium High
Human-spoken Painful Painful Doable
QR-code friendly OK OK Excellent
(alphanumeric) (alphanumeric) (alphanumeric mode)
// ЧТО У НИХ ОБЩЕГО
Все три определены в RFC 4648 — едином документе 2006 года, объединившем семейство «двоично-в-текст кодирований base-N». У них общий базовый алгоритм: взять двоичный вход, перегруппировать биты в куски по log₂(размер алфавита), сопоставить каждому куску символ, дополнить паддингом до границы слова на выходе.
• Base64: куски по 6 бит → 4 символа на 3 байта (соотношение 4/3, ~33% сверху)
• Base32: куски по 5 бит → 8 символов на 5 байт (соотношение 8/5, ~60% сверху)
• Base16 (hex): куски по 4 бита → 2 символа на 1 байт (соотношение 2/1, 100% сверху)
Все три обратимы, детерминированы и сохраняют каждый байт входа. Это именно кодирования, а не сжатие и не шифрование. Любой, у кого есть строка, может её декодировать.
// КОГДА ВЫБИРАТЬ BASE64 (СТАНДАРТНЫЙ, §4)
Стандартный Base64 — дефолт для любого текстового канала, кроме URL. Тела MIME-писем, PEM-обёрнутые сертификаты, HTTP Basic Auth, S/MIME, XML-DSIG, data URI и большинство файловых форматов «бинарь-в-тексте» используют именно его. Символы + / = безопасны внутри атрибутов в кавычках, внутри заголовков писем (при переносе строк) и внутри строк XML/JSON.
Выбирайте стандартный Base64, когда нижестоящий потребитель — текстовый протокол, допускающий произвольный печатаемый ASCII, и особенно когда спецификация на уровне RFC прямо это требует (MIME: RFC 2045; PEM: RFC 7468; HTTP Basic Auth: RFC 7617; data URI: RFC 2397).
- > Вложения электронной почты (MIME base64 transfer encoding)
- > PEM-сертификаты, ключи, CRL (-----BEGIN ... -----)
- > Значение заголовка HTTP Basic Authentication
- > Data URI: data:image/png;base64,...
- > S/MIME и XML-ENC полезные нагрузки
- > Классические SOAP / XML-DSIG подписи
- > Любое двоичное поле в JSON-документе, которое затем не помещается в URL
// КОГДА ВЫБИРАТЬ BASE64URL (§5)
Как только ваш вывод Base64 касается URL, значения cookie, имени файла, DNS-метки или любого места, где + / = пришлось бы процентно кодировать, переходите на Base64URL. Он использует тот же 64-символьный алфавит с двумя заменами (+ → -, / → _) и обычно отбрасывает паддинг.
- > Токены JWT — заголовок, payload, подпись — всё это base64url (RFC 7515)
- > OAuth 2.0 PKCE code_challenge (RFC 7636)
- > Параметры state и nonce в OpenID Connect
- > Магические ссылки, инвайт-токены, токены сброса пароля
- > Значения cookie, которые могут попасть в URL
- > Имена файлов, производные от хэшей — избегайте / в именах файлов
- > DNS-метки, TXT-записи — дефисы допустимы, слэши нет
- > Ключи content-addressable хранилищ
- > Короткие URL-идентификаторы на основе случайных байт
// КОГДА ВЫБИРАТЬ BASE32 (§6)
Base32 использует всего 32 символа: заглавные A–Z и цифры 2–7. Это ~60% накладных расходов — гораздо хуже, чем у Base64, — но взамен вы получаете три очень специфических свойства, недостижимых для Base64.
Регистронезависимость. Алфавит состоит только из заглавных букв. Человек, читающий или вводящий строку, может игнорировать регистр; JBSWY3DP и jbswy3dp декодируются одинаково.
Нет визуально похожих символов. Цифры 0, 1, 8 и 9 исключены, потому что в типовых шрифтах они похожи на O, I, B и g. Используются только 2–7. Это радикально повышает надёжность ручного набора с печатной страницы или экрана телефона.
Совместимость с alphanumeric-режимом QR-кодов. У QR-кодов есть специальный «alphanumeric»-режим, который кодирует 5,5 бит на символ, используя подмножество ASCII. Base32 целиком укладывается в это подмножество (плюс паддинг), поэтому QR с Base32 получается заметно меньше, чем QR с Base64.
- > Секреты TOTP / HOTP — Google Authenticator, 1Password, Authy используют Base32
- > Tor .onion-адреса v3 — 56-символьные Base32-представления ключей ed25519
- > BitTorrent info-hash в magnet-ссылках
- > Коды местоположения типа geohash, которыми делятся люди
- > Лицензионные ключи и серийные номера продуктов
- > Печатаемые восстановительные коды (резервные 2FA-коды, мнемоники кошельков)
- > Передача вроде DTMF через голосовые каналы
- > Системы, которым нужно регистронезависимое хранение (DNS-метки)
// НАКЛАДНЫЕ РАСХОДЫ — КОНКРЕТНЫЙ ПРИМЕР
// Input: a 32-byte SHA-256 hash
// Raw: 0x89abcdef… (32 bytes, binary — can't put in text)
// Hex (Base16): 40b2e2… (64 chars, 100% overhead)
// Base32: 5ENM4H2TQWMZ3O4OQBJAFY5Q (56 chars, 75% overhead)
// Base64: ia+N7/eZtRsPj5TqFoqUlD… (44 chars, 37% overhead)
// Base64URL: ia-N7_eZtRsPj5TqFoqUlD… (43 chars, 34% overhead, no padding)
// Input: a 16-byte UUID
// Hex: e7a6c1d0-4b7d-4c6c-8e2f-9f1a3e4b5c6d (36 chars incl. dashes)
// Base32: 5WTMDUCLPVGGZDRPTF… (26 chars)
// Base64: 56bB0Et9TGyOL58aPktcbQ== (24 chars)
// Base64URL: 56bB0Et9TGyOL58aPktcbQ (22 chars, no padding)
// БЕНЧМАРК ПО УДОБОЧИТАЕМОСТИ
Именно здесь Base32 блистает. Попробуйте прочитать вслух:
• a+b/c1D2e3F/+g= — Base64. «маленькая-a, плюс, маленькая-b, слэш-вперёд, маленькая-c, один, большая-D, два, маленькая-e, три, большая-F, слэш-вперёд, плюс, маленькая-g, равно». Один регистр уже провоцирует ошибки ввода.
• JBSWY3DPEHPK3PXP — Base32. «J-B-S-W-Y, три, D-P-E-H-P-K, три, P-X-P». Регистр не важен. Нет путаницы 0/O или 1/l. Такое можно надиктовать по телефону с высокой надёжностью.
Именно поэтому TOTP использует Base32: кому-то приходится вводить секрет в приложение-аутентификатор с резервного экрана QR-кода. Регистрозависимость Base64 породила бы бесконечный поток обращений в поддержку.
// СРАВНЕНИЕ ПО РАЗМЕРУ QR-КОДА
У QR-кодов есть специальный «alphanumeric mode», упаковывающий 5,5 бит на символ из подмножества в 45 знаков: 0–9, A–Z (только верхний регистр), пробел и $ % * + - . / :. Всё, что выходит за пределы этого подмножества, переводит QR-код в «byte mode», где на символ уходит 8 бит — и QR заметно разрастается.
Base32 полностью укладывается в alphanumeric-подмножество. Base64 — нет: строчные буквы и +/= вынуждают переход в byte mode (формально +/ входят в alphanumeric, но любые строчные буквы уже переводят в byte mode). В итоге одна и та же полезная нагрузка помещается в меньший QR, если закодирована в Base32 — часто это разница между читабельным 21×21 и перегруженным 33×33 QR-кодом.
// ПОДВОДНЫЕ КАМНИ ДЕКОДИРОВАНИЯ
-
>
Регистр — декодеры Base64 отвергают вход с неправильным регистром (
SGVsbG8=≠sgvSbg8=). Декодеры Base32 обычно нормализуют в верхний регистр перед поиском, поэтому терпимы к любому. -
>
Паддинг — стандартный Base64 требует паддинг
=; JWT/base64url запрещает его; в Base32 он опционален (RFC 4648 §6). Всегда проверяйте, что ожидает ваш декодер. -
>
Пробельные символы — MIME Base64 переносится по 76 колонкам с CR-LF. Часть декодеров терпит пробелы, часть — нет. Срезайте их перед
atob()и его аналогами. -
>
Коллизии алфавитов — подача Base64 в Base32-декодер (или наоборот) поначалу может казаться рабочей —
A,B,Cвалидны в обоих — а затем тихо рушится на+или=. - > Crockford Base32 — это не-RFC-вариант, используемый в ID Stripe и некоторых блокчейнах. У него другой алфавит (без I, L, O, U) и поддержка контрольных знаков. Не путайте с RFC 4648 Base32.
- > Base32 Extended Hex (RFC 4648 §7) — альтернативный алфавит Base32, сохраняющий лексикографический порядок сортировки. Используется в DNSSEC NSEC3. Его легко перепутать со стандартным Base32.
// БЛОК-СХЕМА ПРИНЯТИЯ РЕШЕНИЯ
Does the output go into a URL, cookie, filename, DNS, JWT, or OAuth flow?
│
├─ Yes → Does a human need to type or speak the string?
│ │
│ ├─ Yes → Base32 (uppercase, no ambiguous chars)
│ │ e.g., TOTP seeds, recovery codes
│ │
│ └─ No → Base64URL (more compact, URL-safe)
│ e.g., JWT, short tokens, hash-named files
│
└─ No → Does the output go into a QR code that must stay tiny?
│
├─ Yes → Base32 (fits in QR alphanumeric mode)
│
└─ No → Standard Base64
e.g., email MIME, PEM, HTTP Basic, data URI
// ПОЧЕМУ НЕ BASE16 (HEX)?
Шестнадцатеричный (в RFC 4648 §8 именно это и называется Base16) — универсальный запасной вариант. Каждая shell-утилита, отладчик и протокол его понимают. Он регистронезависим, элементарно читается человеком и тривиально реализуется. Но он удваивает размер полезной нагрузки (100% сверху), поэтому применяется только для маленьких идентификаторов фиксированной длины: SHA-256-хэшей (64 hex-символа = 32 байта), UUID (32 hex-символа = 16 байт), MAC-адресов, адресов памяти в отладчиках.
Для всего, что больше нескольких десятков байт, накладные расходы hex в сети по-настоящему болезненны. Base64 на 50% меньше hex, Base32 — на 25%. Именно поэтому Base64 победил в почте и веб-встраиваниях, а hex остался в отладке и отображении хэшей.
// А КАК НАСЧЁТ BASE58 / BASE62 / BASE85?
Не-RFC-кодирования base-N существуют под конкретные ниши:
• Base58 — адреса Bitcoin, ID фото Flickr. Исключает четыре неоднозначных символа (0, O, I, l) и +/ для удобства ручного набора. ~37% сверху.
• Base62 — сокращатели URL, ID-снежинки Twitter. Использует только буквы и цифры (без спецзнаков), безопасен в URL без экранирования. ~34% сверху.
• Base85 / Ascii85 / Z85 — PostScript, PDF, старые кадры ZeroMQ. ~25% сверху (плотнее, чем Base64), но с хитрыми символами, провоцирующими ад экранирования в XML/JSON.
Они интересны, но не стандартизованы в RFC 4648. Если вы делаете открытый протокол, Base64 или Base64URL почти всегда безопаснее по умолчанию — стандартная библиотека любого языка уже их поддерживает. Выберете Base58 — будете тащить зависимость каждому потребителю.
// ПОПРОБУЙТЕ ИХ БОК О БОК
• Кодировщик Base64 — стандартный алфавит с переключателем URL-safe
• Кодировщик Base64URL — URL-safe со снятым паддингом
• Кодировщик Base32 — алфавит из RFC 4648 §6
• Кодировщик Base16 (hex) — для сравнения
• Кодировщик Base58 — удобный для человека алфавит в стиле Bitcoin
Дополнительное чтение:
• Что такое Base64 и как он работает?
• URL-safe против стандартного Base64 — подробная история
• Base64 для UTF-8 и Unicode