В вычислительной технике: кодирование - это процесс преобразования информации или инструкции в определенную форму.

Зачем нам вообще нужно кодировать информацию?

Допустим, вам нужно перенести данные из приложения A в B, а затем в C.

Приложение A - использует схему кодирования X.

Приложение B - использует схему кодирования Q, которая является подмножеством X.

Приложение C - использует ту же схему кодирования, что и A.

Вы заметили здесь проблему?

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

Давайте будем более конкретными.

Приложение A - использует схему кодировки UTF-8.

Приложение B - использует схему кодирования ASCII и не поддерживает никакую другую.

Приложение C - использует ту же схему кодирования, что и приложение A.

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

Во-первых, мы должны понять, как работает кодировка UTF-8 и ASCII:

Для UTF-8:

2 164 864 «символа» потенциально могут быть закодированы.

Это число 2⁷ + 2¹¹ + 2¹⁶ + 2²¹, что зависит от способа работы кодировки:

  • 1-байтовые символы имеют 7 бит для кодирования 0xxxxxxx - (ASCII)
  • 2-байтовые символы имеют 11 бит для кодирования 110xxxxx 10xxxxxx
  • 3-байтовые символы имеют 16 бит для кодирования 1110xxxx 10xxxxxx 10xxxxxx
  • 4-байтовые символы имеют 21 бит для кодирования 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Как мы видим, ASCII (128) - это всего лишь часть символов UTF-8 (2 164 864).

Как работает кодировщик base64?

Кодировщик base64 использует только 64 символа (A-Z, a-z, 0–9, +, /) из набора символов ASCII.

Стоит отметить, что кодировщику Base64 требуется всего 6 бит для представления всех символов в таблице. В символах ASCII используется 8 бит, следовательно, наименьшее число, которое может быть успешно закодировано без манипуляции с битами, будет 24 бита (наименьшее число 6 и 8 будет делиться без остатка)

Мой алгоритм кодирования данных в формате base64:

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

Этого вполне достаточно для кодирования наших данных в формате base64, но недостаточно для декодирования, когда они попадают в приложение C, base64 выходит за рамки этого руководства, но вот дополнительные правила, необходимые для простого декодирования:

Вычислите длину байтовой строки и разделите ее на 24:
- если остаток равен 18, мы добавляем «=» к закодированной строке, это означает, что закодированная строка короче 6 бит.

- если остаток равен 12, мы добавляем «==» к закодированной строке, это означает, что закодированная строка короче 12 бит.

- если остаток равен 6, мы ничего не добавляем к закодированной строке, но это указывает на то, что закодированная строка короче на 18 бит

Я реализовал алгоритм с php ниже:

$base64StringMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
$base64StringMapArray = str_split($base64StringMap);
$inputString = "Man is distinguished, not only by his reason, but by this singular passion from
other animals, which is a lust of the mind, that by a perseverance of delight
in the continued and indefatigable generation of knowledge, exceeds the short
vehemence of any carnal pleasure.";
$inputStringArray = str_split($inputString);
$inputStringLength = count($inputStringArray);
$inputStringBits = "";
for ($i = 0; $i < $inputStringLength; $i++) {
  $stringInBits = decbin(ord($inputStringArray[$i]));
  $inputStringBits .= str_pad($stringInBits,8,"0",STR_PAD_LEFT);
}
$offset = 0;
$length = 6;
$noOfIterations = ceil(strlen($inputStringBits)/$length);
$padZeros =  strlen($inputStringBits) + (6 - strlen($inputStringBits)%$length);
$base64EncodedString = "";
if ($padZeros > 0) {
  $inputStringBits = str_pad($inputStringBits,$padZeros,"0",STR_PAD_RIGHT);
}
for ($i = 0; $i < $noOfIterations; $i++) {
  $base64EncodedString .= $base64StringMapArray[bindec(substr($inputStringBits, $offset, $length))];
  $offset += $length;
}
$inputStringLastBitsBlockLength = strlen($inputStringBits) % 24;
if ($inputStringLastBitsBlockLength == 18) {
  $base64EncodedString .= "=";
} else if ($inputStringLastBitsBlockLength == 12) {
  $base64EncodedString .= "==";
}
echo $base64EncodedString;

Обратите внимание, что существуют более эффективные алгоритмы и библиотеки кодирования base64, цель этой статьи - не реализация, а то, как работает кодирование base64.

Спасибо за прочтение. !!!