Utilo

Base64 объясняется: как это работает, когда использовать и когда нет

Ясное объяснение кодирования Base64: алгоритм, наполнение, безопасность URL-адресов Base64, URL-адреса данных, размер накладных расходов, Unicode ловушки и ошибочные представления о безопасности.

· 5 мин чтения

Base64 появляется в электронных приложениях, JSON Web Tokens, URL-адресах данных, секретах Kubernetes, HTTP Basic аутентификации и бесчисленных API, которые должны перемещать двоичные данные через текстовые каналы. Это просто, как только вы видите, как это работает, но это часто используется неправильно, особенно, как если бы это было шифрование. В этой статье объясняется алгоритм шаг за шагом, распространенные варианты и практическое руководство о том, когда Base64 является правильным инструментом.

Проблема Base64 решается

Многие системы были разработаны для передачи текста, а не произвольных байтов. Электронная почта (SMTP) исторически поддерживала только 7-разрядный ASCII. Строки JSON не могут содержать сырой двоичный код. URL-адреса и заголовки HTTP имеют ограниченные наборы символов. Если вы поместите сырые байты изображения в любой из них, некоторые байты будут интерпретироваться как контрольные символы, окончания строк или делимитаторы, и данные будут повреждены.

Base64 отображает произвольные байты на 64 безопасных, печатаемых символов: A–Z, a–z, 0–9, + и /. Любая система, которая может переносить простой текст, может переносить данные целыми.

Как работает кодирование

Base64 обрабатывает ввод в группах по 3 байта (24 бита) и выводит 4 символа по 6 бит каждый. Поскольку 2 ^ 6 = 64, каждое 6-битное значение выбирает один символ из алфавита.

Возьмем слово Man:

  1. Байты ASCII: M = 77, a = 97, n = 110.
  2. В бинарном: 01001101 01100001 01101110.
  3. Разделяем на четыре группы: 010011 010110 000101 101110.
  4. В виде чисел: 19, 22, 5, 46.
  5. Посмотрите по алфавиту: T, W, F, u.

Так что Man становится TWFu. Декодирование обращает процесс вспять.

Покрытие =

Когда длина ввода не является кратным 3, последняя группа неполная. База-64 загружает:

  • 1 оставшийся байт производит 2 символа плюс ==.
  • 2 оставшихся байта производят 3 символа плюс =.

Ma кодирует TWE= и M до TQ==. Покрытие делает выходной длину кратным четырем, что требуется некоторым декодерам. Другие, особенно URL-безопасные реализации, пропускают его, потому что длина уже подразумевает, сколько байтов отсутствует.

Размер накладных

Каждые 3 байта превращаются в 4 символа, поэтому вывод Base64 примерно на 33% больше, чем ввод, плюс подкладка и иногда перерывы в строке (MIME email wraps lines at 76 characters). 1 МБ изображения становится примерно 1,37 МБ текста. Это имеет значение, когда вы встраиваете большие файлы в JSON или HTML.

URL-безопасность Base64

Стандартный алфавит включает + и /, которые имеют специальные значения в URL-адресах, и =, который используется в строках запросов. Base64URL, определенный в RFC 4648, заменяет + на - и / на _, и обычно упускает подкладку. JWT, многие токены API и веб-ключи push используют этот вариант см. как JWT работает для примера.

Стандартный декодер не работает на - и _, и наоборот, что является распространенным источником ошибок "недействительных символов". Толерантный [Base64 декодер] ((/tools/base64) принимает оба алфавита и восстанавливает отсутствующую подкладку автоматически.

Текст, байты и Unicode

Base64 кодирует байты, а не символы. Для кодирования текста сначала необходимо преобразовать его в байты с кодировкой символов, почти всегда UTF-8. Вот где браузеры обманывают людей: встроенный в JavaScript btoa() принимает только символы в диапазоне Latin-1, поэтому btoa("héllo") работает случайно, а btoa("你好") бросает ошибку.

Правильный подход в современном JavaScript:

const bytes = new TextEncoder().encode("你好 👋");
const b64 = btoa(String.fromCharCode(...bytes));
const back = new TextDecoder().decode(Uint8Array.from(atob(b64), c => c.charCodeAt(0)));

Другие языки делают это ясным: Python base64.b64encode принимает байты, так что вы пишете base64.b64encode("你好".encode("utf-8")).

URL-адреса данных

URL данных встраивает файл непосредственно в HTML или CSS:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA..." alt="">

Это сохраняет HTTP-запрос, который был ценен в эпоху HTTP/1.1. Сегодня, при мультиплексировании HTTP/2, компромиссы обычно выступают в пользу отдельных файлов:

  • URL-адреса данных не могут быть кэшированы самостоятельно; они повторно загружаются с каждой страницей или таблицей стилей, которая их содержит.
  • Они надувают HTML и CSS, что блокирует рендеринг до загрузки и анализа.
  • Применяется 33% накладные расходы, хотя gzip восстанавливает часть из них.

Используйте URL-адреса данных для крошечных активов небольших значков менее 1 2 КБ, изображений, хранящих место, или экспорта одного файла HTML. Для чего-то большего, используйте обычный файл и вместо этого сжайте его.

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

Это самый важный момент. У Base64 нет ключа. Каждый может расшифровать его мгновенно, и многие инструменты делают это автоматически. Тем не менее, часто встречаются:

  • API-ключи "скрыты" в Base64 в коде фронта.
  • Пароли хранятся в базах данных или конфигурационных файлах с кодировкой Base64.
  • Секреты Kubernetes считаются защищенными, потому что их значения - Base64.

Kubernetes кодирует секретные значения в Base64 исключительно для того, чтобы бинарные данные помещались в YAML; защита происходит от контроля доступа и шифрования в состоянии покоя, которые должны быть настроены отдельно. Если данные должны быть конфиденциальными, шифруйте их с помощью реального алгоритма, такого как AES-GCM, и если вам нужно проверить пароли, используйте хэширующую функцию пароля не Base64 и не простой хэш, такой как MD5 ([почему бы и нет] ((/blog/md5-vs-sha256)).

Распространенные варианты использования

  • Основная аутентификация HTTP отправляет Authorization: Basic base64(user:password). Кодирование исключает только проблемы со специальными символами; учетные данные защищены исключительно HTTPS.
  • Приложения к электронной почте используют MIME Base64 с перерывами линий каждые 76 символов.
  • ** Встраивание двоичного файла в JSON**, например, небольшого изображения подписи или криптографического ключа, является законным использованием. Для больших файлов загрузить отдельно и ссылаться на них по URL.
  • Хранение бинарных данных в текстовой конфигурации, например, сертификаты TLS в переменных среды.

Устранение ошибок декодирования

  • Недействительный символ: Вы, вероятно, декодируете Base64URL стандартным декодером, или строка содержит пробелы или перерывы линий.
  • Неправильная упаковка: добавить = до тех пор, пока длина не станет кратной четырех.
  • Склонение текста после расшифровки: оригинал был закодирован из другого набора символов, или данные являются двоичными, а не текстовыми.
  • Выход выглядит как Base64 снова: данные были закодированы дважды; декодировать еще раз.

Соответствующие кодировки

  • Base32 использует 32 символа (AZ и 27), не чувствителен к большим и малым и используется в секретах TOTP для приложений аутентификации. Общие расходы - 60%.
  • Гексадецимальный (база 16) использует два символа на байт 100% накладные , но легко читается и распространен для хэшей.
  • Base58 удаляет похожие символы и используется в биткойн-адресах.
  • %-кодирование спасает только небезопасные символы в URL-адресах.

Итоги

Base64 преобразует байты в текстовый алфавит из 64 символов, по 3 байта за раз, за счет дополнительного размера примерно на 33%. Используйте его для переноса двоичных данных через текстовые каналы; используйте вариант URL-безопасность в URL и токены; всегда конвертировать текст в UTF-8 байтов сначала. Никогда не используйте его для защиты секретов это шифрование, а не замок.

Эта страница переведена с английского автоматически. Если вы заметили ошибку, сообщите нам.

Похожие руководства