Frage

Ist es möglich, eine RegEx zu verwenden, um zu validieren, oder Base64 Daten sanieren? Das ist die einfache Frage, aber die Faktoren, die diese Frage antreiben werden, was es schwierig machen.

Ich habe einen Base64 Decoder, die nicht vollständig auf den Eingangsdaten verlassen können den RFC-Spezifikationen zu folgen. So sind die Fragen, die ich konfrontiert sind Themen wie vielleicht Base64 Daten, die nicht in 78 aufgebrochen werden kann (ich glaube, es 78 ist, muss ich würde das Doppelte der RFC überprüfen, so tun ding mich nicht, wenn die genaue Zahl falsch ist) Zeichen Linien, oder daß die Zeilen in CRLF nicht beenden; dadurch kann es nur einen CR oder LF hat, oder vielleicht auch nicht.

Also, ich habe eine Hölle einer Zeit Parsen Base64 Daten als solche formatiert hatte. Aufgrund dieser Tatsache Beispiele wie das unmöglich werden folgende zuverlässig zu entschlüsseln. Ich werde nur teilweise MIME-Header der Kürze angezeigt werden soll.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Ok, so dass das Parsen ist kein Problem, und ist genau das Ergebnis, das wir erwarten. Und in 99% der Fälle von Code unter Verwendung von zumindest zu überprüfen, ob jeder char in dem Puffer ist ein gültiges base64 char, funktioniert perfekt. Aber das nächste Beispiel wirft einen Schraubenschlüssel in die Mischung.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Dies ist eine Version von Base64-Codierung, die ich in einigen Viren und andere Dinge gesehen haben, die die Vorteile von einigen Mail-Leser Mime mit allen Mitteln analysieren wollen nehmen versuchen, im Vergleich zu denen, die streng durch das Buch gehen, oder besser gesagt RFC; wenn du möchtest.

My Base64-Decoder decodiert das zweite Beispiel auf den folgenden Datenstrom. Und hier im Auge behalten, der ursprüngliche Strom ist alle ASCII-Daten!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

Wer eine gute Möglichkeit, beide Probleme auf einmal zu lösen? Ich bin mir nicht sicher, es ist sogar möglich, außerhalb mit unterschiedlichen Regeln angewandt zwei Transformationen auf die Daten zu tun, und die Ergebnisse zu vergleichen. Allerdings, wenn Sie diesen Ansatz nehmen, welche Ausgabe vertrauen Sie? Es scheint, dass ASCII-Heuristik ist über die am besten Lösung, aber wie viel mehr Code, Ausführungszeit und Komplexität würde, dass etwas hinzufügen, als Virenscanners kompliziert, die dieser Code tatsächlich beteiligt ist? Wie würden Sie die Heuristik-Engine trainieren zu lernen, was akzeptabel Base64 ist, und was nicht?


UPDATE:

Sie auf die Anzahl der Ansichten, diese Frage zu erhalten bleibt, habe ich beschlossen, die einfache RegEx zu schreiben, die ich für 3 Jahre in einer C # Anwendung jetzt mit Hunderttausenden von Transaktionen habe. Ehrlich gesagt, ich mag die Antwort von Gumbo die besten, weshalb ich es als die aufgenommenen Antwort an. Aber für jeden C #, und suchen nach einem sehr schnellen Weg, um zumindest zu erkennen, ob ein String oder byte [] enthält gültige Base64-Daten oder nicht, habe ich folgendes arbeiten sehr gut für mich gefunden.

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

Und ja, das ist nur für ein STRING von Base64-Daten, nicht ein richtig formatierte RFC1341 Nachricht. Also, wenn Sie mit Daten dieser Art zu tun haben, nehmen Sie bitte, dass zu berücksichtigen, bevor Sie die oben RegEx zu verwenden. Wenn Sie mit Base16, Base32, Radix oder sogar Base64 für andere Zwecke (URLs, Dateinamen, XML Encoding, etc.) zu tun haben, dann ist es hoch wird empfohlen, ein href lesen <= "http : //tools.ietf.org/html/rfc4648" rel = "noreferrer" title = "RFC4648"> RFC4648 , die a href <= "https://stackoverflow.com/users/53114/gumbo/" title = „Gumbo“> Gumbo in seiner Antwort erwähnt, wie Sie auch des charset bewusst sein müssen und durch die Implementierung verwendeten Terminator, bevor die Vorschläge in dieser Frage / Antwort-Satz zu verwenden.

War es hilfreich?

Lösung

Von der RFC 4648 :

  

Basis-Codierung von Daten ist in vielen Situationen zum Speichern oder Übertragen von Daten in Umgebungen, die vielleicht für Legacy-Gründen beschränkt sind auf US-ASCII-Daten.

So ist es auf dem Zweck der Nutzung der codierten Daten abhängig, ob die Daten sollten als gefährlich betrachtet werden.

Wenn Sie aber nur für einen regulären Ausdruck suchen Base64 codiert Worte übereinstimmen, können Sie die folgenden Befehle verwenden:

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

Andere Tipps

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

Dieses ist gut, aber einen leeren String passen

Dieses nicht leere Zeichenkette übereinstimmen:

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

Weder ein ": " " ", noch eine in gültiger Base64 zeigen, so dass ich glaube, Sie eindeutig die http://www.stackoverflow.com Linie wegwerfen kann. In Perl, sagen wir, so etwas wie

my $sanitized_str = join q{}, grep {!/[^A-Za-z0-9+\/=]/} split /\n/, $str;

say decode_base64($sanitized_str);

könnte sein, was Sie wollen. Es produziert

Das ist einfach ASCII Base64 für Stackoverflow exmaple.

Die beste regexp die ich finden konnte bis jetzt hier ist https://www.npmjs.com/package/base64-regex

, die in der aktuellen Version ist wie folgt aussieht:

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');
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top