web-dev-qa-db-fra.com

Erreur base64 générant une erreur de caractère non valide

Je continue à avoir une erreur de caractère invalide Base64 même si je ne devrais pas.

Le programme prend un fichier XML et l'exporte dans un document. Si l'utilisateur le souhaite, il compressera également le fichier. La compression fonctionne correctement et renvoie une chaîne Base64 encodée en UTF-8 et écrite dans un fichier.

Lorsqu'il est temps de recharger le document dans le programme, je dois vérifier s'il est compressé ou non, le code est simplement:

byte[] gzBuffer = System.Convert.FromBase64String(text);
return "1F-8B-08" == BitConverter.ToString(new List<Byte>(gzBuffer).GetRange(4, 3).ToArray());

Il vérifie le début de la chaîne pour voir si elle contient du code GZips.

Maintenant, le truc, c'est que tous mes tests fonctionnent. Je prends une chaîne, la compresse, la décompresse et la compare à l'originale. Le problème vient du moment où la chaîne est renvoyée d'un jeu d'enregistrements ADO. La chaîne correspond exactement à ce qui a été écrit dans le fichier (avec l’ajout de "\ 0" à la fin, mais je ne pense pas que cela puisse faire quoi que ce soit, même coupé, il jette encore). J'ai même copié et collé la chaîne entière dans une méthode de test et compressé/décompressé. Fonctionne bien.

Les tests vont réussir mais le code échouera en utilisant exactement la même chaîne? La seule différence est qu'au lieu de simplement déclarer une chaîne normale et de la transmettre, je reçois celle renvoyée d'un jeu d'enregistrements.

Des idées sur ce que je fais mal?

13
Brandon

Vous dites

La chaîne correspond exactement à ce qui était écrit au fichier (avec l'ajout d'un "\ 0" à la fin, mais je ne pense pas que ne fait même rien).

En fait, cela fait quelque chose (votre code génère une FormatException: "Caractère invalide dans une chaîne Base 64") parce que Convert.FromBase64String ne considère pas "\ 0" comme un caractère Base64 valide.

  byte[] data1 = Convert.FromBase64String("AAAA\0"); // Throws exception
  byte[] data2 = Convert.FromBase64String("AAAA");   // Works

Solution: Supprimez la terminaison zéro. (Peut-être appeler .Trim("\0"))

Remarques:

Le MSDN docs pour Convert.FromBase64String dit que cela jettera une FormatException quand

La longueur de s, en ignorant les espaces blancs caractères, n'est pas zéro ou un multiple de 4.

-ou- 

Le format de s n'est pas valide. s contient un caractère non base 64, plus que deux caractères de remplissage, ou un caractère d'espace non blanc parmi les caractères de remplissage.

et cela

Les 64 chiffres de base en ordre croissant à partir de zéro sont les caractères majuscules 'A' à 'Z', caractères minuscules 'a' à 'z', aux chiffres '0' à '9' et au symboles '+' et '/'.

15

Que le caractère nul soit autorisé ou non dépend vraiment du codec base64 en question ..__ Étant donné le caractère vague de la norme Base64 (il n'y a pas de spécification exacte faisant autorité), de nombreuses implémentations l'ignoreraient simplement comme un espace. Et ensuite, d'autres peuvent signaler qu'il s'agit d'un problème. Et les plus dérangés ne le remarqueraient pas et essaieraient avec plaisir de le décoder ...: - /

Mais il semble que c # ne l’aime pas (ce qui est une approche valable), donc si le supprimer aide, cela devrait être fait.

Un commentaire supplémentaire mineur: UTF-8 n'est pas une exigence, ISO-8859-x aussi appelé Latin-x et Ascii 7 bits fonctionneraient également. Ceci parce que Base64 a été spécifiquement conçu pour utiliser uniquement un sous-ensemble 7 bits qui fonctionne avec tous les codages compatibles ASCII 7 bits.

3
StaxMan

S'il est impossible de supprimer\0 de la fin d'une chaîne, vous pouvez ajouter votre propre caractère pour chaque chaîne que vous encodez et le supprimer lors du décodage.

0
abatishchev

La conversion de Base64 à partir d'une chaîne est un inconvénient. Certaines fonctions de conversion utilisent les données précédentes: "data: image/jpg; base64", tandis que d'autres acceptent uniquement les données réelles.

0
SteveCav
string stringToDecrypt = HttpContext.Current.Request.QueryString.ToString()

// change en string stringToDecrypt = HttpUtility.UrlDecode (HttpContext.Current.Request.QueryString.ToString ())

0
Uday