Lunghezza non valida per un array di caratteri Base-64

Come dice il titolo, sto ottenendo:

Lunghezza non valida per un array di caratteri Base-64.

Ho letto su questo problema qui e sembra che il suggerimento è quello di memorizzare ViewState in SQL se è grande. Sto usando un wizard con una buona dose di raccolta dati, quindi è probabile che il mio ViewState sia grande. Ma, prima di passare alla soluzione “store-in-DB”, forse qualcuno può dare un’occhiata e dirmi se ho altre opzioni?

Costruisco l’email per la consegna utilizzando il seguente metodo:

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.

" + "" + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + userName.Encrypt("verify") + ""; SendEmail(to, "", "", "Account created! Email verification required.", msg); }

Il metodo Encrypt ha il seguente aspetto:

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

    Ecco come appare l’HTML in hotmail:

    Clicca sul link qui sotto o incollalo in un browser per verificare il tuo account di posta elettronica.

    http: // localhost: 1563 / Conti / VerifyEmail.aspx a = YOHY57xYRENEOu3H + FGq1Rf09AZAI56EPjfwuK8XWKg =

    Sul lato ricevente, la pagina VerifyEmail.aspx.cs ha la linea:

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

    Ecco il getter per UserNameToVerify:

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

    Ed ecco il metodo GetQueryStringValue:

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

    E il metodo di decrittografia sembra:

     public static string Decrypt(string cipherText, string password) { **// THE ERROR IS THROWN HERE!!** byte[] cipherBytes = Convert.FromBase64String(cipherText); 

    Questo errore può essere risolto con una correzione del codice o devo archiviare ViewState nel database?

    La lunghezza di una stringa codificata in base64 è sempre un multiplo di 4. Se non è un multiplo di 4, quindi = caratteri vengono aggiunti fino a quando non lo sono. Una stringa di query del modulo ?name=value ha problemi quando il value contiene = caratteri (alcuni di essi verranno eliminati, non ricordo il comportamento esatto). Potresti essere in grado di farla franca aggiungendo il giusto numero di caratteri = prima di eseguire la decodifica di base64.

    Modifica 1

    Potresti scoprire che il valore di UserNameToVerify è stato modificato da "+" a " " , quindi potrebbe essere necessario fare qualcosa del genere:

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

    Questo dovrebbe avere la giusta lunghezza;

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

    Ovviamente chiamare UrlEncode (come nella risposta di LukeH) dovrebbe rendere tutto questo moot.

    La mia ipotesi è che hai semplicemente bisogno di codificare l’ URL della tua stringa Base64 quando la includi nella Querystring.

    La codifica Base64 utilizza alcuni caratteri che devono essere codificati se fanno parte di una querystring (ovvero + e / , e forse = troppo). Se la stringa non è codificata correttamente, non sarà ansible decodificarla correttamente dall’altra parte, quindi gli errori.

    È ansible utilizzare il metodo HttpUtility.UrlEncode per codificare la stringa Base64:

     string msg = "Please click on the link below or paste it into a browser " + "to verify your email account.

    " + _configuration.RootURL + "Accounts/VerifyEmail.aspx?a=" + HttpUtility.UrlEncode(userName.Encrypt("verify")) + "";

    Non sono abbastanza affidabile da votare o commentare ancora, ma la risposta di LukeH era azzeccata per me.

    Poiché la crittografia AES è lo standard da utilizzare ora, produce una stringa base64 (almeno tutte le implementazioni di crittografia / decrittografia che ho visto). Questa stringa ha una lunghezza in multipli di 4 (string.length% 4 = 0)

    Le stringhe che stavo ricevendo contenevano + e = all’inizio o alla fine, e quando lo si concatena in una query querys dell’URL, sembrerà giusto (ad esempio, in un’e-mail che si genera), ma quando il link è seguito e il La pagina .NET lo riceve e lo inserisce in this.Page.Request.QueryString, quei caratteri speciali saranno scomparsi e la lunghezza della stringa non sarà in un multiplo di 4.

    Siccome i caratteri speciali sono FRONT della stringa (es: +), così come = alla fine, non puoi semplicemente aggiungere un po ‘= per fare la differenza mentre stai modificando il testo della cifratura in un modo che non Corrispondono a ciò che era effettivamente nella querystring originale.

    Quindi, avvolgere il testo cifrato con HttpUtility.URLEncode (non HtmlEncode) trasforma i caratteri non alfanumerici in un modo che assicuri che .NET li ritorni nel loro stato originale quando è intepretato nella collezione querystring.

    La cosa buona è che abbiamo solo bisogno di fare l’URLEncode quando si genera la querystring per l’URL. Sul lato in entrata, viene automaticamente tradotto nuovamente nel valore di stringa originale.

    Ecco alcuni esempi di codice

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

    La mia ipotesi iniziale senza conoscere i dati sarebbe che UserNameToVerify non è un multiplo di 4 di lunghezza. Dai un’occhiata a FromBase64String su msdn .

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