Алгоритм кодирования и декодирования Base64

25.11.2017

Иногда бывает, что разработчики, когда используют готовые механизмы — не до конца понимают сути их работы. Многие оперируют, к примеру, хеш таблицами и ничего не знают об «О» большом, сложности алгоритмов и скорости их работы. Это, как правило, сухие практики на маленьких проектах, которые считают, что теория им не нужна. Возможно, поэтому я не очень люблю всякого рода полностью готовые решения, которые, безусловно, облегчают и упрощают повседневную жизнь, но с другой стороны могут нанести непоправимый вред. Особенно для неокрепших молодых умов 🙂 Это касается многих ORM, некоторых свистоплясок с LINQ, функциональных подходов и т.д. Это вовсе не зло — это, наверное, даже очень хорошо. Но только в случае, когда вы знаете как именно это устроено под капотом и есть понимания о том, как обойтись без всех этих рюшечек, синтаксического сахара и т.д.

Сегодня я хочу поговорить про невероятно простой и (от этого) красивый алгоритм кодирования Base64. Я думаю, что с данным видом кодирования работали все: явно или неявно. Чаще всего base64 используется, когда необходимо представить произвольный набор байт в удобочитаемый текст — 64 печатных символа (отсюда и название) ASCII. Данный механизм широко используется в протоколах отправки электронной почты, IRC, FTP, в современных браузерах и т.д. Это удобный и простой способ не потерять ничего важного.

К примеру, текст Hello, World! будет выглядеть так: SGVsbG8sIFdvcmxkIQ==. Подобные «ухищрения» имеют огромный диапазон применения. Скажем, у вас есть чат без возможности передавать в нём бинарные файлы, только текст. Вы можете закодировать любую двоичную информацию средствами base64 и передать её в простом текстовом виде и ваш адресат без труда сможет декодировать ваше сообщение.

Кодирование информации в BASE64 строку

Теперь про сам алгоритм. Функция кодирования в Base64 строку — это функция, на входе в которую поступает массив байт. Внутри наши байты разбиваются в терцеты по три байта и трансформируется в порции по 6 бит, т.е. каждые три байта (24 бита) превращаются в 4 кусочка по 6 бит. Затем каждый шестибитовые кусочек переводим в десятичную систему счисления и находим соответствующий индекс в этой строке: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ (данный набор символов называется алфавитом кодирования). Если первоначальный массив не кратен трём — то мы используем специальный дополнительный символ равенства =.

Возможно, сразу звучит не очень просто — поэтому мы разберём пример. Возьмём слово: programming. Это 11 байт, в HEX: 70 72 6f 67 72 61 6d 6d 69 6e 67:

HEX BIN
01 080 01010000
02 114 01110010
03 111 01101111
04 103 01100111
05 114 01110010
06 097 01100001
07 109 01101101
08 109 01101101
09 105 01101001
10 110 01101110
11 103 01100111

Мы получаем последовательность бит в трёх полных терцетах:

01010000 01110010 01101111
01100111 01110010 01100001
01101101 01101101 01101001
01101110 01100111

Превращаем эту таблицу с тремя колонками в таблицу с четырьмя, т.е. в аккуратную матрицу 3×4. Преобразовав восьмибитовые ячейки — в ячейку по 6 бит получаем:

010100 000111 001001 101111
011001 110111 001001 100001
011011 010110 110101 101001
011011 100110 011100

Мы получили набор 6-битовых значений, каждый из которого при переводе в десятичную систему исчисления — даст индекс от 0 до 63 (итого 64 варианта). Извлекаем из массива символов ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ по нужному индексу символ и конкатенируем строку. Т.к. 11 байт не кратно 3 (крайняя правая нижняя ячейка пустая) — мы к концу нашей строки прибавляем символ равенства =. Или два таких символа, если к кратности необходимо будет добавить ещё один символ.
Для удобства можно воспользоваться следующей таблицей:ASCII to Base64
В остальном дело техники. Символ за символом мы получаем строку: UHJvZ3JhbW1pbmc=, что и является нашей кодированной в алгоритме base64 строкой.

Декодирование информации из BASE64 строки

С декодированием практически также легко. По сути это обратная операция кодированию. Последовательность символов, полученных при конвертации байт в base64 мы разбиваем на ровные группы по 4, затем каждый символ в соответствии с алфавитом кодирования base64 мы получаем цифровой порядковы йиндекс (номер), каждое подобное значения мы конвертируем в двоичную систему (6 бит) и получаем 24 бита, которые делим на уже три части и это будут наши первоначальные байты информации. Повторить до конечного результата 🙂

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

В ближайшее время я покажу простую реализацию этого алгоритма на языке C#. Оставайтесь с нами 🙂

Leave a comment

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Prev Post Next Post