В компьютерном программировании Base64 — это группа схем кодирования двоичных данных в текст , которая преобразует двоичные данные в последовательность печатных символов, ограниченную набором из 64 уникальных символов. Более конкретно, исходные двоичные данные берутся по 6 бит за раз, затем эта группа из 6 бит сопоставляется с одним из 64 уникальных символов.
Как и все схемы кодирования двоичного текста, Base64 предназначен для передачи данных, хранящихся в двоичных форматах, по каналам, которые надежно поддерживают только текстовый контент. Base64 особенно распространен в World Wide Web [1] , где одним из его применений является возможность встраивать файлы изображений или другие двоичные активы в текстовые активы, такие как файлы HTML и CSS . [2]
Base64 также широко используется для отправки вложений электронной почты , поскольку SMTP – в своей первоначальной форме – был разработан для передачи только 7-битных символов ASCII. Кодирование вложения в Base64 перед отправкой и его последующее декодирование при получении гарантирует, что старые серверы SMTP не будут мешать вложению.
Кодирование Base64 приводит к накладным расходам в размере 33–37% относительно размера исходных двоичных данных (33% за счет самого кодирования; до 4% больше за счет вставленных переносов строк).
Конкретный набор из 64 символов, выбранный для представления 64-значных значений для базы, различается в зависимости от реализации. Общая стратегия заключается в выборе 64 символов, которые являются общими для большинства кодировок и которые также являются печатаемыми. Такая комбинация делает маловероятным изменение данных при передаче через информационные системы, такие как электронная почта, которые традиционно не были 8-битными чистыми . [3] Например, реализация Base64 MIME использует –A
, Z
– a
, z
и 0
– 9
для первых 62 значений. Другие вариации разделяют это свойство, но отличаются символами, выбранными для последних двух значений; примером является UTF-7 .
Самые ранние примеры этого типа кодирования были созданы для коммутируемой связи между системами, работающими под управлением одной и той же ОС — например, uuencode для UNIX и BinHex для TRS-80 (позже адаптированный для Macintosh ) — и поэтому могли делать больше предположений о том, какие символы безопасны для использования. Например, uuencode использует заглавные буквы, цифры и многие знаки препинания, но не строчные. [4] [5] [6] [3]
Это алфавит Base64, определенный в RFC 4648 §4. См. также § Сводная таблица вариантов.
В примере ниже для простоты используется текст ASCII , но это не типичный случай использования, поскольку его уже можно безопасно передавать через все системы, которые могут обрабатывать Base64. Более типичное использование — кодирование двоичных данных (например, изображения); полученные данные Base64 будут содержать только 64 различных символа ASCII, все из которых можно надежно передавать через системы, которые могут повредить исходные байты.
Вот известная идиома из распределенных вычислений :
Много рук делают работу легкой.
Когда кавычка (без конечных пробелов) кодируется в Base64, она представляется как последовательность байтов из 8-битных символов ASCII , закодированных в схеме Base64 MIME следующим образом (символы новой строки и пробелы могут присутствовать в любом месте, но при декодировании их следует игнорировать):
TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu
В приведенной выше цитате закодированное значение Man — TWFu . Закодированные в ASCII символы M , a и n хранятся как байтовые значения 77
, 97
, и 110
, которые являются 8-битными двоичными значениями 01001101
, 01100001
, и 01101110
. Эти три значения объединяются в 24-битную строку, создавая 010011010110000101101110
. Группы из 6 бит (6 бит имеют максимум 2 6 = 64 различных двоичных значения) преобразуются в отдельные числа от начала до конца (в этом случае в 24-битной строке четыре числа), которые затем преобразуются в соответствующие им значения символов Base64.
Как показывает этот пример, кодировка Base64 преобразует три октета в четыре закодированных символа.
=
Можно добавить символы заполнения, чтобы последний закодированный блок содержал четыре символа Base64.
Преобразование шестнадцатеричного числа в восьмеричное полезно для преобразования между двоичным и Base64. Такое преобразование доступно как для продвинутых калькуляторов, так и для языков программирования. Например, шестнадцатеричное представление 24 бит выше — 4D616E. Восьмеричное представление — 23260556. Эти 8 восьмеричных цифр можно разбить на пары ( 23 26 05 56 ), и каждая пара преобразуется в десятичное, чтобы получить 19 22 05 46 . Используя эти четыре десятичных числа в качестве индексов для алфавита Base64, соответствующие символы ASCII будут TWFu .
Если имеется только два значимых входных октета (например, «Ma») или когда последняя входная группа содержит только два октета, все 16 бит будут захвачены в первых трех цифрах Base64 (18 бит); два наименее значимых бита последнего содержательного 6-битного блока окажутся равными нулю и будут отброшены при декодировании (вместе с последующим =
символом заполнения):
Если имеется только один значимый входной октет (например, «M») или когда последняя входная группа содержит только один октет, все 8 бит будут захвачены в первых двух цифрах Base64 (12 бит); четыре наименее значимых бита последнего содержательного 6-битного блока окажутся равными нулю и будут отброшены при декодировании (вместе с двумя последующими =
символами заполнения):
Существуют также интерактивные инструменты для пошаговой визуализации кодирования из обычного текста в base64. [7]
Поскольку Base64 — это шестибитная кодировка, а декодированные значения делятся на 8-битные октеты, каждые четыре символа текста, закодированного в Base64 (4 секстета = 4 × 6 = 24 бита), представляют три октета некодированного текста или данных (3 октета = 3 × 8 = 24 бита). Это означает, что когда длина некодированного ввода не кратна трем, к закодированному выводу необходимо добавить заполнение, чтобы его длина была кратна четырем. Символ заполнения — =
, что указывает на то, что для полного кодирования ввода не требуется дополнительных битов. (Это отличается от A
, что означает, что все оставшиеся биты — нули.) Пример ниже иллюстрирует, как усечение ввода приведенной выше цитаты изменяет заполнение вывода:
Символ заполнения не является существенным для декодирования, поскольку количество отсутствующих байтов можно вывести из длины закодированного текста. В некоторых реализациях символ заполнения является обязательным, в то время как в других он не используется. Исключением, в котором требуются символы заполнения, является случай, когда было объединено несколько файлов, закодированных в Base64.
При декодировании текста Base64 четыре символа обычно преобразуются обратно в три байта. Исключение составляют только символы заполнения. Один =
указывает, что четыре символа будут декодированы только в два байта, а ==
указывает, что четыре символа будут декодированы только в один байт. Например:
Другой способ интерпретации символа заполнения — рассматривать его как инструкцию отбрасывать 2 конечных бита из битовой строки каждый раз, когда =
встречается a. Например, когда ` bGlnaHQg dw== ` декодируется, мы преобразуем каждый символ (за исключением конечных вхождений ) в соответствующее им 6-битное представление, а затем отбрасываем 2 конечных бита для первого и еще 2 конечных бита для другого . В этом случае мы получили бы 6 бит из , и еще 6 бит из для битовой строки длиной 12, но поскольку мы удаляем 2 бита для каждого (всего 4 бита), в итоге при декодировании получается 8 бит (1 байт).=
=
=
d
w
=
dw==
Без заполнения после обычного декодирования четырех символов в три байта снова и снова может остаться менее четырех закодированных символов. В этой ситуации может остаться только два или три символа. Один оставшийся закодированный символ невозможен, потому что один символ Base64 содержит только 6 бит, а для создания байта требуется 8 бит, поэтому требуется минимум два символа Base64: первый символ вносит 6 бит, а второй символ вносит свои первые 2 бита. Например:
Декодирование без дополнения не выполняется последовательно среди декодеров. Кроме того, разрешение декодирования без дополнения по определению позволяет декодировать несколько строк в один и тот же набор байтов, что может быть риском безопасности. [8]
Реализации могут иметь некоторые ограничения на алфавит, используемый для представления некоторых битовых шаблонов. Это особенно касается последних двух символов, используемых в алфавите в позициях 62 и 63, и символа, используемого для заполнения (который может быть обязательным в некоторых протоколах или удаленным в других). В таблице ниже обобщены эти известные варианты и приведены ссылки на подразделы ниже.
Первое известное стандартизированное использование кодировки, которая сейчас называется MIME Base64, было в протоколе Privacy-enhanced Electronic Mail (PEM), предложенном RFC 989 в 1987 году. PEM определяет схему «печатаемой кодировки», которая использует кодировку Base64 для преобразования произвольной последовательности октетов в формат, который может быть выражен короткими строками 6-битных символов, как того требуют протоколы передачи, такие как SMTP . [9]
Текущая версия PEM (указанная в RFC 1421) использует 64-символьный алфавит, состоящий из заглавных и строчных латинских букв ( – , – ), цифр ( – ) и символов и . Символ также используется в качестве суффикса-заполнителя. [4] Исходная спецификация RFC 989 дополнительно использовала символ для разграничения закодированных, но незашифрованных данных в выходном потоке.A
Z
a
z
0
9
+
/
=
*
Для преобразования данных в печатную кодировку PEM первый байт помещается в самые старшие восемь бит 24-битного буфера , следующий — в средние восемь, а третий — в самые младшие восемь бит. Если осталось кодировать меньше трех байтов (или всего), оставшиеся биты буфера будут равны нулю. Затем буфер используется по шесть бит за раз, самые старшие сначала, как индексы в строке: " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
", и указанный символ выводится.
Процесс повторяется для оставшихся данных до тех пор, пока не останется менее четырех октетов. Если остается три октета, они обрабатываются как обычно. Если для кодирования остается менее трех октетов (24 бита), входные данные дополняются справа нулевыми битами для формирования целого числа, кратного шести битам.
После кодирования не дополненных данных, если два октета 24-битного буфера заполнены нулями, =
к выходу добавляются два символа; если один октет 24-битного буфера заполнен нулями, =
добавляется один символ. Это сигнализирует декодеру, что нулевые биты, добавленные из-за заполнения, следует исключить из восстановленных данных. Это также гарантирует, что длина закодированного вывода будет кратна 4 байтам.
PEM требует, чтобы все закодированные строки состояли ровно из 64 печатных символов, за исключением последней строки, которая может содержать меньше печатных символов. Строки разделяются пробелами в соответствии с локальными (платформенно-специфическими) соглашениями.
В спецификации MIME ( Multipurpose Internet Mail Extensions) Base64 указан как одна из двух схем кодирования двоичных данных в текст (вторая — quote-printable ). [5] Кодировка Base64 MIME основана на версии PEM RFC 1421: она использует тот же 64-символьный алфавит и механизм кодирования, что и PEM, и использует символ для заполнения выходных данных таким же образом, как описано в RFC 2045.=
MIME не определяет фиксированную длину для строк, закодированных в Base64, но определяет максимальную длину строки в 76 символов. Кроме того, он определяет, что любой символ, выходящий за пределы стандартного набора из 64 символов кодировки (например, последовательности CRLF), должен игнорироваться совместимым декодером, хотя большинство реализаций используют пару новой строки CR/LF для разделения закодированных строк.
Таким образом, фактическая длина двоичных данных, закодированных в Base64 и совместимых с MIME, обычно составляет около 137% от исходной длины данных ( 4 ⁄ 3 × 78 ⁄ 76 ), хотя для очень коротких сообщений накладные расходы могут быть намного выше из-за накладных расходов заголовков. Очень грубо, окончательный размер двоичных данных, закодированных в Base64, равен 1,37 исходного размера данных + 814 байт (для заголовков). Размер декодированных данных можно приблизительно рассчитать с помощью этой формулы:
байты = (длина_строки(кодированная_строка) − 814) / 1,37
UTF-7 , впервые описанный в RFC 1642, который позже был заменен RFC 2152, представил систему, называемую модифицированным Base64 . Эта схема кодирования данных используется для кодирования UTF-16 как символов ASCII для использования в 7-битных транспортах, таких как SMTP . Это вариант кодировки Base64, используемой в MIME. [10] [11]
Алфавит «Modified Base64» состоит из алфавита MIME Base64, но не использует =
символ заполнения « ». UTF-7 предназначен для использования в заголовках почты (определено в RFC 2047), а символ « » зарезервирован в этом контексте как символ экранирования для кодировки «quoted-printable». Модифицированный Base64 просто опускает заполнение и заканчивается сразу после последней цифры Base64, содержащей полезные биты, оставляя до трех неиспользованных бит в последней цифре Base64.=
OpenPGP , описанный в RFC 4880, описывает кодировку Radix-64 , также известную как « ASCII armor ». Radix-64 идентична кодировке «Base64», описанной MIME, с добавлением необязательного 24-битного CRC . Контрольная сумма вычисляется по входным данным перед кодированием; затем контрольная сумма кодируется тем же алгоритмом Base64 и, с префиксом в виде символа « » в качестве разделителя, добавляется к закодированным выходным данным. [12]=
RFC 3548, озаглавленный «Кодировки данных Base16, Base32 и Base64 », представляет собой информационный (ненормативный) меморандум, в котором делается попытка унифицировать спецификации RFC 1421 и RFC 2045 для кодировок Base64, кодировок с альтернативным алфавитом, а также кодировок Base32 (которая используется редко) и Base16.
Если только реализации не написаны в соответствии со спецификацией, которая ссылается на RFC 3548 и специально не требует иного, RFC 3548 запрещает реализациям генерировать сообщения, содержащие символы за пределами алфавита кодирования или без заполнения, а также заявляет, что реализации декодера должны отклонять данные, содержащие символы за пределами алфавита кодирования. [6]
RFC 4648 отменяет RFC 3548 и фокусируется на Base64/32/16:
Кодировка Base64 может быть полезна, когда в среде HTTP используется довольно длинная идентификационная информация. Например, фреймворк сохранения базы данных для объектов Java может использовать кодировку Base64 для кодирования относительно большого уникального идентификатора (обычно 128-битных UUID ) в строку для использования в качестве параметра HTTP в формах HTTP или URL-адресах HTTP GET . Кроме того, многим приложениям необходимо кодировать двоичные данные таким образом, чтобы их было удобно включать в URL-адреса, в том числе в скрытые поля веб-форм, и Base64 является удобной кодировкой для их компактного отображения.
Использование стандартного Base64 в URL требует кодирования символов ' +
', ' /
' и ' =
' в специальные шестнадцатеричные последовательности с процентным кодированием+
(' ' становится ' %2B
', ' /
' становится ' %2F
' и ' =
' становится ' %3D
'), что делает строку неоправданно длинной.
По этой причине существуют модифицированные варианты Base64 для URL (например, base64url в RFC 4648), где символы ' ' и ' ' стандартного Base64 соответственно заменяются на ' ' и ' ', так что использование кодировщиков/декодеров URL больше не требуется и не влияет на длину закодированного значения, оставляя ту же закодированную форму нетронутой для использования в реляционных базах данных, веб-формах и идентификаторах объектов в целом. Популярным сайтом для использования таких вариантов является YouTube . [13] Некоторые варианты разрешают или требуют пропускать знаки заполнения ' ', чтобы избежать их путаницы с разделителями полей, или требуют, чтобы любое такое заполнение было закодировано процентами. Некоторые библиотеки [ which? ] будут кодировать ' ' в ' ', потенциально подвергая приложения атакам относительного пути, когда имя папки кодируется из пользовательских данных. [ необходима цитата ]+
/
-
_
=
=
.
Методы atob()
и btoa()
JavaScript, определенные в спецификации проекта HTML5, [14] предоставляют функциональность кодирования и декодирования Base64 для веб-страниц. btoa()
Метод выводит символы заполнения, но они необязательны во входных данных метода atob()
.
Base64 можно использовать в различных контекстах:
<data encoding="base64">…</data>
например, на значки в экспортированном файле Firefoxbookmarks.html
.data:
URI, а не предоставляться в отдельных файлах.Некоторые приложения используют алфавит Base64, который существенно отличается от алфавитов, используемых в наиболее распространенных вариантах Base64 (см. сводную таблицу вариантов выше).
" (пробел)) до 95 (" _
"). Uuencoding использует алфавит " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_
" . Избегание всех строчных букв было полезно, поскольку многие старые принтеры печатали только заглавные. Использование последовательных символов ASCII экономило вычислительную мощность, поскольку требовалось только добавить 32, без необходимости использования таблицы поиска. Использование большинства знаков препинания и символа пробела может ограничить его полезность в некоторых приложениях, например, тех, которые используют эти символы в качестве синтаксиса. [ необходима цитата ]7
', 'O
', 'g
' и 'o
'. Его алфавит включает дополнительные знаки пунктуации. Он использует алфавит " !"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr
" .0b10xxxxxx
/etc/passwd
файле, используя кодировку B64 . Алфавит crypt помещает знаки препинания .
и /
перед буквенно-цифровыми символами. crypt использует алфавит " ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
" без заполнения. Преимущество перед RFC 4648 заключается в том, что сортировка закодированных данных ASCII дает тот же порядок, что и сортировка простых данных ASCII../0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
" . [18]./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
" . [19]+
and-
вместо.
and/
. Xxencoding использует алфавит " +-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
" .0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_
" . [21]JPEG contents encoded in Base64
" ... />В противном случае числа имеют вид [base#]n, где необязательное основание — это десятичное число от 2 до 64, представляющее арифметическую базу, а n — это число в этой базе.