Что такое Base64?
Base64 переписывает байты, используя шестьдесят четыре читаемых символа, чтобы данные выживали в канале, созданном для текста: тело письма, строка JSON, атрибут XML, URL. Каждые три байта становятся четырьмя символами, отсюда и название — в алфавите шестьдесят четыре символа, и каждый несёт ровно шесть бит.
Это транспортное кодирование, а не мера безопасности и не этап сжатия. Результат примерно на треть больше входа, и любой, у кого есть строка, может сразу превратить её обратно. Если нужно узнать, были ли данные изменены, для этого служит хеш (Генератор хешей); если нужно, чтобы данные оставались секретными, это шифрование. Base64 не делает ни того, ни другого.
Одно число, которое нужно запомнить: три входных байта становятся четырьмя выходными символами. Всё остальное на этой странице следует из этого. Четыре символа несут двадцать четыре бита, а двадцать четыре бита — ровно три байта, поэтому данные никогда не теряются и не выдумываются — кроме самого конца, где вход может не заполнить последнюю группу из трёх.
Пять алфавитов, которые может использовать эта страница
Первые две строки — стандарты, а последние три — соглашения, возникшие вокруг Unix. Все пять несут одинаковые шесть бит на символ и отличаются лишь тем, какие шестьдесят четыре символа несут эти биты, поэтому одни и те же байты становятся пятью разными строками. Внутри строки не сказано, каким алфавитом она создана, поэтому селектор алфавита по умолчанию стандартный, а флажок URL-безопасного варианта — это быстрый выбор второй строки.
Как страница выбирает кандидата: селектор — значение по умолчанию для обоих направлений. При декодировании панель справа также читает саму строку: - и _ могут появиться только в URL-безопасном алфавите, + или / — только в стандартном, а / или . около начала указывают на два алфавита Unix. Там перечислены все алфавиты, которые могут прочитать текущий вход, с причиной, почему каждый из них является кандидатом или нет.
Перенос строк: 76 и 64 символа
MIME требовал, чтобы Base64 помещался в письмо без чрезмерно длинных строк, и остановился на 76 символах в строке, разделённых CRLF. Файлы PEM, в которых хранятся сертификаты и ключи, используют 64. Переводы строк не являются частью данных: декодер удаляет их и склеивает строки обратно, прежде чем делать что-либо ещё, поэтому строка с переносами и без них декодируются в одинаковые байты. Каждая строка, кроме последней, содержит целое число групп по четыре символа, и именно это делает безопасным их склеивание.
Эта страница оставляет результат в одну строку, если вы не выберете ширину, а декодер принимает вход с переносами и без них. Переносы, которые пишет эта страница, — обычные символы перевода строки, которые способно вместить текстовое поле; тела писем MIME традиционно используют возврат каретки перед каждым переводом строки, и любой используемый декодер принимает оба варианта.
Заполнение и почему его можно убрать
Когда вход не кратен трём байтам, последняя группа из четырёх символов неполна, и один или два символа = её дополняют. Они вообще не несут данных: они лишь говорят, сколько из четырёх символов настоящие. Декодер может определить это по длине, поэтому URL-безопасный Base64 традиционно обходится без заполнения — = неудобен в URL или имени файла, а некоторые системы кодируют его процентами.
Флажок в строке параметров сохраняет заполнение при выборе URL-безопасного алфавита. Ничего больше не меняется; символы, которые несут данные, одинаковы в обоих случаях.
Распространённые недоразумения
- "Base64 скрывает данные." Нет. Это подстановка без ключа, и весь смысл в том, что любой читатель может её отменить. Заворачивание пароля или токена в Base64 ничего не меняет в том, кто может его прочитать.
- "Base64 сжимает." Наоборот: каждые три входных байта становятся четырьмя выходными символами, поэтому текст на треть больше данных, которые он несёт.
- "Переводы строк — часть значения." Это оформление. Добавление или удаление их никогда не меняет байты, которые выходят в результате.
- "URL-безопасный — это другое кодирование." Это то же кодирование с двумя поменянными символами:
+ становится -, а / становится _, поэтому строка может стоять в пути URL или значении запроса без экранирования. - "Строка, которая декодируется, обязана быть корректным Base64." Любая строка из символов алфавита является корректным Base64, потому что любая комбинация шестибитных значений — допустимая последовательность байтов. Строка оказывается неверной только на следующем шаге, когда эти байты проверяются по формату, который они должны были представлять.
- "Заполнение говорит, какой алфавит использован." Нет, и в большинстве случаев символы тоже не говорят: стандартный и URL-безопасный алфавиты совпадают в шестидесяти двух из шестидесяти четырёх символов, поэтому короткая строка часто читается одинаково в обоих.
Частые вопросы
Почему строка Base64 иногда заканчивается одним =, а иногда двумя? Один означает, что последняя группа несёт три настоящих символа, то есть два входных байта; два — что она несёт два символа, то есть один входной байт. Без = длина входа кратна трём.
Может ли Base64 представлять произвольные двоичные файлы? Да, и это его главное применение. Эта страница обрабатывает вход как текст UTF-8; отдельный инструмент Файл в Base64 читает сырые байты, когда нужно закодировать что-то не являющееся текстом.
Какой алфавит использовать в API? Тот, что документирует принимающая сторона. Если там написано «URL-безопасный», используйте его; если ничего не написано, а значение передаётся внутри URL, безопасный для URL вариант без заполнения — верный выбор.
Чувствителен ли результат к регистру? Полностью. a и A — разные значения, поэтому Base64 гораздо хуже переносит опечатку в символе, чем Base32 или Crockford Base32.