История действительно не длинная. Я пытался выполнить одну из своих задач, когда понял, что существует странное поведение декодирования строки base64 в .NET C#. Вы знакомы с этой функцией, верно?

byte[] bytes = Convert.FromBase64String(text);

И вот проблема: когда вы хотите использовать свой закодированный текст как часть некоторого URL-адреса, вы хотите избежать некоторых символов, разрешенных в base64: «+», «/» и «=». Обычной практикой является замена «+» на «-», «/» на «_» и удаление всех знаков равенства с конца декодируемой строки. Вы можете погуглить процесс кодирования, я просто скажу, что знак равенства представляет собой «пробел» в декодируемой строке. Кодировка base64 занимает каждые 3 байта (каждые 3 символа) и создает для них 4 символа ASCII. Другими словами: если ваша исходная строка содержит количество символов, которое можно разделить на 3 без остатка, в конце не будет знаков равенства. Но для других случаев будет.

Было бы очень полезно, если бы функция .NET сама восстанавливала знаки равенства, но этого не происходит:

[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(“abcd”)) // -> YWJjZA==
$test = "YWJjZA"
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($test)) // -> Invalid length for a Base-64 char array or string.
$test = "YWJjZA=="
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($test)) // -> abcd

То же самое для С#. Если вы хотите использовать закодированную строку как часть URL-адреса, вы делаете что-то вроде этого:

var bytes = Encoding.UTF8.GetBytes(source);
var encodedUrlFriendly = Convert.ToBase64String(bytes).TrimEnd(‘=’).Replace(‘+’, ‘-’).Replace(‘/’, ‘_’);

Теперь вы хотите восстановить исходную строку на сервере (или в любом другом месте). Я не претендую на идеальное решение, но это может сэкономить вам время:

encoded = encoded.Replace(‘-’, ‘+’).Replace(‘_’, ‘/’);
var d = encoded.Length % 4;
if (d != 0)
{
    encoded = encoded.TrimEnd(‘=’);
    encoded += d % 2 > 0 ? “=” : “==”;
}
byte[] bytes = Convert.FromBase64String(encoded);
var decoded = Encoding.UTF8.GetString(bytes);

Надеюсь, это поможет кому-то.

p.s.: Команда .NET, пожалуйста, исправьте это наконец: D