Недопустимая длина массива символов Base-64

как говорится в названии, я получаю:

недопустимая длина для основания-64 char матрица.

Я читал об этой проблеме здесь, и кажется, что рекомендуется хранить ViewState в SQL, если он большой. Я использование мастера с большим количеством сбора данных, поэтому шансы мой ViewState большой. Но, прежде чем я перейду к " store-in-DB" решение, может быть, кто-то может взглянуть и сказать мне, если у меня есть другие варианты?

I создайте письмо для доставки, используя следующий метод:

public void SendEmailAddressVerificationEmail(string userName, string to)
{
    string msg = "Please click on the link below or paste it into a browser to verify your email account.<BR><BR>" +
                    "<a href="" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" +
                    userName.Encrypt("verify") + "">" +
                    _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" +
                    userName.Encrypt("verify") + "</a>";

    SendEmail(to, "", "", "Account created! Email verification required.", msg);
}

метод шифрования выглядит так:

public static string Encrypt(string clearText, string Password)
{

    byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);

    PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });


    byte[] encryptedData = Encrypt(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));

    return Convert.ToBase64String(encryptedData);
}

вот как выглядит HTML в hotmail:

Пожалуйста, нажмите на ссылку ниже или вставьте его в браузер, чтобы проверить почтовый ящик.

http://localhost:1563/Accounts/VerifyEmail.аспн?a=YOHY57xYRENEOu3H+FGq1Rf09AZAI56EPjfwuK8XWKg=

на принимающей стороне, в VerifyEmail.аспн.страница cs имеет строку:

 string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify");

вот геттер для UserNameToVerify:

public string UserNameToVerify
{
    get
    {
        return GetQueryStringValue("a").ToString();
    }
}

и вот метод GetQueryStringValue:

private static string GetQueryStringValue(string key)
{
    return HttpContext.Current.Request.QueryString.Get(key);
}

и метод дешифрования выглядит так:

public static string Decrypt(string cipherText, string password)
{

    **// THE ERROR IS THROWN HERE!!**
    byte[] cipherBytes = Convert.FromBase64String(cipherText);

можно ли исправить эту ошибку с помощью исправления кода или я должен хранить ViewState в базе данных?

4 ответов


длина строки в кодировке base64 всегда кратна 4. Если это не кратно 4, то = символы добавляются, пока не будет. Строка запроса формы ?name=value проблемы, когда value содержит = charaters (некоторые из них будут отброшены, я не помню точное поведение). Вы можете быть в состоянии уйти с добавлением правильного числа = символы перед выполнением декодирования base64.

изменить 1

вы можете найти что значение UserNameToVerify имеет "+"изменился на " "так что вам может понадобиться сделать что-то вроде этого:

a = a.Replace(" ", "+");

это должно получить правильную длину;

int mod4 = a.Length % 4;
if (mod4 > 0 )
{
    a += new string('=', 4 - mod4);
}

конечно, назвав UrlEncode (в ответ LukeH) должны сделать это все спорно.


Я думаю, что вам просто нужно URL-кодирование ваша строка Base64 при включении ее в строку запроса.

кодировка base64 использует некоторые символы, которые должны быть закодированы, если они являются частью строки запроса (а именно + и /, а может = тоже). Если строка неправильно закодирована, вы не сможете ее успешно декодировать на другом конце, отсюда и ошибки.

можно использовать HttpUtility.UrlEncode способ кодирования ваша строка Base64:

string msg = "Please click on the link below or paste it into a browser "
             + "to verify your email account.<br /><br /><a href=\""
             + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a="
             + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "\">"
             + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a="
             + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "</a>";

Я еще недостаточно авторитетен, чтобы поднять или прокомментировать, но ответ LukeH был для меня.

поскольку шифрование AES является стандартом для использования сейчас, он создает строку base64 (по крайней мере, все реализации шифрования/дешифрования, которые я видел). Эта строка имеет длину, кратную 4 (string.длина % 4 = 0)

строки, которые я получал, содержали + и = в начале или конце, и когда вы просто объедините это в строку запроса URL, она будет выглядеть правильно (для например, в электронном письме, которое вы генерируете), но когда ссылка следует, и страница .NET получает ее и помещает ее в это.Страница.Запрос.QueryString, эти специальные символы исчезнут, и ваша длина строки не будет кратной 4.

Как специальные символы в передней части строки (например:+), а также = в конце, вы не можете просто добавить некоторые =, чтобы компенсировать разницу, поскольку вы изменяете текст шифра таким образом, что не соответствует тому, что было на самом деле в оригинальный файл querystring.

Итак, обертывание зашифрованного текста с HttpUtility.URLEncode (не HtmlEncode) преобразует не буквенно-цифровые символы таким образом, что .NET анализирует их обратно в исходное состояние, когда он intepreted в коллекцию querystring.

хорошо, что нам нужно только сделать URLEncode при создании строки запроса для URL. На входящей стороне, он автоматически переводится обратно в исходную строку значение.

вот пример кода

string cryptostring = MyAESEncrypt(MySecretString);
string URL = WebFunctions.ToAbsoluteUrl("~/ResetPassword.aspx?RPC=" + HttpUtility.UrlEncode(cryptostring));

моя первоначальная догадка, не зная данных, будет заключаться в том, что UserNameToVerify не кратен 4 в длину. Проверьте FromBase64String на msdn.

// Ok
byte[] b1 = Convert.FromBase64String("CoolDude");
// Exception
byte[] b2 = Convert.FromBase64String("MyMan");