108 votes

Longueur non valide pour un tableau de caractères Base-64

Comme le titre l'indique, je reçois :

Longueur non valide pour une Base- de base-64.

J'ai lu ce problème sur ce site et il semble que la fonction de stocker le ViewState dans SQL s'il est volumineux. Je suis j'utilise un assistant avec un grand nombre de données collectées, il y a donc des chances donc il y a de fortes chances que mon ViewState soit volumineux. Mais, avant de me tourner vers la solution du "stockage dans la base de données", j'ai décidé d'utiliser la solution du "stockage dans la base de données". dans la base de données, quelqu'un pourrait peut-être jeter un coup d'œil et me dire si j'ai d'autres options ? d'autres options ?

Je construis l'e-mail pour l'envoyer 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 se présente comme suit :

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 code HTML dans hotmail :

Veuillez cliquer sur le lien ci-dessous ou le coller dans un navigateur pour vérifier votre compte e-mail.

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

Du côté de la réception, la page VerifyEmail.aspx.cs contient la ligne :

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

Voici le getter pour UserNameToVerify :

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

Voici la méthode GetQueryStringValue :

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

Et la méthode de décryptage se présente comme suit :

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 par une correction de code ou dois-je stocker ViewState dans la base de données ?

244voto

uncle brad Points 1134

La longueur d'une chaîne encodée en base64 est toujours un multiple de 4. Si elle n'est pas un multiple de 4, alors = sont ajoutés jusqu'à ce qu'il le soit. Une chaîne de requête de la forme ?name=value a des problèmes lorsque le value contient = (certains d'entre eux seront supprimés, je ne me souviens pas du comportement exact). Vous pouvez peut-être vous en sortir en ajoutant le bon nombre de = avant de procéder au décodage base64.

Édition 1

Vous pouvez constater que la valeur de UserNameToVerify a eu "+" a été modifié en " " Il se peut donc que vous deviez faire quelque chose comme cela :

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

Cela devrait permettre d'obtenir la bonne longueur ;

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

Bien entendu, l'appel UrlEncode (comme dans la réponse de LukeH) devrait rendre tout cela discutable.

34voto

LukeH Points 110965

Je pense que vous devez simplement Coder 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 + y / 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 bout, d'où les erreurs.

Vous pouvez utiliser le HttpUtility.UrlEncode 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>";

12voto

Ken Forslund Points 25

Je n'ai pas encore la réputation nécessaire pour voter ou commenter, mais la réponse de LukeH était tout à fait pertinente pour moi.

Comme le cryptage AES est le standard à utiliser actuellement, il produit une chaîne base64 (du 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 j'obtenais contenaient des + et des = au début ou à la fin, et lorsque vous concaténé 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 que la page .NET le reçoit et le met 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 quelques = pour compenser la différence, car vous modifiez le texte codé d'une manière qui ne correspond pas à ce qui était réellement dans la chaîne de requête d'origine.

Ainsi, en enveloppant le texte codé avec HttpUtility.URLEncode (et non HtmlEncode), les caractères non alphanumériques sont transformés de manière à ce que .NET les analyse à nouveau dans leur état d'origine lorsqu'ils sont interprétés dans la collection de chaînes de requête.

L'avantage est que nous n'avons besoin d'effectuer l'URLEncode que lors de la génération de la chaîne de requête pour l'URL. Du côté de la réception, elle est automatiquement traduite dans la valeur de la chaîne d'origine.

Voici un exemple de code

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

8voto

SwDevMan81 Points 22634

Sans connaître les données, je pense que le UserNameToVerify n'est pas un multiple de 4. Vérifier le FromBase64String sur msdn.

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

2voto

Vikrant Points 3886

La chaîne cryptée comportait deux caractères spéciaux, + y = .

Le signe '+' provoquait l'erreur, la solution ci-dessous a donc bien fonctionné :

//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
...

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X