Come verificare se una stringa è codificata Base64 oppure no


195

Voglio decodificare una stringa codificata Base64, quindi memorizzarla nel mio database. Se l'input non è codificato Base64, devo generare un errore.

Come posso verificare se una stringa è codificata Base64?


Perché? Come può sorgere la situazione?
Marchese di Lorne,

2
senza specificare quale linguaggio di programmazione (e / o) sistema operativo stai
prendendo di

5
Tutto quello che puoi determinare è che la stringa contiene solo caratteri validi per una stringa codificata in base64. Potrebbe non essere possibile determinare che la stringa sia la versione codificata in base64 di alcuni dati. per esempio test1234è una stringa codificata in base64 valida e quando la decodifichi otterrai alcuni byte. Non esiste un modo indipendente dall'applicazione per concludere che test1234non sia una stringa codificata in base64.
Kinjal Dixit,

Risposte:


249

È possibile utilizzare la seguente espressione regolare per verificare se una stringa è codificata base64 o meno:

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

Nella codifica base64, il set di caratteri è [A-Z, a-z, 0-9, and + /]. Se la lunghezza del resto è inferiore a 4, la stringa è riempita con '='caratteri.

^([A-Za-z0-9+/]{4})* indica che la stringa inizia con 0 o più gruppi base64.

([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$intendono le estremità delle corde in una delle tre forme: [A-Za-z0-9+/]{4}, [A-Za-z0-9+/]{3}=o [A-Za-z0-9+/]{2}==.


10
Volevo solo verificare quindi per favore aiutatemi con la mia domanda: qual è la garanzia che questo regex si riferirà sempre solo alla stringa base64 ?? Se c'è una stringa che non ha spazio ed è multipla di 4 caratteri, allora quella stringa sarà considerata come stringa base64 ????
DShah,

3
Quindi è una stringa base64 valida che può essere decodificata. È possibile aggiungere un vincolo di lunghezza minima; per esempio, invece di zero o più ripetizioni di gruppi di quattro, richiedono (diciamo) quattro o più. Dipende anche dal tuo problema; se i tuoi utenti inseriscono spesso una sola parola in una lingua con parole lunghe e ASCII puro (hawaiano?) è più soggetto a errori rispetto a se l'input non base64 in genere contiene spazi, punteggiatura, ecc.
tripleee

62
Questo indica solo che un input avrebbe potuto essere un valore codificato b64, ma non indica se l'input sia effettivamente un valore codificato b64. In altre parole, abcdcorrisponderà, ma non rappresenta necessariamente il valore codificato di un semplice abcdinput
Tzury Bar Yochay,

3
Il tuo regexp non è corretto, poiché non corrisponde alla stringa vuota, con è la codifica base64 dei dati binari di lunghezza zero secondo RFC 4648.
rossastro

5
@Adomas, "pass" è una stringa base64 perfettamente valido, che decodifica nella sequenza di byte 0xa5, 0xabe 0x2c. Perché scartarlo a priori , se non hai più contesto da decidere?
Luis Colorado,

52

Se stai usando Java, puoi effettivamente usare la libreria commons-codec

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

String stringToBeChecked = "...";
boolean isBase64 = Base64.isArrayByteBase64(stringToBeChecked.getBytes());

18
dalla documentazione: isArrayByteBase64(byte[] arrayOctet)obsoleto. 1.5 Utilizzo isBase64(byte[]), verrà rimosso in 2.0.
Avinash R

7
Puoi anche usare Base64.isBase64 (String base64) invece di convertirlo da solo in array di byte.
Sasa,

5
Purtroppo, in base alla documentazione: commons.apache.org/proper/commons-codec/apidocs/org/apache/… : "Verifica una determinata stringa per vedere se contiene solo caratteri validi all'interno dell'alfabeto Base64. Attualmente il metodo tratta gli spazi bianchi come valido." Ciò significa che questo metodo ha alcuni falsi positivi come "spazi bianchi" o numeri ("0", "1").
Christian Vielma,

per stringa Base64.isBase64 (contenuto)
ema,

4
Questa risposta è sbagliata perché data stringToBeChecked="some plain text"quindi imposta boolean isBase64=trueanche se non è un valore codificato Base64. Leggi l'origine per commons-codec-1.4 Base64.isArrayByteBase64()verifica solo che ogni carattere nella stringa sia valido per essere considerato per la codifica Base64 e consente lo spazio bianco.
Brad

49

Bene puoi:

  • Verifica che la lunghezza sia un multiplo di 4 caratteri
  • Controlla che ogni carattere sia nel set AZ, az, 0-9, +, / tranne che per il riempimento alla fine che sia 0, 1 o 2 caratteri '='

Se ci si aspetta che sarà in Base64, allora probabilmente si può semplicemente usare qualsiasi libreria è disponibile sulla vostra piattaforma per cercare di decodificare in un array di byte, un'eccezione se non è valida base 64. Tale dipende dalla vostra piattaforma, ovviamente.


L'analisi differisce dalla convalida almeno per il fatto che richiede memoria per l'array di byte decodificato. Quindi questo non è l'approccio più efficace in alcuni casi.
Victor Yarema,

1
@VictorYarema: ho suggerito sia un approccio di sola validazione (punti elenco) sia un approccio di analisi (dopo i punti elenco).
Jon Skeet,

16

A partire da Java 8, puoi semplicemente usare java.util.Base64 per provare a decodificare la stringa:

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

try {
    decoder.decode(someString);
} catch(IllegalArgumentException iae) {
    // That string wasn't valid.
}

3
sì, è un'opzione, ma non dimenticare che la cattura è un'operazione piuttosto costosa in Java
panser

2
Questo non è il caso più. La gestione delle eccezioni sta andando abbastanza bene. È meglio non dimenticare che Java Regex è piuttosto lento. Voglio dire: VERAMENTE LENTO! In realtà è più veloce decodificare un Base64 e verificare che funzioni (non) invece di abbinare la stringa al Regex sopra. Ho fatto un test approssimativo e la corrispondenza di Java Regex è circa sei volte più lenta (!!) rispetto a un'eventuale eccezione sul decodifica.
Sven Döring,

Con più test eseguiti, in realtà è undici volte più lento. È tempo di una migliore implementazione di Regex in Java. Anche un controllo Regex con il motore JavaScript Nashorn in Java è molto più veloce. Incredibile. Inoltre JavaScript Regex (con Nashorn) è molto più potente.
Sven Döring,

3
Con Java 11 (anziché Java 8) il controllo Regex è addirittura 22 volte più lento. 🤦 (Perché la decodifica Base64 è diventata più veloce.)
Sven Döring il

15

Prova in questo modo per 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"; 
}

Usa questo per 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;
 }
}

1
Che lingua è questa? La domanda fu posta senza fare riferimento a una lingua
Ozkan,

questo non funzionerà. leggi la documentazione Returns FALSE if input contains character from outside the base64 alphabet. base64_decode
Aley

1
Come? se l'input contiene caratteri esterni, allora non è base64, giusto?
Suneel Kumar,

7
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');
}

5

Controlla se la lunghezza della stringa è un multiplo di 4. In seguito usa questa regex per assicurarti che tutti i caratteri nella stringa siano caratteri base64.

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

Se la libreria che usi aggiunge una nuova riga come modo di osservare i 76 caratteri massimi per regola di riga, sostituiscili con stringhe vuote.


Il link menzionato mostra 404. Controlla e aggiorna.
Ankur,

Mi dispiace @AnkurKumar, ma è quello che succede quando le persone hanno URL non freddi: cambiano continuamente. Non ho idea di dove sia stato spostato. Spero che troverai altre risorse utili tramite Google
Yaw Boakye,

Puoi sempre ottenere vecchie pagine da web.archive.org - ecco l'URL originale. web.archive.org/web/20120919035911/http://… oppure ho pubblicato il testo qui: gist.github.com/mika76/d09e2b65159e435e7a4cc5b0299c3e84
Mladen Mihajlovic

4

Esistono molte varianti di Base64 , quindi prendi in considerazione solo la possibilità di stabilire se la stringa è simile alla varietà che prevedi di gestire. Come tale, potrebbe essere necessario regolare l'espressione regolare sotto rispetto ai caratteri dell'indice e imbottitura (cioè +, /, =).

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

Uso:

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

3

Prova questo:

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");
    }
}

3

È impossibile verificare se una stringa è codificata in base64 o meno. È possibile validare solo se quella stringa ha un formato stringa codificato in base64, il che significherebbe che potrebbe essere una stringa prodotta dalla codifica base64 (per verificare che la stringa possa essere convalidata rispetto a una regexp o che sia possibile utilizzare una libreria, molti altre risposte a questa domanda forniscono buoni modi per verificarlo, quindi non entrerò nei dettagli).

Ad esempio, stringa flowè una stringa codificata in base64 valida. Ma è impossibile sapere se è solo una stringa semplice, una parola inglese flowo è una stringa codificata in base 64~Z0


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

questa espressione regolare mi ha aiutato a identificare la base64 nella mia applicazione in rotaie, ho avuto solo un problema, è che riconosce la stringa "errorDescripcion", ho generato un errore, per risolverlo basta convalidare la lunghezza di una stringa.


Il precedente regex /^.....$/.match(my_string) restituisce un errore di formattazione dicendo "Chiusura senza pari)"
james2611nov,

E con 'fine prematura della classe char: / ^ ((errori di sintassi [A-Za-z0-9 + /'.
james2611nov

Nevermind ha risolto il problema aggiungendo \ davanti a ogni / carattere.
james2611nov,

errorDescriptionè una stringa base64 valida, decodifica nella sequenza binaria di byte (in esadecimale): 7a ba e8 ac 37 ac 72 b8 a9 b6 2a 27.
Luis Colorado,

Ha funzionato perfettamente per me per controllare la stringa codificata base64.
Deepak Lakhara,

1

Questo funziona 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.")

Riepilogo: IsBase64("string here") restituisce true se string hereè codificato Base64 e restituisce false se string hereNON è codificato Base64.


1

C # Questo sta andando alla grande:

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;
}

1
Console.WriteLine("test".IsBase64()); // true
Langdon,

2
Raccomandare di cambiare il linguaggio di programmazione per risolvere un problema in generale non è una risposta valida.
Luis Colorado,

0

Non è possibile distinguere tra stringa e codifica base64, tranne per il fatto che la stringa nel proprio sistema presenta alcune limitazioni o identificazioni specifiche.


0

Questo frammento può essere utile quando conosci la lunghezza del contenuto originale (ad esempio un checksum). Verifica che la forma codificata abbia la lunghezza corretta.

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() ;
}

0

Se RegEx non funziona e si conosce lo stile del formato della stringa originale, è possibile invertire la logica, regexing per questo formato.

Ad esempio, lavoro con file xml con codifica base64 e controllo solo se il file contiene markup xml validi. In caso contrario, posso presumere che sia decodificato in base64. Questo non è molto dinamico ma funziona bene per la mia piccola applicazione.


0

Questo funziona 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)

0

Prova questo usando una regex menzionata in precedenza:

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");
}

... Possiamo anche fare una semplice validazione come, se ha spazi non può essere Base64:

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");
 }

Ok, potresti per favore dare una soluzione allora?
Marco,

0

se durante la decodifica otteniamo una stringa con caratteri ASCII, la stringa non è stata codificata

(RoR) soluzione di rubino:

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

def decoded?(str)
  Base64.decode64(str.downcase).scan(/[^[:ascii:]]/).count > 0
end

0

Provo a usare questo, sì, questo funziona

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

ma ho aggiunto la condizione per verificare che almeno la fine del personaggio sia =

string.lastIndexOf("=") >= 0

Perché controllare =: quale specifica Base64stai usando? Cosa end of the charactersignifica e in che modo non negativo lo lastIndexOf()controlla?
greybeard il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.