2010-05-27 4 views
57

Как видно из названия говорит, я получаю:Недопустимая длина для Base-64 массива символов

неверной длину для базы-64 голец массива.

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

Я построить электронную почту для доставки, используя метод ниже:

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); 
} 

Метод Encrypt выглядит следующим образом:

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.aspx?a=YOHY57xYRENEOu3H+FGq1Rf09AZAI56EPjfwuK8XWKg=

На приемном конце, страница VerifyEmail.aspx.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 в базе данных?

+2

плз отправить мне дэ ошибки – DevDemon

+0

DevDemon - ошибка, как писала «FormatException: Invalid длина массива символов Base-64.» Есть ли что-то еще, что я должен отправить? –

ответ

127

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

Edit 1

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

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

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

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

Конечно вызывающему UrlEncode (как в ответ LukeH в) должны сделать все это спорный вопрос.

+8

Спасибо, Брэд. Это был на самом деле этот маленький код, который выполнял эту работу: a = a.Replace ("", "+"); –

+1

@Code Sherpa: если это так, ваш лучший выбор - это urlencode перед отправкой строка и urldecode при получении. В противном случае, если в вашу строку попадет другой важный символ URL, вам нужно будет добавить еще один оператор Replace. Кодирование - это обложка, которая защищает вас независимо. –

+0

полностью работает для r me. это ребята решения. – tugberk

4

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

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

Спасибо SwDevMan81. Только сейчас выходим из работы, но попробуем это позже сегодня вечером. Спасибо за вашу помощь. –

+0

Нет проблем, исправление будет состоять из пэда с символом, чтобы получить строку, которая кратна 4. – SwDevMan81

+0

Еще раз спасибо SwDevMan81. Я посмотрю на это. Я опубликовал UserNameToVeryify в своем исходном сообщении (FYI). ОК...теперь мне действительно нужно идти, или я собираюсь попасть в беду с настоящим боссом :) –

23

Я думаю, что вам просто нужно URL-encode вашей строки 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>"; 
+0

Спасибо. Просто попробовал ваше предложение Люк, но это не сработало :( –

+0

@Sherpa - Продолжайте работать, проблема почти наверняка связана с символами '='. –

+0

Luke - У меня такое чувство, что вы правы. домой. Спасибо, пакет. FYI. Я добавил, что строка выглядит как в моем ящике hotmail в моем исходном сообщении. –

7

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

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

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

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

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

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

Вот несколько примеров кода

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