Comme le titre l'indique, je reçois:
Longueur non valide pour un tableau de caractères Base-64.
J'ai lu ce problème ici et il semble que la suggestion soit de stocker ViewState dans SQL s'il est volumineux. J'utilise un assistant avec beaucoup de collecte de données, donc il y a de fortes chances que mon ViewState soit grand. Mais, avant de passer à la solution "store-in-DB", peut-être que quelqu'un peut jeter un coup d'œil et me dire si j'ai d'autres options?
Je construis l'e-mail pour la livraison en utilisant la méthode ci-dessous:
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);
}
La méthode Encrypt ressemble à ceci:
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);
}
Voici à quoi ressemble le HTML dans hotmail:
Veuillez cliquer sur le lien ci-dessous ou le coller dans un navigateur pour vérifier votre compte de messagerie.
Du côté de la réception, la page VerifyEmail.aspx.cs a la ligne:
string username = Cryptography.Decrypt(_webContext.UserNameToVerify, "verify");
Voici le getter pour UserNameToVerify:
public string UserNameToVerify
{
get
{
return GetQueryStringValue("a").ToString();
}
}
Et voici la méthode GetQueryStringValue:
private static string GetQueryStringValue(string key)
{
return HttpContext.Current.Request.QueryString.Get(key);
}
Et la méthode de déchiffrement ressemble à:
public static string Decrypt(string cipherText, string password)
{
**// THE ERROR IS THROWN HERE!!**
byte[] cipherBytes = Convert.FromBase64String(cipherText);
Cette erreur peut-elle être corrigée avec un correctif de code ou dois-je stocker ViewState dans la base de données?
Replace
instruction. L'encodage est une combinaison qui vous protège malgré tout.a = a + new string('=', (4 - a.Length % 4) % 4)
. Exemple pour décoder 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
lequel nous supprimions des caractères. Merci @MattEllenJe suppose que vous devez simplement encoder l'URL votre chaîne Base64 lorsque vous l'incluez dans la chaîne de requête.
L'encodage Base64 utilise certains caractères qui doivent être encodés s'ils font partie d'une chaîne de requête (à savoir
+
et/
, et peut-être=
aussi). Si la chaîne n'est pas correctement encodée, vous ne pourrez pas la décoder avec succès à l'autre extrémité, d'où les erreurs.Vous pouvez utiliser la
HttpUtility.UrlEncode
méthode pour encoder votre chaîne 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>";
la source
=
caractères de fin .Je ne suis pas encore assez réputé pour voter ou commenter, mais la réponse de LukeH était parfaite pour moi.
Comme le cryptage AES est la norme à utiliser maintenant, il produit une chaîne base64 (au moins toutes les implémentations de cryptage / décryptage que j'ai vues). Cette chaîne a une longueur en multiples de 4 (string.length% 4 = 0)
Les chaînes que je recevais contenaient + et = au début ou à la fin, et lorsque vous concaténez simplement cela dans la chaîne de requête d'une URL, cela aura l'air correct (par exemple, dans un e-mail que vous générez), mais lorsque le lien est suivi et le La page .NET la reçoit et la place dans this.Page.Request.QueryString, ces caractères spéciaux auront disparu et la longueur de votre chaîne ne sera pas un multiple de 4.
Comme il y a des caractères spéciaux à l'AVANT de la chaîne (ex: +), ainsi que = à la fin, vous ne pouvez pas simplement ajouter des = pour compenser la différence car vous modifiez le texte chiffré d'une manière qui ne ne correspond pas à ce qui était réellement dans la chaîne de requête d'origine.
Ainsi, l'encapsulation du texte chiffré avec HttpUtility.URLEncode (et non HtmlEncode) transforme les caractères non alphanumériques d'une manière qui garantit que .NET les analyse à nouveau dans leur état d'origine lorsqu'il est interprété dans la collection de chaînes de requête.
La bonne chose est que nous n'avons besoin de faire le URLEncode que lors de la génération de la chaîne de requête pour l'URL. Du côté entrant, il est automatiquement traduit dans la valeur de chaîne d'origine.
Voici un exemple de code
string cryptostring = MyAESEncrypt(MySecretString); string URL = WebFunctions.ToAbsoluteUrl("~/ResetPassword.aspx?RPC=" + HttpUtility.UrlEncode(cryptostring));
la source
Ma première supposition sans connaître les données serait que UserNameToVerify n'est pas un multiple de 4 de longueur. Découvrez la FromBase64String sur msdn.
// Ok byte[] b1 = Convert.FromBase64String("CoolDude"); // Exception byte[] b2 = Convert.FromBase64String("MyMan");
la source
La chaîne chiffrée contenait deux caractères spéciaux
+
et=
.Le signe '+' donnait l'erreur, donc la solution ci-dessous fonctionnait bien:
//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 ...
la source
string stringToDecrypt = CypherText.Replace(" ", "+"); int len = stringToDecrypt.Length; byte[] inputByteArray = Convert.FromBase64String(stringToDecrypt);
la source