134 Stimmen

RegEx zum Parsen oder Validieren von Base64-Daten

Ist es möglich, ein RegEx zu verwenden, um Base64-Daten zu validieren oder zu bereinigen? Das ist die einfache Frage, aber die Faktoren, die diese Frage antreiben, machen sie schwierig.

Ich habe einen Base64-Decoder, der sich nicht vollständig darauf verlassen kann, dass die Eingabedaten den RFC-Spezifikationen entsprechen. Die Probleme, mit denen ich konfrontiert bin, sind also Probleme wie z. B. Base64-Daten, die möglicherweise nicht in 78 (ich glaube, es sind 78, ich müsste den RFC noch einmal überprüfen, also bitte nicht meckern, wenn die genaue Zahl falsch ist) Zeichenzeilen aufgeteilt sind, oder dass die Zeilen möglicherweise nicht mit CRLF enden, sondern nur ein CR oder LF oder vielleicht keines von beiden enthalten.

Ich hatte also verdammt viel Mühe mit dem Parsen von Base64-Daten, die als solche formatiert sind. Aus diesem Grund sind Beispiele wie die folgenden nicht mehr zuverlässig zu entschlüsseln. Der Kürze halber werde ich nur einen Teil der MIME-Header anzeigen.

Content-Transfer-Encoding: base64

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Das zu analysieren ist also kein Problem und entspricht genau dem Ergebnis, das wir erwarten würden. Und in 99 % der Fälle funktioniert die Verwendung eines Codes, der zumindest überprüft, ob jedes Zeichen im Puffer ein gültiges base64-Zeichen ist, perfekt. Aber das nächste Beispiel wirft einen Schraubenschlüssel in den Mix.

Content-Transfer-Encoding: base64

http://www.stackoverflow.com
VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu

Dies ist eine Version der Base64-Kodierung, die ich in einigen Viren und anderen Dingen gesehen habe, die versuchen, den Wunsch einiger E-Mail-Leser auszunutzen, Mime um jeden Preis zu parsen, im Gegensatz zu denen, die sich strikt an das Buch oder besser gesagt RFC halten.

Mein Base64-Decoder dekodiert das zweite Beispiel in den folgenden Datenstrom. Und denken Sie daran, dass der ursprüngliche Datenstrom ausschließlich aus ASCII-Daten besteht!

[0x]86DB69FFFC30C2CB5A724A2F7AB7E5A307289951A1A5CC81A5CC81CDA5B5C1B19481054D0D
2524810985CD94D8D08199BDC8814DD1858DAD3DD995C999B1BDDC8195E1B585C1B194B8

Hat jemand eine gute Idee, wie man beide Probleme auf einmal lösen kann? Ich bin mir nicht sicher, ob es überhaupt möglich ist, abgesehen davon, dass man zwei Transformationen mit unterschiedlichen Regeln auf die Daten anwenden und die Ergebnisse vergleichen kann. Aber wenn Sie diesen Ansatz wählen, welchem Ergebnis vertrauen Sie dann? Es scheint, dass die ASCII-Heuristik etwa die am besten Lösung, aber wie viel mehr Code, Ausführungszeit und Komplexität würde das zu etwas so Kompliziertem wie einem Virenscanner hinzufügen, an dem dieser Code tatsächlich beteiligt ist? Wie würden Sie die Heuristik trainieren, damit sie lernt, was für Base64 akzeptabel ist und was nicht?


UPDATE:

Da diese Frage immer wieder gestellt wird, habe ich beschlossen, das einfache RegEx zu veröffentlichen, das ich seit 3 Jahren in einer C#-Anwendung mit Hunderttausenden von Transaktionen verwende. Ehrlich gesagt, gefällt mir die Antwort von Gumbo die beste, weshalb ich sie auch als Antwort ausgewählt habe. Aber jeder mit C#, und auf der Suche nach einer sehr schnellen Weg, um zumindest zu erkennen, ob eine Zeichenfolge oder byte[] enthält gültige Base64-Daten oder nicht, ich habe die folgenden sehr gut für mich arbeiten gefunden.

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

Und ja, das ist nur für eine STRING von Base64-Daten, NICHT eine richtig formatierte RFC1341 Nachricht. Wenn Sie also mit Daten dieses Typs zu tun haben, sollten Sie dies berücksichtigen, bevor Sie versuchen, das obige RegEx zu verwenden. Wenn Sie mit Base16, Base32, Radix oder sogar Base64 für andere Zwecke arbeiten (URLs, Dateinamen, XML-Kodierung usw.), dann ist es sehr empfehlen, dass Sie lesen RFC4648 dass Gumbo in seiner Antwort erwähnt, da Sie sich über den Zeichensatz und die Terminatoren, die von der Implementierung verwendet werden, im Klaren sein müssen, bevor Sie versuchen, die Vorschläge in diesem Frage/Antwort-Set zu verwenden.

0 Stimmen

Ich denke, dass man die Aufgabe besser definieren muss. Es ist völlig unklar, was Ihr Ziel ist: streng sein? 100% der Proben analysieren? ...

0 Stimmen

Ihr erstes Beispiel sollte 'VGhpcyBpcyBhIHNpbXBsZSBBU0NJSSBCYXNlNjQgZXhhbXBsZSBmb3IgU3RhY2tPdmVyZmxvdy4=' lauten.

1 Stimmen

Warum verwenden Sie nicht eine Standardlösung in Ihrer Sprache? Warum brauchen Sie einen handgeschriebenen Parser auf der Grundlage von Regexen?

5voto

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

die in der aktuellen Version 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');
};

5voto

Jayani Sumudini Punkte 1282

Zur Validierung base64-Bild können wir diese Regex verwenden

/^data:image/(?:gif|png|jpeg|bmp|webp)(?:;charset=utf-8)?;base64,(?:[A-Za-z0-9]|[+/])+={0,2}

  private validBase64Image(base64Image: string): boolean {
    const regex = /^data:image\/(?:gif|png|jpeg|bmp|webp|svg\+xml)(?:;charset=utf-8)?;base64,(?:[A-Za-z0-9]|[+/])+={0,2}/;
    return base64Image && regex.test(base64Image);
  }

5voto

Paul M Punkte 51

Die kürzeste Regex zur Überprüfung der RFC-4648-Konformität unter Einhaltung der kanonischen Kodierung (d.h. alle Pad-Bits auf 0 gesetzt):

^(?=(.{4})*$)[A-Za-z0-9+/]*([AQgw]==|[AEIMQUYcgkosw048]=)?$

Eigentlich ist dies die Mischung aus este y dass Antworten.

1voto

Teodor Punkte 53

I gefunden eine Lösung, die sehr gut funktioniert

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

Er passt auf die folgenden Zeichenfolgen

VGhpcyBpcyBzaW1wbGUgQVNDSUkgQmFzZTY0IGZvciBTdGFja092ZXJmbG93IGV4YW1wbGUu
YW55IGNhcm5hbCBwbGVhcw==
YW55IGNhcm5hbCBwbGVhc3U=
YW55IGNhcm5hbCBwbGVhc3Vy

während sie mit keiner dieser ungültigen

YW5@IGNhcm5hbCBwbGVhcw==
YW55IGNhc=5hbCBwbGVhcw==
YW55%%%%IGNhcm5hbCBwbGVhc3V
YW55IGNhcm5hbCBwbGVhc3
YW55IGNhcm5hbCBwbGVhc
YW***55IGNhcm5hbCBwbGVh=
YW55IGNhcm5hbCBwbGVhc==
YW55IGNhcm5hbCBwbGVhc===

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X