python b64decode неправильное заполнение

Я отправляю файл небольшими пакетами UDP. (python 3) На сервере я делю файл на маленькие кусочки и делаю

packets.append(b64encode(smallPart))

с другой стороны я делаю ровно наоборот

packets.append(b64decode(peice))    

Тем не менее, я продолжаю получать (во всех, кроме пакета) исключение Incorrect Padding

Есть ли стандартный размер для b64decode, который мне не хватает?


person msshapira    schedule 23.05.2011    source источник
comment
Вы уверены, что данные, которые вы отправляете, являются данными, которые вы получаете? Вы всегда можете добавить assert b64decode(b64encode(smallPart)) == smallPart, чтобы убедиться, что функции работают (они работают).   -  person Omri Barel    schedule 24.05.2011


Ответы (4)


Ваше описание того, что вы делаете, звучит нормально. Выбор размера входного куска влияет только на эффективность. Байты заполнения минимизируются, если длина каждой входной части (кроме, конечно, последней) кратна 3.

Вам нужно показать нам как код сервера, так и код клиента. В качестве альтернативы: на сервере регистрируйте ввод и переданные фрагменты. На клиенте регистрируйте полученные фрагменты. Сравнивать.

Любопытство: почему бы вам просто b64закодировать всю строку, разделить закодированный результат, как вам нравится, передать части, на клиенте снова собрать части с помощью b''.join(pieces) и b64декодировать это?

Дальнейшее любопытство: я думал, что содержимое пакета UDP может быть любым старым бинарным набором байтов; почему вы вообще делаете кодировку base64?

person John Machin    schedule 23.05.2011
comment
Machin: Любопытство: я записываю результат в stdout, и для больших файлов влияние соединения будет большим. Дальнейшее любопытство: кодировать, чтобы скрыть данные, пытаясь зашифровать файлы по протоколу dns. - person msshapira; 25.05.2011
comment
@msshapira: b64encode != шифрование, оно ничего не скрывает; на самом деле данные base64 легко распознаются как таковые. В любом случае, вы узнали, в чем была ваша проблема? Вы планируете принять ответ? - person John Machin; 25.05.2011

База 64 работает, кодируя каждые 3 байта в 4 байта. При декодировании он берет эти 4 байта и преобразует их обратно в 3 байта. Если во входных данных осталось менее 3 байтов, выходные данные дополняются символом «=», чтобы получить 4 байта. Если ввод в b64decode не кратен 4 байтам, вы получите исключение.

Самым простым решением для вас будет убедиться, что ваши пакеты всегда кратны 4 байтам.

person Mark Ransom    schedule 23.05.2011
comment
3 байта в 4 символа потребуют кратного 3, а не 4! - person msshapira; 24.05.2011
comment
3 байта ввода = 4 байта вывода, поэтому он говорит, что вы должны получить число, кратное 4. - person Mu Mind; 24.05.2011
comment
@msshapira, моя терминология была небрежной, я это исправлю. - person Mark Ransom; 24.05.2011
comment
-1 Вы должны иметь возможность разбивать ввод на части ЛЮБОГО размера, передавать каждую часть, декодировать каждую часть и присоединяться к списку декодированных частей. Процедуры кодирования Base 64 ЗАПОЛНЯЮТ вывод, если размер ввода не кратен ТРЁМ. Таким образом, разбиение входных данных на (в основном) фрагменты, кратные трем, более эффективно, но не обязательно. - person John Machin; 24.05.2011
comment
@John Machin, я полностью переписал ответ, и теперь он должен быть полностью технически точным. - person Mark Ransom; 24.05.2011
comment
@Mark Ransom: Должно быть, но это не так. (1) символы??? (2) размер содержимого пакета, кратный 4, является ПОБОЧНЫМ ЭФФЕКТОМ обеспечения того, чтобы данные были правильно закодированы в base64 и не были искажены при передаче. - person John Machin; 24.05.2011
comment
@John Machin, я очень удивлен, что версия b64encode для Python3 не возвращает текстовую строку Unicode, поскольку весь смысл заключается в преобразовании в текст, но, конечно, вы правы: docs.python.org/release/3.1.3/library/ Моя рекомендация делать пакеты число, кратное 4, было заявлено как самое простое решение, а не единственное решение - я все еще поддерживаю его. - person Mark Ransom; 24.05.2011
comment
@Mark Ransom: все дело в том, чтобы сделать 7-битные данные без специального значения для передачи по сети, что происходит в байтах - абсолютно ничего общего с текстом Unicode. Создание пакетов, кратных 4, является побочным эффектом правильного решения; это не само по себе решение. - person John Machin; 24.05.2011

Длина любой правильно закодированной строки base64 должна делиться на 4.

Base64 кодирует 3 байта как 4, поэтому, если вы начинаете с длины строки, которая не кратна 3, алгоритм добавляет один или два символа = в конце закодированной формы, по одному на каждый байт меньше некоторого числа, кратного 3. (см. http://en.wikipedia.org/wiki/Base64#Padding).

То, как получается выравнивание, количество символов = также равно количеству символов, кратному 4 в закодированной форме.

person Mu Mind    schedule 23.05.2011

Я пытался декодировать URL-безопасную строку в кодировке base64. Простая замена "." с "=" сделал свое дело для меня.

s = s.replace('.', '=')
# then base64decode
person Phil LaNasa    schedule 30.04.2015