Почему мы используем Base64?

Википедия говорит

схемы кодирования Base64 обычно используются, когда есть необходимость кодировать двоичные данные, которые должны храниться и передаваться через носители, предназначенные для обработки текстовых данных. Это необходимо для того, чтобы данные оставались нетронутыми без изменений во время транспортировки.

но разве это не то, что данные всегда хранятся / передаются в двоичном формате, потому что память, что наши машины хранят двоичный файл, и это просто зависит от того, как вы это толкуете? Итак, кодируете ли вы битовый шаблон 010011010110000101101110 as Man в ASCII или as TWFu в Base64 вы в конечном итоге собираетесь сохранить тот же битовый шаблон.

если конечная кодировка в терминах нулей и единиц и каждая машина и носитель могут иметь дело с ними, как это имеет значение, если данные представлены как ASCII или Base64?

что означает "носители, предназначенные для обработки текстовых данных"? Они могут иметь дело с бинарными они могут справиться с чем угодно.


спасибо всем, думаю, теперь я понимаю.

когда мы отправляем данные, мы не можем быть уверены, что данные будут интерпретироваться в том же формате, как мы предполагали. Итак, мы отправляем данные, закодированные в некотором формате (например, Base64), который обе стороны понимают. Таким образом, даже если отправитель и получатель интерпретируют одни и те же вещи по-разному, но поскольку они согласны с кодированным форматом, данные не будут интерпретироваться незаслуженно.

С пример Марка Байерса

если я хочу послать

Hello
world!

один из способов-отправить его в ASCII, как

72 101 108 108 111 10 119 111 114 108 100 33

но байт 10 может быть неправильно интерпретирован как новая строка на другом конце. Итак, мы используем подмножество ASCII для кодирования его следующим образом

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

который за счет большего количества данных, передаваемых за тот же объем информации, гарантирует, что получатель может декодировать данные по назначению, даже если приемник имеет разные интерпретации для остальной части набора символов.

12 ответов


ваша первая ошибка-думать, что кодировка ASCII и кодировка Base64 взаимозаменяемы. Это не так. Они используются для различных целей.

  • когда вы кодируете текст в ASCII, вы начинаете с текстовой строки и преобразуете ее в последовательность байтов.
  • когда вы кодируете данные в Base64, вы начинаете с последовательности байтов и преобразуете ее в текстовую строку.

чтобы понять, почему Base64 был необходим в первую очередь нам нужно немного история вычислений.


компьютеры общаются в двоичных-0s и 1s - но люди обычно хотят общаться с более богатыми данными форм, таких как текст или изображения. Для передачи этих данных между компьютерами их сначала нужно закодировать в 0 и 1, отправить, а затем снова декодировать. Взять в качестве примера текст - существует множество различных способов выполнения этой кодировки. Было бы намного проще, если бы мы все могли договориться об одной кодировке, но, к сожалению, это не случай.

первоначально было создано много разных кодировок (например,Бодо код), который использовал другое количество бит на символ, пока в конечном итоге ASCII не стал стандартом с 7 битами на символ. Однако большинство компьютеров хранят двоичные данные в байтах, состоящих из 8 бит каждый так ASCII не подходит для передачи данных такого типа. Некоторые системы даже стерли бы самый важный бит. Furthermore разница в кодировках конца линии через системы означают, что символы ASCII 10 и 13 также иногда изменялись.

для решения этих проблем в base64 кодировка была введена. Это позволяет кодировать арибтрарные байты в байты, которые, как известно, безопасны для отправки без повреждения (ASCII буквенно-цифровые символы и несколько символов). Недостатком является то, что кодирование сообщения с помощью Base64 увеличивает его длину-каждые 3 байта данных кодируются до 4 символов ASCII.

в отправить текст надежно вы можете первый кодировать в байты, используя текстовую кодировку по вашему выбору (например, UTF-8), а затем после Base64 кодирует полученные двоичные данные в текстовую строку, которая безопасна для отправки в кодировке ASCII. Получателю придется отменить этот процесс, чтобы восстановить исходное сообщение. Это, конечно, требует, чтобы получатель знал, какие кодировки были использованы, и эта информация часто должна быть отправлена отдельно.

исторически он использовался для кодирования двоичных данных в сообщениях электронной почты, где почтовый сервер может изменять окончания строк. Более современным примером является использование кодировки Base64 для вставить данные изображения непосредственно в исходный код HTML. Здесь необходимо кодировать данные, чтобы такие символы, как " ", не интерпретировались как теги.


вот пример:

Я хочу, чтобы отправить текстовое сообщение с двумя линии

Hello
world!

если я отправлю его как ASCII (или UTF-8), он будет выглядеть так:

72 101 108 108 111 10 119 111 114 108 100 33

байт 10 поврежден в некоторых системах, поэтому мы можем использовать 64 для кодирования этих байтов как строку Base64:

SGVsbG8sCndvcmxkIQ==

который при кодировании с помощью ASCII выглядит следующим образом:

83 71 86 115 98 71 56 115 67 110 100 118 99 109 120 107 73 61 61

все байты здесь известны безопасные байты, поэтому очень мало шансов, что какая-либо система повредит это сообщение. Я могу отправить это вместо моего первоначального сообщения и позволить receiver обратный процесс для восстановления исходного сообщения.


кодирование двоичных данных в XML

Предположим, вы хотите встроить пару изображений в XML-документ. Изображения являются двоичными данными, а XML-документ-текстом. Но XML не может обрабатывать встроенные двоичные данные. Так как же вы это делаете?

один из вариантов-кодировать изображения в base64, превращая двоичные данные в текст, который может обрабатывать XML.

вместо:

<images>
  <image name="Sally">{binary gibberish that breaks XML parsers}</image>
  <image name="Bobby">{binary gibberish that breaks XML parsers}</image>
</images>

вы:

<images>
  <image name="Sally" encoding="base64">j23894uaiAJSD3234kljasjkSD...</image>
  <image name="Bobby" encoding="base64">Ja3k23JKasil3452AsdfjlksKsasKD...</image>
</images>

и XML parser сможет правильно проанализировать XML-документ и извлечь данные изображения.


Почему бы не посмотреть на RFC, который в настоящее время определяет Base64?

базовое кодирование данных используется в многие ситуации для хранения или передачи
данные в средах, которые, возможно, для причины наследия, ограничиваются Данные US-ASCII [1].Базовая кодировка также использоваться в новых приложениях которые не имеют прежних ограничений, просто потому, что это делает возможным управление объектами с помощью текста редколлегия.

в прошлом, разные приложения имеют различные требования и таким образом иногда реализуется база кодировки в немного разных пути. Сегодня, спецификации протокола иногда используйте базовые кодировки в вообще, и "в base64" в частности, без точного описания или ссылка. Многоцелевая Интернет-Почта Часто используются расширения (MIME) [4] в качестве ссылки для base64 без рассмотрение последствий для линии обтекания или алфавит письмена. Цель этого спецификация установить общее алфавит и кодирование рассмотрения. Это надеюсь уменьшить неоднозначность в других документы, ведущие к лучшему совместимость.

Base64 изначально был разработан как способ, позволяющий подключать двоичные данные к электронной почте как часть универсальных расширений интернет-почты.


носитель, предназначенный для текстовых данных, конечно, также является двоичным, но текстовые носители часто используют определенные двоичные значения для управляющих символов. Кроме того, текстовые носители могут отклонять определенные двоичные значения как нетекстовые.

кодировка Base64 кодирует двоичные данные как значения, которые могут быть интерпретированы только как текст в текстовых носителях и свободны от каких-либо специальных символов и/или управляющих символов, так что данные будут сохранены на текстовых носителях.


это больше, чем СМИ проверка кодировка строк, поэтому мы хотим убедиться, что данные приемлемы для приложения обработки (и не содержат двоичную последовательность, представляющую EOL, например)

представьте, что вы хотите отправить двоичные данные по электронной почте с кодировкой UTF-8 - письмо может отображаться неправильно, если поток единиц и нулей создает последовательность который не является допустимым Unicode в кодировке UTF-8.

тот же тип что происходит в URL-адресах, когда мы хотим кодировать символы, недопустимые для URL-адреса в самом URL-адресе:

http://www.foo.com/hello мой друг ->http://www.foo.com/hello%20my%20friend

это потому, что мы хотим отправить пространство над системой, которая будет думать, что пространство воняет.

все, что мы делаем, это обеспечение отображения от 1 до 1 между известной хорошей, приемлемой и безвредной последовательностью битов к другой буквальной последовательности битов, и что приложение обработки не отличает кодировка.

в вашем примере man может быть допустимым ASCII в первой форме; но часто вы можете передавать значения, которые являются случайными двоичными (т. е. отправка изображения по электронной почте):

MIME-версия: 1.0
Содержание-Описание: "Base64 кодирует a.gif"
Тип контента: изображение / gif; name="a.gif"
Контент-Передача-Кодирование: В base64
Content-Disposition: вложение; filename="a.gif"

здесь мы видим, что GIF-изображение кодируется в base64 как кусок электронной почты. Почтовый клиент читает заголовки и декодирует их. Из-за кодировки мы можем быть уверены, что GIF не содержит ничего, что может быть интерпретировано как протокол, и мы избегаем вставки данных, которые SMTP или POP могут найти значимыми.


один пример того, когда я нашел это удобным, был при попытке вставить двоичные данные в XML. Некоторые двоичные данные неправильно интерпретировались анализатором SAX, потому что эти данные могли быть буквально чем угодно, включая специальные символы XML. Base64 кодирование данных на передающей стороне и декодирование его на приемной стороне исправили эту проблему.


большинство компьютеров хранят данные в 8-битном двоичном формате, но это не является требованием. Некоторые машины и средства передачи могут обрабатывать только 7 бит (или, возможно, даже меньше) одновременно. Такой носитель будет интерпретировать поток в кратных 7 битах, поэтому, если вы отправите 8-битные данные, вы не получите то, что ожидаете на другой стороне. Base-64 - это только один способ решить эту проблему: вы кодируете вход в 6-битный формат, отправляете его на свой носитель и декодируете его обратно в 8-битный формат на приемный конец.


Base64 вместо экранирования специальных символов

я приведу вам совсем другой, но реальный пример: я пишу код javascript для запуска в браузере. HTML-теги имеют значения ID, но есть ограничения на то, какие символы допустимы в ID.

но я хочу, чтобы мой ID без потерь ссылался на файлы в моей файловой системе. Файлы на самом деле могут иметь все виды странных и замечательных персонажей в них от восклицательных знаков, акцентированных символов, Тильды, даже emoji! Я не могу ... это:

<div id="/path/to/my_strangely_named_file!@().jpg">
    <img src="http://myserver.com/path/to/my_strangely_named_file!@().jpg">
    Here's a pic I took in Moscow.
</div>

предположим, я хочу запустить такой код:

# ERROR
document.getElementById("/path/to/my_strangely_named_file!@().jpg");

Я думаю, что этот код потерпит неудачу при выполнении.

С Base64 я могу ссылаться на что-то сложное, не беспокоясь о том, какой язык позволяет какие специальные символы и которые нужно избежать:

document.getElementById("18GerPD8fY4iTbNpC9hHNXNHyrDMampPLA");

в отличие от использования MD5 или какой-либо другой функции хэширования, вы можете изменить кодировку, чтобы узнать, какие именно данные были действительно полезны.

желаю Я знал о Base64 лет назад. Я бы не стала рвать на себе волосы с помощью"encodeURIComponent и str.replace(‘\n’,’\n’)


что значит "СМИ, что предназначены для работы с текстовыми данными"?

что эти протоколы были разработаны для обработки текста (часто только английский язык text) вместо двоичных данных (например .png и .jpg изображения).

они могут иметь дело с binary => они могут справиться с чем угодно.

но обратное неверно. Протокол, предназначенный для представления текста, может неправильно обрабатывать двоичные данные, которые содержать:

  • байты 0x0A и 0x0D, используемые для окончаний строк, которые отличаются платформой.
  • другие управляющие символы, такие как 0x00 (null = C string terminator), 0x03 (конец текста), 0x04 (конец передачи) или 0x1A (DOS end-of-file), которые могут преждевременно сигнализировать о конце данных.
  • байт выше 0x7F (если протокол, который был разработан для ASCII).
  • байтовые последовательности, которые являются недопустимыми UTF-8.

Так что вы не можете просто отправка двоичных данных по текстовому протоколу. Вы ограничены байтами, которые представляют собой неконтролируемые символы ASCII без пробела, из которых 94. Причиной базовая 64 было выбрано, что это быстрее работать с силы два, и 64-крупнейший один, который работает.

один вопрос. Как это системы по-прежнему не согласны с общим метод кодирования, такой как so common UTF-8?

в Интернете, по крайней мере, они в основном имеют. большинство сайтов используют UTF-8.

проблема на Западе в том, что есть много старого программного обеспечения, которое ass-u-me-s, что 1 байт = 1 символ и не может работать с UTF-8.

проблема на Востоке заключается в их привязанности к кодировкам, таким как GB2312 и Shift_JIS.

и тот факт, что Microsoft, похоже, все еще не оправилась, выбрав неправильную кодировку UTF. Если вы хотите использовать API Windows или библиотеку времени выполнения Microsoft C, вы ограничено UTF-16 или кодировкой "ANSI" локали. Это делает болезненным использование UTF-8, потому что вам нужно все время конвертировать.


в дополнение к другим (несколько длинным) ответам: даже игнорируя старые системы, поддерживающие только 7-битный ASCII, основные проблемы с поставкой двоичных данных в текстовом режиме:

  • новые строки обычно преобразуются в текстовом режиме.
  • нужно быть осторожным, чтобы не рассматривать нулевой байт как конец текстовой строки, что слишком легко сделать в любой программе С C lineage.

что означает "носители, предназначенные для обработки текстовых данных"?

в те дни, когда ASCII правил миром, имея дело с не-ASCII-значениями, была головной болью. Люди прыгали через всевозможные обручи, чтобы получить их по проводу, не теряя информации.


Почему / как мы используем кодировку Base64?

Base64 - одна из схем кодирования двоичного текста с эффективностью 75%. Он используется так, что типичные двоичные данные (например, изображения) могут быть безопасно отправлены по устаревшим "не 8-битным чистым" каналам. В более ранних почтовых сетях (до начала 1990-х годов) большинство сообщений электронной почты были обычным текстом в 7-битном наборе символов US-ASCII. Поэтому многие ранние стандарты протокола comm были разработаны для работы над "7-битными" комм-ссылками "не 8-битными". Эффективность схемы соотношение между количеством битов на входе и количеством битов на закодированном выходе. Шестнадцатеричная (Base16) также является одной из схем кодирования двоичного текста с эффективностью 50%.

Шаги Кодирования Base64 (Упрощенные):

  1. двоичные данные расположены в непрерывных кусках по 24 бита (3 байта) каждый.
  2. каждый 24 битный кусок сгруппирован в четыре части по 6 бит каждый.
  3. каждая 6-битная группа преобразуется в соответствующую Base64 значения символов, т. е. кодировка Base64 преобразует три октета в четыре закодированных символа. Отношение выходных байтов к входным составляет 4: 3 (33% накладных расходов).
  4. интересно, что одни и те же символы будут кодироваться по-разному в зависимости от их положения в группе из трех октетов, которая кодируется для получения четырех символов.
  5. получателю придется отменить этот процесс, чтобы восстановить исходное сообщение.