У меня есть следующая строка base64:
R1NNQiBBZ2VuY3kgR21iSCAvIFdlYmRlc2lnbiBBZ2VudHVyIFVsbSAvIE9ubGluZXNob3AgQWdlbnR1ciAvIEFwcCBBZ2VudHVyIFVsbSwgR2VybWFueS==
И используя онлайн-декодер base64, я получаю следующий результат:
GSMB Agency GmbH / Webdesign Agentur Ulm / Onlineshop Agentur / App Agentur Ulm, Germany
Все хорошо, верно? Но теперь, если я попытаюсь преобразовать этот текст обратно в base64, результат станет
R1NNQiBBZ2VuY3kgR21iSCAvIFdlYmRlc2lnbiBBZ2VudHVyIFVsbSAvIE9ubGluZXNob3AgQWdlbnR1ciAvIEFwcCBBZ2VudHVyIFVsbSwgR2VybWFueQ==
Есть идеи?
Это код С#, который я использую для декодирования:
string basestring = "R1NNQiBBZ2VuY3kgR21iSCAvIFdlYmRlc2lnbiBBZ2VudHVyIFVsbSAvIE9ubGluZXNob3AgQWdlbnR1ciAvIEFwcCBBZ2VudHVyIFVsbSwgR2VybWFueS= = ";
string output = Encoding.UTF8.GetString(Convert.FromBase64String(basestring));
return output;
И вот часть кодирования
string basestring = "GSMB Agency GmbH / Webdesign Agentur Ulm / Onlineshop Agentur / App Agentur Ulm, Germany";
string output = Convert.ToBase64String(Encoding.UTF8.GetBytes(basestring));
return output;
Я удалил тег шифрования, потому что этот вопрос не имеет ничего общего с шифрованием.
Похоже, что один из этих кодировщиков использует неинициализированную переменную. Но на практике это не должно иметь значения.





На самом деле это артефакт перехода от 8-битной кодировки (UTF8) к 6-битной кодировке (Base64).
В качестве справки, вот таблица кодировки Base64
Возьмем пример строки "AB"; A и B являются символами (65 и 66) соответственно. В 8-битной двоичной группе 65/66 равны 01000001/01000010.
При кодировании в Base64 одни и те же биты вашей строки разделяются на группы по 6 вместо 8. Таким образом, та же 16-битная последовательность выше разбивается на 010000/010100/0010 (тот же битовый шаблон, просто сгруппированный по-другому).
Итак, первые две группы просты. Вы посмотрите таблицу кодирования, указанную выше, и увидите, что 010000 = Q / 010100 = U. Затем у вас есть последняя группа только с 4 битами вместо ожидаемых 6. Здесь все становится интереснее.
При кодировании конец обычно дополняется нулями, чтобы получить 6 бит. Таким образом, ваше 0010 становится 001000, то есть I. Итак, "AB" при кодировании в Base64 становится "QUI = ". = не является обязательным, он нужен только для того, чтобы число символов было кратно 4.
Помните, когда ваша последняя группа 0010 была дополнена до 6 бит? Вот самое интересное: они не обязательно должны быть нулями. 16-бит (2x8) в исходной строке стали 18-битами (3x6) из-за заполнения. Поскольку 18 не кратно 8 (битам), кодер/декодер знает достаточно, чтобы отбросить лишние биты. Таким образом, двухбитное заполнение может быть любым, и они все равно будут правильно декодироваться.
0010 при заполнении может быть 001000, 001001, 001010 или 001011, что переводится как I, J, K, or L. Поднимите любой декодер и попробуйте расшифровать QUI, QUJ, QUK и QUL. Все они будут расшифрованы в "AB"
Теперь ваша строка при разделении 6-битных групп выглядит следующим образом (см. fiddle):
var basestring = "GSMB Agency GmbH / Webdesign Agentur Ulm / Onlineshop Agentur / App Agentur Ulm, Germany";
var sixBitGroups = Encoding.UTF8.GetBytes(basestring)
.SelectMany(b => $"{Convert.ToString(b, 2).PadLeft(8,'0')}")
.Chunk(6)
.Select(c => new string(c.ToArray()));
string.Join("/", sixBitGroups).Dump();
Вы заметите, что оно заканчивается на ../01. Это 01 нужно дополнить 4 дополнительными битами. Опять же, обычно это нули, что делает 010000 то есть Q. Итак, вы увидите, что ваша закодированная строка заканчивается на ..FueQ==. Но когда вы поймете, что они не обязательно должны быть все нулями, вы увидите в таблице , что 01xxxx охватывает все, начиная с Q,R,S, .. i,j. Это объясняет, почему ваш base64 ..FueS== все еще декодирует ту же самую строку.
Хорошо, спасибо за такой подробный ответ, это определенно будет полезно знать в будущем!
Просто примечание: этими битами заполнения можно злоупотреблять для отправки скрытой информации, если можно сгенерировать и отправить большое количество строк base64.
Связанный, возможный дубликат: Является ли строка в кодировке base64 уникальной?