RegEx pour analyser ou valider les données de Base64
est-il possible d'utiliser un RegEx pour valider ou épurer les données de Base64? C'est la question simple, mais les facteurs qui poussent cette question sont ce qui la rend difficile.
j'ai un décodeur Base64 qui ne peut pas entièrement compter sur les données d'entrée pour suivre les spécifications RFC. Donc, les problèmes auxquels je fais face sont des problèmes comme peut-être Base64 données qui ne peuvent pas être décomposées en 78 (je pense que c'est 78, je devrais revérifier le RFC, alors ne me sonnez pas si le le nombre exact est erroné) des lignes de caractères, ou que les lignes ne peuvent pas se terminer dans CRLF; en ce qu'il peut avoir seulement un CR, ou LF, ou peut-être ni l'un ni l'autre.
donc, j'ai eu un enfer d'un temps parsing Base64 données formatées en tant que tel. De ce fait, des exemples comme celui-ci deviennent impossibles à décoder de manière fiable. Je n'afficherai que des en-têtes MIME partiels par souci de brièveté.
Content-Transfer-Encoding: base64
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
Ok, donc l'analyse n'est pas un problème, et est exactement le résultat que nous attendons. Et dans 99% des cas, en utilisant n'importe quel code pour au moins vérifier que chaque char dans le buffer est un char de base64 valide, fonctionne parfaitement. Mais, l'exemple suivant jette une clé dans le mélange.
Content-Transfer-Encoding: base64
http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
c'est une version de Base64 encoding que j'ai vu dans certains virus et autres choses qui tentent de profiter de certains lecteurs de courrier désir de parser mime à tout prix, par rapport à ceux qui vont strictement selon le livre, ou plutôt RFC; si vous voulez.
Ma Base64 le décodeur décode le second exemple dans le flux de données suivant. Et gardez à l'esprit ici, le flux original est toutes les données ASCII!
[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8
quelqu'un a une bonne façon de résoudre deux problèmes à la fois? Je ne suis pas sûr que ce soit même possible, en dehors de faire deux transformations sur les données avec différentes règles appliquées, et comparer les résultats. Cependant, si vous avez adopté cette approche, à quel résultat croyez-vous? Il semble que L'heuristique ASCII est sur le meilleur solution, mais combien plus de code, de temps d'exécution et de complexité est-ce que cela ajouterait à quelque chose d'aussi compliqué qu'un scanner de virus, dans lequel ce code est réellement impliqué? Comment former le moteur heuristique pour apprendre ce qui est acceptable comme Base64, et ce qui ne l'est pas?
mise à jour:
faire au nombre de vues cette question continue d'obtenir, j'ai décidé de poster le RegEx simple que J'utilise une application C# depuis 3 ans maintenant, avec des centaines de milliers de transactions. Honnêtement, j'aime la réponse donnée par Gumbo la meilleure, qui est pourquoi je l'ai choisi comme réponse choisie. Mais pour n'importe qui utilisant C#, et cherchant un moyen très rapide pour au moins détecter si une chaîne, ou byte[] contient des données de Base64 valides ou non, j'ai trouvé le suivant pour travailler très bien pour moi.
[^-A-Za-z0-9+/=]|=[^=]|={3,}$
Et oui, c'est juste pour un CHAÎNE de données Base64, PAS correctement formaté RFC1341 message. Donc, si vous avez affaire à des données de ce type, veuillez en tenir compte avant de tenter d'utiliser le RegEx ci-dessus. Si vous avez affaire à Base16, Base32, Radix ou même Base64 à d'autres fins (URLs, noms de fichiers, encodage XML, etc.), puis il est highly recommander que vous lisez RFC4648 que Gumbo mentionné dans sa réponse que vous devez être bien conscient du jeu de caractères et des terminateurs utilisés par la mise en œuvre avant d'essayer d'utiliser les suggestions dans cet ensemble de questions/réponses.
4 réponses
From the RFC 4648 :
encodage de Base de données est utilisé dans de nombreuses situations pour stocker ou transférer des données dans des environnements qui, peut-être pour des raisons d'héritage, sont limités aux données US-ASCII.
cela dépend donc de la finalité de l'utilisation des données codées si les données doivent être considérées comme dangereuses.
mais si vous cherchez juste une expression régulière pour correspondre Base64 mots encodés, vous pouvez utiliser ce qui suit:
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$
C'est bon, mais correspond à une Chaîne vide (
celui-ci ne correspond pas à une chaîne vide:
^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$
Ni " : " ni " . " apparaîtra dans valid Base64, donc je pense que vous pouvez jeter sans ambiguïté la ligne http://www.stackoverflow.com
. En Perl, dire quelque chose comme
my $sanitized_str = join q{}, grep {!/[^A-Za-z0-9+\/=]/} split /\n/, $str;
say decode_base64($sanitized_str);
pourrait être ce que vous voulez. Elle produit 151970920"
C'est simple ASCII Base64 pour StackOverflow exemple.
Le meilleur regexp que j'ai pu trouver jusqu'à maintenant, c'est ici https://www.npmjs.com/package/base64-regex
qui est dans la version actuelle ressemble à:
module.exports = function (opts) {
opts = opts || {};
var regex = '(?:[A-Za-z0-9+\/]{4}\n?)*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=)';
return opts.exact ? new RegExp('(?:^' + regex + '$)') :
new RegExp('(?:^|\s)' + regex, 'g');
};