Метод fundametal для преобразования гекса в base64 в python3
Я хочу конвертировать данный гекс в base64 (в Python без использования каких-либо библиотек). Как я узнал из других ответов в стеке, мы можем сгруппировать 3 шестнадцатеричных слова (12 битов, т.е. 4 бита каждый), чтобы получить 2 значения base64 (12 битов, т.е. 6 битов каждый). А также мы можем сгруппировать 6 шестнадцатеричных (24 бита) в 4 значения base64 (24 бита).
Стандартная процедура - сложить все двоичные биты шестнадцатеричных кодов и начать группировку слева в пакеты по 6.
Мой вопрос касается ситуации, для которой нам нужно заполнение: (Предполагается, что мы конвертируем 3 гекса в 2 base64). Возникнет ситуация, когда у нас останется только 2 или 1 шестнадцатеричное значение для конвертации. Возьмите пример ниже:
'a1' к base64
10100001 (двоичное из a1)
101000 01 (0000) // создание групп по 6 и добавление дополнительных 0, где это необходимо
Это дает "oQ" ответ, который находится в каком-то месте(oQ==), а что-то другое в другом месте(wqE=)
Q1. Какой из двух источников дает правильный ответ? Почему другой не прав, будучи хорошим онлайн-декодером?
Q2. Как мы понимаем число '=' здесь? (Мы могли бы просто добавить достаточное количество 0 в любом месте, как необходимо в примере выше, и, таким образом, окончание ответа было бы здесь просто oQ, а не oQ==, при условии, что oQ == является правильным)
Моя концепция такова: если гекс имеет длину 2 (а не 3), мы дополняем его одним = (следовательно, отвечая ответу wqE= в вышеприведенном случае), иначе, если гекс имеет длину 1 (а не 3), мы дополняем с двойным = 'ы.
В то же время меня смущает, что если 3 гекса преобразуется в 2 base64, нам никогда не понадобятся два =.
'a' к base64
1010 (двоичное из)
Q3. Как конвертировать шестнадцатеричное 'a' в base64.
1 ответ
Base64 определяется RFC 4648 как "предназначенный для представления произвольных последовательностей октетов". Октет представляет собой 8-битную единицу, практически синонимичную с байтом. Когда ваш ввод находится в форме шестнадцатеричной строки, ваш первый шаг должен состоять в том, чтобы декодировать его в байтовую строку. Вам нужно два шестнадцатеричных символа для каждого байта. Если длина входных данных нечетная, разумный путь действий состоит в том, чтобы вызвать ошибку.
Чтобы ответить на ваши пронумерованные вопросы:
В1: Даже когда вы собираетесь реализовать свой собственный кодер, вы можете использовать стандартную библиотеку Python для исследования. Декодирование двух результатов обратно в байты дает:
>>> import base64
>>> base64.b64decode(b'oQ==')
b'\xa1'
>>> base64.b64decode(b'wqE=')
b'\xc2\xa1'
Так, oQ==
правильно, пока wqE=
имеет c2
байт добавлен впереди. Я могу предположить, что это результат применения кодировки UTF-8 перед Base64. Подтвердить:
>>> '\u00a1'.encode('utf-8')
b'\xc2\xa1'
Q2: правила заполнения подробно описаны в RFC.
Q3: Это неоднозначно, и вы правы, что запутались.