Question

Est-il possible d'utiliser un RegEx pour valider ou nettoyer les données Base64? C’est une question simple, mais ce sont les facteurs qui déterminent cette question 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 suis confronté sont des problèmes tels que peut-être les données Base64 qui pourraient ne pas être divisées en 78 (je pense que c'est 78, il faudrait que je vérifie la RFC, alors ne me laissez pas tomber si le nombre exact est erroné) lignes, ou que les lignes ne peuvent pas se terminer par CRLF; en ce sens qu'il peut ne contenir qu'un CR, ou un FL, ou peut-être ni l'un ni l'autre.

J'ai donc passé un sacré moment à analyser des données Base64 formatées comme telles. Pour cette raison, des exemples comme ceux-ci deviennent impossibles à décoder de manière fiable. Je n’afficherai que les en-têtes MIME partiels par souci de concision.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

D'accord, l'analyse ne pose donc pas de problème et correspond exactement au résultat auquel nous nous attendions. Et dans 99% des cas, utiliser n'importe quel code pour vérifier au moins que chaque caractère du tampon est un caractère base64 valide fonctionne parfaitement. Mais, l'exemple suivant jette une clé dans le mélange.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Il s’agit d’une version de l’encodage Base64 que j’ai vu dans certains virus et autres éléments qui tente de tirer parti du désir de certains lecteurs de messagerie d’analyser le mime à tout prix, par opposition à ceux strictement à la livre ou plutôt à la RFC; si vous voulez.

Mon décodeur Base64 décode le deuxième exemple du flux de données suivant. Et gardez à l’esprit ici, le flux original contient toutes les données ASCII!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

Quelqu'un at-il un bon moyen de résoudre les deux problèmes à la fois? Je ne suis pas sûr que ce soit même possible, à part de faire deux transformations sur les données avec des règles différentes appliquées et de comparer les résultats. Cependant, si vous avez choisi cette approche, en quelle production faites-vous confiance? Il semble que l'heuristique ASCII constitue la meilleure solution, mais combien de code, de temps d'exécution et de complexité cela ajouterait-il à quelque chose d'aussi compliqué qu'un antivirus, dans lequel ce code est réellement impliqué? Comment formeriez-vous le moteur heuristique pour savoir ce qui est acceptable en Base64 et ce qui ne l’est pas?

UPDATE:

En ce qui concerne le nombre de vues que cette question continue de recevoir, j’ai décidé d’afficher le simple RegEx que j’utilise dans une application C # depuis 3 ans maintenant, avec des centaines de milliers de transactions. Honnêtement, j'aime bien la réponse donnée par Gumbo le meilleur, c'est pourquoi je l'ai choisi comme réponse sélectionnée. Mais pour tous ceux qui utilisent C # et recherchent un moyen très rapide de détecter au moins si une chaîne ou un octet [] contient des données Base64 valides ou non, j’ai trouvé que les éléments suivants fonctionnaient très bien pour moi.

[^-A-Za-z0-9+/=]|=[^=]|={3,}$

Et oui, cela concerne uniquement une chaîne de données Base64, PAS un RFC1341 . Donc, si vous traitez avec des données de ce type, veuillez en tenir compte avant d'essayer d'utiliser le RegEx ci-dessus. Si vous utilisez Base16, Base32, Radix ou même Base64 à d’autres fins (URL, noms de fichier, codage XML, etc.), il est fortement recommandé de lire RFC4648 que Gumbo a été mentionné dans sa réponse car vous devez bien connaître le jeu de caractères et les terminateurs utilisés par la mise en œuvre avant de tenter d'utiliser les suggestions de cet ensemble de questions / réponses.

Était-ce utile?

La solution

Extrait de la RFC 4648 :

  

Le codage de base des 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 héritées du passé, sont limités aux données US-ASCII.

Cela dépend donc du but d'utilisation des données codées si celles-ci doivent être considérées comme dangereuses.

Si vous souhaitez simplement rechercher une expression régulière correspondant aux mots codés en Base64, vous pouvez utiliser les éléments suivants:

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

Autres conseils

^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$

Celui-ci est bon, mais correspondra à 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 un ": " ni un ". " apparaîtra dans Base64 valide, donc je pense que vous pouvez clairement supprimer la ligne http://www.stackoverflow.com . En Perl, disons 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. Il produit

Il s’agit d’un simple ASCII Base64 pour StackOverflow, exemple.

La meilleure expression rationnelle que j'ai pu trouver jusqu'à présent est ici https://www.npmjs.com/package/base64-regex

qui se trouve 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');
};
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top