So überprüfen Sie, ob eine Zeichenfolge Base64-codiert ist oder nicht

194

Ich möchte eine Base64-codierte Zeichenfolge dekodieren und dann in meiner Datenbank speichern. Wenn die Eingabe nicht Base64-codiert ist, muss ich einen Fehler auslösen.

Wie kann ich überprüfen, ob eine Zeichenfolge Base64-codiert ist?

Loganathan
quelle
Warum? Wie kann die Situation entstehen?
Marquis von Lorne
2
Ohne anzugeben, auf welche Programmiersprache (und / oder welches Betriebssystem) Sie abzielen, ist dies eine sehr offene Frage
bcarroll
5
Sie können lediglich feststellen, dass die Zeichenfolge nur Zeichen enthält, die für eine Base64-codierte Zeichenfolge gültig sind. Es ist möglicherweise nicht möglich festzustellen, dass die Zeichenfolge die Base64-codierte Version einiger Daten ist. Beispiel test1234: Eine gültige Base64-codierte Zeichenfolge. Wenn Sie sie dekodieren, erhalten Sie einige Bytes. Es gibt keine anwendungsunabhängige Schlussfolgerung, dass test1234es sich nicht um eine Base64-codierte Zeichenfolge handelt.
Kinjal Dixit

Antworten:

249

Mit dem folgenden regulären Ausdruck können Sie überprüfen, ob eine Zeichenfolge base64-codiert ist oder nicht:

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

Bei der Base64-Codierung lautet der Zeichensatz [A-Z, a-z, 0-9, and + /]. Wenn die Restlänge weniger als 4 beträgt, wird die Zeichenfolge mit '='Zeichen aufgefüllt .

^([A-Za-z0-9+/]{4})* bedeutet, dass die Zeichenfolge mit 0 oder mehr base64-Gruppen beginnt.

([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$bedeutet , dass die Schnurenden in einer von drei Formen: [A-Za-z0-9+/]{4}, [A-Za-z0-9+/]{3}=oder [A-Za-z0-9+/]{2}==.

xuanyuanzhiyuan
quelle
10
Ich wollte nur überprüfen, bitte helfen Sie bei meiner Frage: Was ist die Garantie, dass sich dieser reguläre Ausdruck immer nur auf den Base64-String bezieht? Wenn eine Zeichenfolge kein Leerzeichen enthält und ein Vielfaches von 4 Zeichen ist, wird diese Zeichenfolge als base64-Zeichenfolge betrachtet.
DShah
3
Dann ist es eine gültige base64-Zeichenfolge, die dekodiert werden kann. Sie können eine Mindestlängenbeschränkung hinzufügen. Anstelle von null oder mehr Wiederholungen von Vierergruppen sind beispielsweise vier oder mehr erforderlich. Es hängt auch von Ihrem Problem ab; Wenn Ihre Benutzer häufig ein einzelnes Wort in einer Sprache mit langen Wörtern und reinem ASCII (Hawaiianisch?) eingeben, ist dies fehleranfälliger als wenn Eingaben ohne Base64 normalerweise Leerzeichen, Interpunktion usw. enthalten
Tripleee
62
Das sagt nur , dass ein Eingang gewesen sein könnte ein b64 codierten Wert, aber nicht sagen , ob der Eingang ist eigentlich ein b64 codierte Wert. Mit anderen Worten, abcdwird übereinstimmen, aber es ist nicht unbedingt der codierte Wert einer einfachen abcdEingabe
Tzury Bar Yochay
3
Ihr regulärer Ausdruck ist falsch, da er nicht mit der leeren Zeichenfolge übereinstimmt. Dies ist die base64-Codierung von Binärdaten mit der Länge Null gemäß RFC 4648.
rötlich
5
@Adomas, "pass" ist ein perfekt gültige Base64 string, daß Decodierungen in die Sequenz von Bytes 0xa5, 0xabund 0x2c. Warum sollten Sie es a priori verwerfen , wenn Sie nicht mehr Kontext zur Entscheidung haben?
Luis Colorado
50

Wenn Sie Java verwenden, können Sie tatsächlich die Commons-Codec- Bibliothek verwenden

import org.apache.commons.codec.binary.Base64;

String stringToBeChecked = "...";
boolean isBase64 = Base64.isArrayByteBase64(stringToBeChecked.getBytes());
zihaoyu
quelle
17
aus der Dokumentation: isArrayByteBase64(byte[] arrayOctet)Veraltet. 1.5 Verwendung isBase64(byte[])wird in 2.0 entfernt.
Avinash R
7
Sie können auch Base64.isBase64 (String base64) verwenden, anstatt es selbst in ein Byte-Array zu konvertieren.
Sasa
5
Basierend auf der Dokumentation: commons.apache.org/proper/commons-codec/apidocs/org/apache/… : " Testet einen bestimmten String, um festzustellen , ob er nur gültige Zeichen im Base64-Alphabet enthält. Derzeit behandelt die Methode Leerzeichen als gültig." Dies bedeutet, dass diese Methode einige falsch positive Ergebnisse wie "Leerzeichen" oder Zahlen ("0", "1") aufweist.
Christian Vielma
für Zeichenfolge Base64.isBase64 (Inhalt)
ema
3
Diese Antwort ist falsch, da sie stringToBeChecked="some plain text"dann festgelegt wird boolean isBase64=true, obwohl es sich nicht um einen Base64-codierten Wert handelt. Lesen Sie die Quelle für Commons-Codec-1.4. Base64.isArrayByteBase64()Sie prüft nur, ob jedes Zeichen in der Zeichenfolge gültig ist, um für die Base64-Codierung berücksichtigt zu werden, und lässt Leerzeichen zu.
Brad
49

Ja, du kannst:

  • Überprüfen Sie, ob die Länge ein Vielfaches von 4 Zeichen ist
  • Überprüfen Sie, ob sich jedes Zeichen in der Menge AZ, az, 0-9, +, / befindet, mit Ausnahme des Auffüllens am Ende, das aus 0, 1 oder 2 '=' Zeichen besteht

Wenn Sie erwarten, dass es sich um base64 handelt, können Sie wahrscheinlich einfach die auf Ihrer Plattform verfügbare Bibliothek verwenden, um zu versuchen , sie in ein Byte-Array zu dekodieren. Wenn dies keine gültige Base 64 ist, wird eine Ausnahme ausgelöst. Dies hängt von Ihrer Plattform ab. natürlich.

Jon Skeet
quelle
Das Parsen unterscheidet sich von der Validierung zumindest dadurch, dass für das decodierte Byte-Array Speicher erforderlich ist. Dies ist in einigen Fällen nicht der effektivste Ansatz.
Victor Yarema
1
@ VictorYarema: Ich habe sowohl einen Nur-Validierungs-Ansatz (Aufzählungspunkte) als auch einen Parsing-Ansatz (nach den Aufzählungspunkten) vorgeschlagen.
Jon Skeet
16

Ab Java 8 können Sie einfach java.util.Base64 verwenden , um zu versuchen, die Zeichenfolge zu dekodieren:

String someString = "...";
Base64.Decoder decoder = Base64.getDecoder();

try {
    decoder.decode(someString);
} catch(IllegalArgumentException iae) {
    // That string wasn't valid.
}
Philippe
quelle
3
Ja, es ist eine Option, aber vergessen Sie nicht, dass der Fang in Java ziemlich teuer ist
Panser
2
Das ist nicht mehr der Fall. Die Ausnahmebehandlung funktioniert ziemlich gut. Sie sollten besser nicht vergessen, dass Java Regex ziemlich langsam ist. Ich meine: WIRKLICH LANGSAM! Es ist tatsächlich schneller, einen Base64 zu dekodieren und zu überprüfen, ob er (nicht) funktioniert, anstatt den String mit dem obigen Regex abzugleichen. Ich habe einen groben Test durchgeführt und der Java Regex-Abgleich ist ungefähr sechsmal langsamer (!!) als das Abfangen einer eventuellen Ausnahme bei der Dekodierung.
Sven Döring
Mit mehr Testläufen ist es tatsächlich elfmal langsamer. Es ist Zeit für eine bessere Regex-Implementierung in Java. Sogar eine Regex-Prüfung mit der Nashorn JavaScript-Engine in Java ist so viel schneller. Unglaublich. Zusätzlich ist JavaScript Regex (mit Nashorn) viel leistungsfähiger.
Sven Döring
3
Mit Java 11 (anstelle von Java 8) ist die Regex-Prüfung sogar 22-mal langsamer. 🤦 (Weil die Base64-Dekodierung schneller wurde.)
Sven Döring
15

Versuchen Sie dies für PHP5

//where $json is some data that can be base64 encoded
$json=some_data;

//this will check whether data is base64 encoded or not
if (base64_decode($json, true) == true)
{          
   echo "base64 encoded";          
}
else 
{
   echo "not base64 encoded"; 
}

Verwenden Sie dies für PHP7

 //$string parameter can be base64 encoded or not

function is_base64_encoded($string){
 //this will check if $string is base64 encoded and return true, if it is.
 if (base64_decode($string, true) !== false){          
   return true;        
 }else{
   return false;
 }
}
Suneel Kumar
quelle
1
Welche Sprache ist das? Die Frage wurde gestellt, ohne sich auf eine Sprache zu beziehen
Ozkan
das wird nicht funktionieren. Lesen Sie die Dokumente Returns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley
1
Wie? Wenn die Eingabe ein externes Zeichen enthält, ist es nicht base64, oder?
Suneel Kumar
6
var base64Rejex = /^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i;
var isBase64Valid = base64Rejex.test(base64Data); // base64Data is the base64 string

if (isBase64Valid) {
    // true if base64 formate
    console.log('It is base64');
} else {
    // false if not in base64 formate
    console.log('it is not in base64');
}
Deepak Sisodiya
quelle
5

Überprüfen Sie , WENN die Länge der Zeichenfolge ist ein Vielfaches von 4 Aftwerwards verwenden diese Regex um sicherzustellen , dass alle Zeichen in der Zeichenfolge sind Base64 - Zeichen.

\A[a-zA-Z\d\/+]+={,2}\z

Wenn die von Ihnen verwendete Bibliothek eine neue Zeile hinzufügt, um die Regel mit maximal 76 Zeichen pro Zeile zu beachten, ersetzen Sie sie durch leere Zeichenfolgen.

Yaw Boakye
quelle
Der erwähnte Link zeigt 404. Bitte überprüfen und aktualisieren.
Ankur
Sorry @AnkurKumar, aber genau das passiert, wenn Leute uncoole URLs haben: Sie ändern sich ständig. Ich habe keine Ahnung, wohin es gezogen ist. Ich hoffe, Sie finden andere nützliche Ressourcen über Google
Yaw Boakye
Sie können immer alte Seiten von web.archive.org erhalten - hier ist die ursprüngliche URL. web.archive.org/web/20120919035911/http://… oder ich habe den Text hier gepostet: gist.github.com/mika76/d09e2b65159e435e7a4cc5b0299c3e84
Mladen Mihajlovic
4

Es gibt viele Varianten von Base64. Stellen Sie also fest, ob Ihre Zeichenfolge der erwarteten Variablen ähnelt . Als solche müssen Sie die Regex unten in Bezug auf den Index und Füllzeichen einzustellen (dh +, /, =).

class String
  def resembles_base64?
    self.length % 4 == 0 && self =~ /^[A-Za-z0-9+\/=]+\Z/
  end
end

Verwendung:

raise 'the string does not resemble Base64' unless my_string.resembles_base64?
user664833
quelle
3

Versuche dies:

public void checkForEncode(String string) {
    String pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
    Pattern r = Pattern.compile(pattern);
    Matcher m = r.matcher(string);
    if (m.find()) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }
}
user5499458
quelle
3

Es ist unmöglich zu überprüfen, ob eine Zeichenfolge base64-codiert ist oder nicht. Es ist nur möglich zu überprüfen, ob diese Zeichenfolge ein Base64-codiertes Zeichenfolgenformat hat. Dies würde bedeuten, dass es sich um eine Zeichenfolge handelt, die durch Base64-Codierung erzeugt wird (um zu überprüfen, ob die Zeichenfolge gegen einen regulären Ausdruck validiert werden kann oder eine Bibliothek verwendet werden kann, können viele verwendet werden Andere Antworten auf diese Frage bieten gute Möglichkeiten, dies zu überprüfen, sodass ich nicht auf Details eingehen werde.

Beispielsweise ist string floweine gültige base64-codierte Zeichenfolge. Es ist jedoch unmöglich zu wissen, ob es sich nur um eine einfache Zeichenfolge, ein englisches Wort flowoder um eine Basis-64-codierte Zeichenfolge handelt~Z0

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

Dieser reguläre Ausdruck hat mir geholfen, die base64 in meiner Anwendung in Rails zu identifizieren. Ich hatte nur ein Problem: Er erkennt die Zeichenfolge "errorDescripcion". Ich generiere einen Fehler, um sie zu lösen. Überprüfen Sie einfach die Länge einer Zeichenfolge.

Onironauta
quelle
Der obige reguläre Ausdruck /^.....$/.match(my_string) gibt einen Formatierungsfehler aus, indem er "
Nicht übereinstimmendes
Und mit 'vorzeitigem Ende der Zeichenklasse: / ^ (([A-Za-z0-9 + /' Syntaxfehler.
james2611nov
Nevermind hat das Problem behoben, indem \ vor jedem / Zeichen \ hinzugefügt wurde.
James2611nov
errorDescriptionist eine gültige base64-Zeichenfolge, die in die binäre Folge von Bytes (in hex) dekodiert : 7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27.
Luis Colorado
Es hat perfekt funktioniert, um die Base64-codierte Zeichenfolge zu überprüfen.
Deepak Lakhara
1

Dies funktioniert in Python:

import base64

def IsBase64(str):
    try:
        base64.b64decode(str)
        return True
    except Exception as e:
        return False

if IsBase64("ABC"):
    print("ABC is Base64-encoded and its result after decoding is: " + str(base64.b64decode("ABC")).replace("b'", "").replace("'", ""))
else:
    print("ABC is NOT Base64-encoded.")

if IsBase64("QUJD"):
    print("QUJD is Base64-encoded and its result after decoding is: " + str(base64.b64decode("QUJD")).replace("b'", "").replace("'", ""))
else:
    print("QUJD is NOT Base64-encoded.")

Zusammenfassung: IsBase64("string here") Gibt true zurück , wenn string hereBase64-codiert ist, und false, wenn string hereNICHT Base64-codiert ist.

gab
quelle
1

C # Das ist großartig:

static readonly Regex _base64RegexPattern = new Regex(BASE64_REGEX_STRING, RegexOptions.Compiled);

private const String BASE64_REGEX_STRING = @"^[a-zA-Z0-9\+/]*={0,3}$";

private static bool IsBase64(this String base64String)
{
    var rs = (!string.IsNullOrEmpty(base64String) && !string.IsNullOrWhiteSpace(base64String) && base64String.Length != 0 && base64String.Length % 4 == 0 && !base64String.Contains(" ") && !base64String.Contains("\t") && !base64String.Contains("\r") && !base64String.Contains("\n")) && (base64String.Length % 4 == 0 && _base64RegexPattern.Match(base64String, 0).Success);
    return rs;
}
Veni Souto
quelle
1
Console.WriteLine("test".IsBase64()); // true
Langdon
2
Die Empfehlung, die Programmiersprache zu wechseln, um ein Problem zu lösen, ist im Allgemeinen keine gültige Antwort.
Luis Colorado
0

Es gibt keine Möglichkeit, Zeichenfolge und Base64-Codierung zu unterscheiden, es sei denn, die Zeichenfolge in Ihrem System weist eine bestimmte Einschränkung oder Identifikation auf.

Pinxue
quelle
0

Dieses Snippet kann nützlich sein, wenn Sie die Länge des ursprünglichen Inhalts kennen (z. B. eine Prüfsumme). Es wird überprüft, ob das codierte Formular die richtige Länge hat.

public static boolean isValidBase64( final int initialLength, final String string ) {
  final int padding ;
  final String regexEnd ;
  switch( ( initialLength ) % 3 ) {
    case 1 :
      padding = 2 ;
      regexEnd = "==" ;
      break ;
    case 2 :
      padding = 1 ;
      regexEnd = "=" ;
      break ;
    default :
      padding = 0 ;
      regexEnd = "" ;
  }
  final int encodedLength = ( ( ( initialLength / 3 ) + ( padding > 0 ? 1 : 0 ) ) * 4 ) ;
  final String regex = "[a-zA-Z0-9/\\+]{" + ( encodedLength - padding ) + "}" + regexEnd ;
  return Pattern.compile( regex ).matcher( string ).matches() ;
}
Laurent Caillette
quelle
0

Wenn die RegEx nicht funktioniert und Sie den Formatstil der ursprünglichen Zeichenfolge kennen, können Sie die Logik umkehren, indem Sie für dieses Format eine Regexing durchführen.

Zum Beispiel arbeite ich mit Base64-codierten XML-Dateien und überprüfe nur, ob die Datei ein gültiges XML-Markup enthält. Wenn nicht, kann ich davon ausgehen, dass es base64 dekodiert ist. Dies ist nicht sehr dynamisch, funktioniert aber gut für meine kleine Anwendung.

Jankapunkt
quelle
0

Dies funktioniert in Python:

def is_base64(string):
    if len(string) % 4 == 0 and re.test('^[A-Za-z0-9+\/=]+\Z', string):
        return(True)
    else:
        return(False)
bcarroll
quelle
0

Versuchen Sie dies mit einem zuvor erwähnten regulären Ausdruck:

String regex = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
if("TXkgdGVzdCBzdHJpbmc/".matches(regex)){
    System.out.println("it's a Base64");
}

... Wir können auch eine einfache Validierung durchführen, z. B. wenn Leerzeichen vorhanden sind, kann es sich nicht um Base64 handeln:

String myString = "Hello World";
 if(myString.contains(" ")){
   System.out.println("Not B64");
 }else{
    System.out.println("Could be B64 encoded, since it has no spaces");
 }
Marco
quelle
Ok, könnten Sie dann bitte eine Lösung geben?
Marco
0

Wenn beim Dekodieren eine Zeichenfolge mit ASCII-Zeichen angezeigt wird, wurde die Zeichenfolge nicht codiert

(RoR) Rubinlösung:

def encoded?(str)
  Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count.zero?
end

def decoded?(str)
  Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count > 0
end
Игорь Хлебников
quelle
0

Ich versuche das zu benutzen, ja das hier funktioniert

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

aber ich habe die Bedingung hinzugefügt, um zu überprüfen, ob mindestens das Ende des Zeichens = ist

string.lastIndexOf("=") >= 0
Ashadi Sedana Pratama
quelle
Warum prüfen auf =: Welche Spezifikation verwenden Base64Sie? Was end of the characterbedeutet und wie lastIndexOf()überprüft das nicht negativ ?
Graubart