base64 не один-к-одному; Есть несколько способов кодировать одни и те же байты. То, что вы видите, - это несколько способов кодирования отступа в конце строки.
base64 кодирует байты (8 бит каждый) в базу 64. Символ в базе 64 кодирует 6 бит, поэтому каждые три символа могут обрабатывать 3 байта. Когда длина ввода не кратна трем, base64 использует =
в качестве символа заполнения. XXX=
указывает, что должны использоваться только первые два байта группы (где XXX
представляет три произвольных символа base64), тогда как XX==
указывает, что должен использоваться только первый байт.
Последняя группа в вашем примере - AA==
, которая кодирует 0 байт. Тем не менее, часть AA
может кодировать 12 битов, из которых наименее значимые четыре игнорируются при декодировании, поэтому вы можете использовать любой символ из A-P
и получить тот же результат. Когда вы используете кодировщик, он всегда выбирает нули для этих четырех битов, поэтому вы получаете обратно AA==
.
Заполнение на самом деле еще более сложно в base64. Технически вы можете исключить символы =
; длина строки будет указывать на их отсутствие (согласно Википедии, не все декодеры поддерживают это). Полезность padding заключается в том, что она позволяет безопасно объединять строки base64, поскольку каждая группа из четырех интерпретируется одинаково. Однако это означает, что заполнение также может появляться в середине строки, а это означает, что последовательность байтов может быть закодирована различными способами. Вы также можете включить пробелы или символы новой строки, которые все игнорируются.
Несмотря на все это, base64 все еще инъективен, то есть если x! = Y, то base64 (x)! = Base64 (y); В результате вы не можете получить коллизии и всегда можете получить исходные данные. Однако base64 не является сюръективным: существует множество способов кодирования одних и тех же данных.