Como o título diz, estou recebendo:
Comprimento inválido para uma matriz de caracteres Base-64.
Eu li sobre esse problema aqui e parece que a sugestão é armazenar ViewState em SQL se ele for grande. Estou usando um assistente com uma grande quantidade de coleta de dados, portanto, é provável que meu ViewState seja grande. Mas, antes de me voltar para a solução "store-in-DB", talvez alguém possa dar uma olhada e me dizer se eu tenho outras opções?
Eu construo o e-mail para entrega usando o método abaixo:
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);
}
O método Encrypt é semelhante a este:
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);
}
Aqui está a aparência do HTML no hotmail:
Clique no link abaixo ou cole em um navegador para verificar sua conta de e-mail.
Na extremidade de recebimento, a página VerifyEmail.aspx.cs tem a linha:
string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify");
Aqui está o getter para UserNameToVerify:
public string UserNameToVerify
{
get
{
return GetQueryStringValue("a").ToString();
}
}
E aqui está o método GetQueryStringValue:
private static string GetQueryStringValue(string key)
{
return HttpContext.Current.Request.QueryString.Get(key);
}
E o método de descriptografia se parece com:
public static string Decrypt(string cipherText, string password)
{
**// THE ERROR IS THROWN HERE!!**
byte[] cipherBytes = Convert.FromBase64String(cipherText);
Esse erro pode ser corrigido com uma correção de código ou devo armazenar ViewState no banco de dados?
Replace
instrução. A codificação é um macacão que o protege de qualquer maneira.a = a + new string('=', (4 - a.Length % 4) % 4)
. Exemplo para decodificar RFC 4648 URL-safe Base64 :public string base64urlDecode(string encoded) { return System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(encoded.Replace("_","/").Replace("-","+") + new string('=', (4 - encoded.Length % 4) % 4))); }
UrlDecode
qual estava removendo caracteres. Obrigado @MattEllenMeu palpite é que você simplesmente precisa codificar em URL sua string Base64 ao incluí-la na string de consulta.
Codificação Base64 usa alguns caracteres que devem ser codificadas se eles são parte de uma querystring (nomeadamente
+
e/
, e talvez=
também). Se a string não estiver codificada corretamente, você não conseguirá decodificá-la com sucesso na outra extremidade, daí os erros.Você pode usar o
HttpUtility.UrlEncode
método para codificar sua string 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>";
fonte
=
caracteres finais .Não tenho reputação o suficiente para votar ou comentar ainda, mas a resposta de LukeH foi certa para mim.
Como a criptografia AES é o padrão a ser usado agora, ela produz uma string base64 (pelo menos todas as implementações de criptografar / descriptografar que vi). Esta string tem um comprimento em múltiplos de 4 (string.length% 4 = 0)
As strings que eu estava recebendo continham + e = no início ou no final, e quando você apenas concatená-las em uma string de consulta de URL, parecerá correto (por exemplo, em um e-mail que você gerar), mas quando o link for seguido e A página .NET o recebe e coloca em this.Page.Request.QueryString, esses caracteres especiais desaparecerão e o comprimento da string não será um múltiplo de 4.
Como são caracteres especiais na FRENTE da string (ex: +), bem como = no final, você não pode simplesmente adicionar alguns = para compensar a diferença, pois você está alterando o texto cifrado de uma forma que não não corresponde ao que estava realmente na string de consulta original.
Portanto, envolver o texto cifrado com HttpUtility.URLEncode (não HtmlEncode) transforma os caracteres não alfanuméricos de uma maneira que garante que o .NET os analise de volta ao seu estado original quando é interpretado na coleção de querystring.
O bom é que só precisamos fazer o URLEncode ao gerar a string de consulta para a URL. No lado de entrada, ele é automaticamente convertido de volta para o valor da string original.
Aqui está um exemplo de código
string cryptostring = MyAESEncrypt(MySecretString); string URL = WebFunctions.ToAbsoluteUrl("~/ResetPassword.aspx?RPC=" + HttpUtility.UrlEncode(cryptostring));
fonte
Meu palpite inicial, sem saber os dados, seria que UserNameToVerify não é um múltiplo de 4 de comprimento. Verifique FromBase64String no msdn .
// Ok byte[] b1 = Convert.FromBase64String("CoolDude"); // Exception byte[] b2 = Convert.FromBase64String("MyMan");
fonte
A string criptografada tinha dois caracteres especiais
+
e=
.O sinal '+' estava dando o erro, então a solução abaixo funcionou bem:
//replace + sign encryted_string = encryted_string.Replace("+", "%2b"); //`%2b` is HTTP encoded string for **+** sign
OU
//encode special charactes encryted_string = HttpUtility.UrlEncode(encryted_string); //then pass it to the decryption process ...
fonte
string stringToDecrypt = CypherText.Replace(" ", "+"); int len = stringToDecrypt.Length; byte[] inputByteArray = Convert.FromBase64String(stringToDecrypt);
fonte