Как работает Binascii.a2b_base64 (base64.b64decode) Python?C++

Программы на C++. Форум разработчиков
Anonymous
Как работает Binascii.a2b_base64 (base64.b64decode) Python?

Сообщение Anonymous »

Я проверил исходный код на Python и реализовал функцию, аналогичную функции Python binascii.a2b_base64.
Эта функция находится по пути Python-3.12.4/Modules. /binascii.c, строка 387.

Код: Выделить всё

static PyObject *
binascii_a2b_base64_impl(PyObject *module, Py_buffer *data, int strict_mode)
Я использовал C++ и реализовал эту функцию в своем коде в соответствии с исходной функцией на Python, чтобы лучше понять и изучить принцип работы декодирования Base64.
Однако я не знаю, почему реализованная мной функция не может правильно обрабатывать символы, не закодированные в Base64.
Я проверил эти коды и подтвердил, что они не влияют на обработка функцией символов, не закодированных в Base64, например function [

Код: Выделить всё

_PyBytesWriter_Init
, _PyBytesWriter_Alloc, _PyBytesWriter_Finish, ...], и проигнорировал его в своем коде.
При обработке строк Base64, соответствующих стандарту RFC4648 , а также: В случае, когда в качестве символа, не закодированного в Base64, используется только \n, реализованная мной функция даст тот же результат, что и соответствующая функция в Python.

Для пример:

Код: Выделить всё

const char *encoded = {
"QUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVpBQkNERUZHSElKS0xNTk9QUVJTVFVW\n"
"V1hZWkFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaQUJDREVGR0hJSktMTU5PUFFS\n"
"U1RVVldYWVpBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWg==\n"
};
Использование моей функции или функции Python binascii.a2b_base64 даст тот же результат, что и следующий:

Код: Выделить всё

ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ
Вот конкретная реализация моего кода:

Код: Выделить всё

#include 
#include 
#include 
#include 
#include 

#define BASE64PAD '='

constexpr uint8_t b64de_table[256] = {
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255, 62, 255,255,255, 63,
52 , 53, 54, 55,  56, 57, 58, 59,  60, 61,255,255, 255,  0,255,255,

255,  0,  1,  2,   3,  4,  5,  6,   7,  8,  9, 10,  11, 12, 13, 14,
15 , 16, 17, 18,  19, 20, 21, 22,  23, 24, 25,255, 255,255,255,255,
255, 26, 27, 28,  29, 30, 31, 32,  33, 34, 35, 36,  37, 38, 39, 40,
41 , 42, 43, 44,  45, 46, 47, 48,  49, 50, 51,255, 255,255,255,255,

255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,

255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255,
255,255,255,255, 255,255,255,255, 255,255,255,255, 255,255,255,255};

uint8_t *
pyBase64Decode(const char *buffer, size_t &length,
bool strict_mode = false)
{
std::string error_message;

const uint8_t *ascii_data = (const uint8_t *)buffer;
size_t ascii_len = length;
bool padding_started = 0;

size_t bin_len = ascii_len / 4 * 3;
uint8_t *bin_data = new (std::nothrow) uint8_t[bin_len + 1];
if(!bin_data) {
throw std::runtime_error("Failed to allocate memory for bin_data.");
}
uint8_t *bin_data_start = bin_data;
bin_data[bin_len] = 0x0;

uint8_t leftchar = 0;
uint32_t quad_pos = 0;
uint32_t pads = 0;

if(strict_mode && (ascii_len > 0) && (*ascii_data == BASE64PAD)) {
error_message = "Leading padding not allowed.";
goto error_end;
}

size_t i;
uint8_t this_ch;
for(i = 0; i < ascii_len; ++i) {
this_ch = ascii_data[i];

if(this_ch == BASE64PAD) {
padding_started = true;
// If the current character is a padding character, the length
// will be reduced by one to obtain the decoded true length.
bin_len--;

if(strict_mode && (!quad_pos)) {
error_message = "Excess padding not allowed.";
goto error_end;
}

if((quad_pos >= 2) && (quad_pos + (++pads) >= 4)) {

if(strict_mode &&  ((i + 1) < ascii_len)) {
error_message = "Excess data after padding.";
goto error_end;
}

goto done;
}

continue;
}

this_ch = b64de_table[this_ch];
if(this_ch == 255) {
if(strict_mode) {
error_message = "Only base64 data is allowed.";
goto error_end;
}
continue;
}

if(strict_mode && padding_started) {
error_message = "Discontinuous padding not allowed.";
goto error_end;
}

pads = 0;

switch(quad_pos) {
case 0:
quad_pos = 1;
leftchar = this_ch;
break;
case 1:
quad_pos = 2;
*bin_data++ = (leftchar > 4);
leftchar = this_ch & 0xf;
break;
case 2:
quad_pos = 3;
*bin_data++ = (leftchar > 2);
leftchar = this_ch & 0x3;
break;
case 3:
quad_pos = 0;
*bin_data++ = (leftchar 

Подробнее здесь: [url]https://stackoverflow.com/questions/78655289/how-does-pythons-binascii-a2b-base64-base64-b64decode-work[/url]

Вернуться в «C++»