176 votes

Comment vérifier si une chaîne encodée en Base 64 est valide en C #

Est-il possible en C# pour voir si une chaîne est codé en Base 64 autres que juste essayer de le convertir et de voir si il y a une erreur? J'ai le code comme ceci:

// Convert base64-encoded hash value into a byte array.
byte[] HashBytes = Convert.FromBase64String(Value);

Je veux éviter le "caractère Invalide dans le Base-64 string" exception qui se produit si la valeur n'est pas valide en base 64 de la chaîne. Je veux juste vérifier et retourner false au lieu de traiter une exception parce que je suppose que, parfois, cette valeur ne va pas être une base de 64 chaîne. Est-il possible de vérifier avant d'utiliser le Convertir.FromBase64String fonction?

Merci!

Mise à jour:
Merci pour toutes vos réponses. Ici est une extension de la méthode, vous pouvez tous les utiliser jusqu'à présent, il semble assurez-vous que votre chaîne ne passe Convertir.FromBase64String sans exception. .NET semble tout ignorer de fuite et de fin des espaces lors de la conversion en base 64 donc "1234" est valide et donc est " 1234 "

public static bool IsBase64String(this string s)
{
    s = s.Trim();
    return (s.Length % 4 == 0) && Regex.IsMatch(s, @"^[a-zA-Z0-9\+/]*={0,3}$", RegexOptions.None);

}

Pour ceux qui s'interrogent sur la performance des tests vs attraper une exception, dans la plupart des cas pour cette base 64 chose, c'est plus rapide pour vérifier que d'attraper l'exception jusqu'à ce que vous atteindre une certaine longueur. Plus la longueur de la plus rapide, il est

Dans ma très scientifique, les essais: Pour 10000 itérations pour la longueur de caractère de 100 000 110000 il était 2,7 fois plus rapide à tester d'abord.

Pour 1000 itérations pour les caractères de longueur 1 - 16 caractères pour un total de 16 000 tests qu'il était de 10,9 fois plus rapide.

Je suis sûr qu'il ya un point où il devient de plus en plus à test, à l'exception base de la méthode. Je ne sais pas à quelle point c'est tout.

56voto

Anirudh Ramanathan Points 25113

Il est assez facile de reconnaître une chaîne Base64, car elle ne sera composée que de caractères 'A'..'Z', 'a'..'z', '0'..'9', '+', '/' et elle est souvent complétée à la fin par trois "=" au maximum, pour que la longueur soit un multiple de 4. Mais au lieu de les comparer, vous feriez mieux d'ignorer l'exception, si cela se produit.

49voto

Pathachiever11 Points 679

Je sais que vous avez dit que vous ne vouliez pas attraper une exception. Mais, comme attraper une exception est plus fiable, je vais aller de l'avant et poster cette réponse.

 public static bool IsBase64(this string base64String) {
     if(base64String.Replace(" ","").Length % 4 != 0) {
         return false;
     }

     try{
         Convert.FromBase64String(base64String);
         return true;
     }
     catch(Exception exception){
     // Handle the exception
     }
     return false;
}
 

10voto

Oybek Points 2861

Par souci d’exhaustivité, je souhaite vous donner une idée de la mise en œuvre. En règle générale, Regex est une approche coûteuse, en particulier si la chaîne est volumineuse (ce qui se produit lors du transfert de fichiers volumineux). L’approche suivante essaie d’abord les méthodes de détection les plus rapides.

 public static class HelperExtensions {
    // Characters that are used in base64 strings.
    private static Char[] Base64Chars = new[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
    /// <summary>
    /// Extension method to test whether the value is a base64 string
    /// </summary>
    /// <param name="value">Value to test</param>
    /// <returns>Boolean value, true if the string is base64, otherwise false</returns>
    public static Boolean IsBase64String(this String value) {

        // The quickest test. If the value is null or is equal to 0 it is not base64
        // Base64 string's length is always divisible by four, i.e. 8, 16, 20 etc. 
        // If it is not you can return false. Quite effective
        // Further, if it meets the above criterias, then test for spaces.
        // If it contains spaces, it is not base64
        if (value == null || value.Length == 0 || value.Length % 4 != 0
            || value.Contains(' ') || value.Contains('\t') || value.Contains('\r') || value.Contains('\n'))
            return false;

        // 98% of all non base64 values are invalidated by this time.
        var index = value.Length - 1;

        // if there is padding step back
        if (value[index] == '=')
            index--;

        // if there are two padding chars step back a second time
        if (value[index] == '=')
            index--;

        // Now traverse over characters
        // You should note that I'm not creating any copy of the existing strings, 
        // assuming that they may be quite large
        for (var i = 0; i <= index; i++) 
            // If any of the character is not from the allowed list
            if (!Base64Chars.Contains(value[i]))
                // return false
                return false;

        // If we got here, then the value is a valid base64 string
        return true;
    }
}
 

6voto

Tyler Eaves Points 5758

Pourquoi ne pas attraper l'exception et renvoyer False?

Cela évite des frais généraux supplémentaires dans le cas courant.

6voto

Roland Points 323

La réponse doit s'appuyer sur l'utilisation de la chaîne. Il y a beaucoup de chaînes qui peuvent être "valide base64", selon la syntaxe proposée par plusieurs affiches, mais qui peut "correctement" décoder, sans exception, à l'état de déchet. Exemple: le 8char chaîne Portland est valable en Base64. Quel est le point de dire que c'est valable Base64? Je suppose qu'à un certain point, vous voulez savoir que cette chaîne devrait ou ne devrait pas être en Base64 décodé.

Dans mon cas, j'ai Oracle chaînes de connexion qui peut être en texte brut comme:

Data source=mydb/DBNAME;User Id=Roland;Password=.....`

ou en base64 comme

VXNlciBJZD1sa.....................................==

J'ai juste à vérifier la présence d'un point-virgule, parce que cela prouve qu'il n'est PAS base64, ce qui est évidemment plus rapide que n'importe quelle méthode ci-dessus.

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