Введение

Преобразование компьютерных данных в текст

Кодирование бинарных данных в текст — это представление данных в виде обычного текста. Более точно, это кодирование двоичных данных в последовательность печатаемых символов. Такие кодировки необходимы для передачи данных, когда канал связи не поддерживает двоичные данные (например, электронная почта или NNTP) или не является 8-битным чистым каналом. В документации PGP термин "ASCII armor" используется для обозначения кодирования бинарных данных в текст применительно к Base64.

Обзор

Основная потребность в кодировании двоичных данных в текст возникает из необходимости передавать произвольные двоичные данные по существующим протоколам связи, которые изначально разрабатывались для передачи только читаемого человеком текста на английском языке. Эти протоколы связи могут быть безопасными только для 7 бит (и даже в этом случае избегать определенных управляющих символов ASCII), могут требовать переноса строки через определенные максимальные интервалы и могут не сохранять пробельные символы. Таким образом, для передачи данных "безопасны" только 94 печатаемых символа ASCII.

Описание

Стандарт кодирования текста ASCII использует 7 бит для кодирования символов. С помощью этого можно кодировать 128 (то есть 2 в 7-й степени) уникальных значений (от 0 до 127) для представления букв, цифр и знаков препинания, обычно используемых в английском языке, а также набор управляющих символов, которые не представляют собой печатные символы. Например, заглавная буква A представлена в 7 битах как 1000001, 0x41 (65 в десятичной системе), цифра 2 – 0110010, 0x32 (50 в десятичной системе), символ } – 1111101, 0x7D (125 в десятичной системе), а управляющий символ RETURN – 0001101, 0x0D (13 в десятичной системе). В отличие от этого, большинство компьютеров хранят данные в памяти, организованной в восьмибитные байты. Файлы, содержащие машинный код и нетекстовые данные, как правило, содержат все 256 возможных восьмибитных байтовых значений. Многие компьютерные программы стали полагаться на это различие между семибитовым текстом и восьмибитовыми двоичными данными и не будут работать правильно, если в данных, которые должны содержать только текст ASCII, появятся символы, не входящие в ASCII. Например, если значение восьмого бита не сохраняется, программа может интерпретировать байтовое значение выше 127 как флаг, указывающий на выполнение какой-либо функции. Однако часто желательно иметь возможность отправлять нетекстовые данные через текстовые системы, например, прикреплять файл изображения к электронному письму. Для этого данные кодируются таким образом, чтобы восьмибитные данные были преобразованы в семибитные символы ASCII (обычно используются только буквенно-цифровые символы и знаки препинания – печатаемые символы ASCII). По безопасному прибытию в пункт назначения данные затем декодируются обратно в восьмибитный формат. Этот процесс называется кодированием двоичных данных в текст. Многие программы выполняют это преобразование для обеспечения передачи данных, такие как PGP и GNU Privacy Guard.

Кодирование простого текста

Методы кодирования бинарных данных в текст также используются как механизм кодирования обычного текста. Например:

Некоторые системы поддерживают более ограниченный набор символов; они не только не поддерживают полную 8-битную кодировку, но и не могут обрабатывать все печатные символы ASCII. Другие системы имеют ограничения на количество символов, допустимых между разрывами строк, например, ограничение в "1000 символов на строку" в некоторых реализациях протокола Simple Mail Transfer Protocol, как это предусмотрено. Некоторые малоизвестные, но всё ещё используемые протоколы используют внутриполосную сигнализацию, что может приводить к путанице при появлении определенных шаблонов в сообщении. Наиболее известным примером является строка "From " (включая завершающий пробел) в начале строки, используемая для разделения почтовых сообщений в формате файла mbox. Используя кодирование бинарных данных в текст для сообщений, которые уже являются обычным текстом, а затем декодируя их на другом конце, можно сделать такие системы полностью прозрачными. Это иногда называют «ASCII-бронированием». Например, компонент ViewState в ASP.NET использует кодирование Base64 для безопасной передачи текста через HTTP POST, чтобы избежать коллизий разделителей.

Стандарты кодирования

В таблице ниже приведено сравнение наиболее распространенных форм кодирования бинарных данных в текст. Эффективность, указанная в таблице, представляет собой отношение количества битов во входных данных к количеству битов в закодированном выходном потоке. Кодирование Тип данных Эффективность Реализации на языках программирования Комментарии Ascii85 Произвольные 80% awk, C, C (2), C#, F#, Go, Java, Perl, Python, Python (2) Существует несколько вариантов этого кодирования, таких как Base85, btoa и другие. Base32 Произвольные 62,5% ANSI C, Delphi, Go, Java, C#, F#, Python Base36 Целые числа ~64% bash, C, C++, C#, Java, Perl, PHP, Python, Visual Basic, Swift, многие другие Использует арабские цифры 0–9 и латинские буквы A–Z (базовый латинский алфавит ISO). Часто используется в системах перенаправления URL, таких как TinyURL или SnipURL/Snipr, в качестве компактных буквенно-цифровых идентификаторов. Base45 Произвольные ~67% (97%) Go, Python Определено в спецификации IETF RFC 9285 для компактного включения бинарных данных в QR-код. Base56 Целые числа — PHP, Python, Go Вариант кодирования Base58, который дополнительно исключает символы '1' и строчную 'o' для минимизации риска мошенничества и ошибок при вводе данных. Base58 Целые числа ~73% C, C++, Python, C#, Java Похоже на Base64, но модифицировано для исключения не буквенно-цифровых символов (+ и /), а также букв, которые могут выглядеть неоднозначно при печати (0 – ноль, I – заглавная i, O – заглавная o и l – строчная l). Base58 используется для представления адресов Bitcoin. Некоторые системы обмена сообщениями и социальных сетей разбивают строки на не буквенно-цифровых символах. Этого можно избежать, не используя зарезервированные символы URI, такие как +. Для SegWit оно было заменено на Bech32, см. ниже. Base62 Произвольные ~74% Rust, Python Похоже на Base64, но содержит только буквенно-цифровые символы. Base64 Произвольные 75% awk, C, C (2), Delphi, Go, Python, многие другие Раннее и до сих пор популярное кодирование, впервые определенное в 1987 году. Base85 Произвольные 80% C, Python, Python (2) Пересмотренная версия Ascii85. Base91 Произвольные 81% C#, F# Вариант фиксированной ширины basE91 Произвольные 81% C, Java, PHP, 8086 Assembly, AWK, C#, F#, Rust Вариант переменной ширины Base94 Произвольные 82% Python, C, Rust Base122 Произвольные 87,5% JavaScript, Python, Java Base125 Python и Javascript, Go, C BaseXML Произвольные 83,5% C, Python, JavaScript Bech32 Произвольные 62,5% + минимум 8 символов (метка, разделитель, 6 символов ECC) C, C++, JavaScript, Go, Python, Haskell, Ruby, Rust Спецификация. Используется в Bitcoin и Lightning Network. Данные кодируются как Base32 с возможностью проверки и исправления до 6 опечаток с помощью 6-символьного BCH-кода в конце, который также проверяет/исправляет удобочитаемую человеком часть. Вариант Bech32m имеет небольшое изменение, которое делает его более устойчивым к изменениям длины. BinHex Произвольные 75% Perl, C, C (2) MacOS Classic Decimal Целые числа ~42% Большинство языков Обычно используется для представления входных/выходных данных для людей. Hexadecimal (Base16) Произвольные 50% Большинство языков Существует в вариантах с заглавными и строчными буквами. Intel HEX Произвольные ≲50% C library, C++ Обычно используется для программирования EPROM и NOR flash-памяти. MIME Произвольные См. Quoted printable и Base64 См. Quoted printable и Base64 Контейнер кодирования для форматирования электронной почты. Percent encoding Текст (URI), Произвольные (RFC1738) ~40% (33–70%) C, Python, вероятно, многие другие Quoted printable Текст ~33–100% Вероятно, многие Сохраняет переносы строк; обрезает строки до 76 символов. S record (Motorola hex) Произвольные 49,6% C library, C++ Обычно используется для программирования EPROM и NOR flash-памяти. 49,6% предполагает 255 двоичных байт на запись. Tektronix hex Произвольные Обычно используется для программирования EPROM и NOR flash-памяти. Uuencoding Произвольные ~60% (до 70%) Perl, C, Delphi, Java, Python, вероятно, многие другие Раннее кодирование, разработанное в 1980 году для Unix to Unix Copy. В значительной степени заменено MIME и yEnc. Xxencoding Произвольные ~75% (похоже на Uuencoding) C, Delphi Предложено (и иногда используется) в качестве замены Uuencoding для устранения проблем с преобразованием наборов символов между ASCII и системами EBCDIC, которые могут повредить закодированные данные Uuencoding. z85 (ZeroMQ spec:32/Z85) Двоичные и ASCII 80% (похоже на Ascii85/Base85) C (оригинальный), C#, Dart, Erlang, Go, Lua, Ruby, Rust и другие Определяет подмножество ASCII, похожее на Ascii85, исключая некоторые символы, которые могут вызывать ошибки в программе (`\ " ' , ;). Формат соответствует спецификации ZeroMQ:32/Z85. (S/KEY) Произвольные 33% C, Каждое 64-битное число отображается в шесть коротких слов, каждое из одного-четырех символов, из общедоступного словаря 2048 слов. Коды от 32 до 126 из 95 являются известными как печатаемые символы ASCII. Некоторые старые и сегодня редко используемые форматы включают BOO, BTOA и USR. Большинство этих кодировок генерируют текст, содержащий только подмножество всех печатаемых символов ASCII: например, кодирование base64 генерирует текст, который содержит только буквы верхнего и нижнего регистра (A–Z, a–z), цифры (0–9) и символы "+", "/" и "=". Некоторые из этих кодировок (quoted printable и percent encoding) основаны на наборе разрешенных символов и одном управляющем символе. Разрешенные символы остаются неизменными, а все остальные символы преобразуются в строку, начинающуюся с управляющего символа. Этот тип преобразования позволяет получить почти читаемый текст, поскольку буквы и цифры являются частью разрешенных символов и, следовательно, остаются неизменными в закодированном тексте. Эти кодировки создают самый короткий вывод ASCII для входных данных, которые в основном состоят из печатаемых символов ASCII. Другие кодировки (base64, uuencoding) основаны на отображении всех возможных последовательностей из шести битов в различные печатаемые символы. Поскольку печатаемых символов больше 26 = 64, это возможно. Данная последовательность байтов преобразуется путем просмотра ее как потока битов, разбиения этого потока на фрагменты по шесть битов и создания последовательности соответствующих символов. Различные кодировки различаются отображением между последовательностями битов и символами, а также способом форматирования результирующего текста. Некоторые кодировки (оригинальная версия BinHex и рекомендуемое кодирование для CipherSaber) используют четыре бита вместо шести, отображая все возможные последовательности из 4 битов на 16 стандартных шестнадцатеричных цифр. Использование 4 битов на закодированный символ приводит к выходу на 50% длиннее, чем base64, но упрощает кодирование и декодирование — расширение каждого байта в источнике независимо до двух закодированных байтов проще, чем расширение 3 исходных байтов до 4 закодированных байтов в base64. Из первых 192 кодов PETSCII 164 имеют видимые представления при цитировании: 5 (белый), 17–20 и 28–31 (цвета и элементы управления курсором), 32–90 (эквивалент ascii), 91–127 (графика), 129 (оранжевый), 133–140 (функциональные клавиши), 144–159 (цвета и элементы управления курсором) и 160–192 (графика). Теоретически это позволяет создавать кодировки, такие как base128, между машинами, говорящими на PETSCII.