2010-03-31 17 views
23

C'è un modo per rilevare se una stringa è stata base64_encoded() in PHP?Rileva la codifica base64 in PHP?

Stiamo convertendo un po 'di spazio di archiviazione da testo normale a base64 e parte di esso risiede in un cookie che deve essere aggiornato. Mi piacerebbe ripristinare i loro cookie se il testo non è ancora stato codificato, altrimenti lasciarlo da solo.

risposta

24

Ci scusiamo per una risposta tardiva a una domanda già risposta, ma non penso che base64_decode ($ x, true) sia una soluzione sufficientemente buona per questo problema. Infatti, potrebbe non esserci un'ottima soluzione che funziona contro qualsiasi input dato. Per esempio, posso mettere molti valori sbagliati in $ x e non ottenere un valore di ritorno falso.

var_dump(base64_decode('wtf mate',true)); 
string(5) "���j�" 

var_dump(base64_decode('This is definitely not base64 encoded',true)); 
string(24) "N���^~)��r��[jǺ��ܡם" 

credo che oltre al controllo rigoroso valore di ritorno, avresti anche bisogno di fare la convalida post-decodifica. Il modo più affidabile è se fosse possibile decodificare e quindi verificare contro un insieme noto di possibili valori.

Una soluzione più generale con meno del 100% di precisione (più vicino con stringhe più lunghe, imprecise per stringhe corte) è se si controlla l'output per vedere se molti sono al di fuori di un normale intervallo di utf-8 (o qualsiasi altra codifica usare) caratteri.

Vedi questo esempio:

<?php 
$english = array(); 
foreach (str_split('[email protected]#$%^*()_+|}?><": Iñtërnâtiônàlizætiøn') as $char) { 
    echo ord($char) . "\n"; 
    $english[] = ord($char); 
} 
    echo "Max value english = " . max($english) . "\n"; 

$nonsense = array(); 
echo "\n\nbase64:\n"; 
foreach (str_split(base64_decode('Not base64 encoded',true)) as $char) { 
    echo ord($char) . "\n"; 
    $nonsense[] = ord($char); 
} 

    echo "Max nonsense = " . max($nonsense) . "\n"; 

?> 

Risultati:

Max value english = 195 
Max nonsense = 233 

così si può fare qualcosa di simile:

if ($maxDecodedValue > 200) {} //decoded string is Garbage - original string not base64 encoded 

else {} //decoded string is useful - it was base64 encoded 

Probabilmente si dovrebbe utilizzare la media() della decodificato valori invece di max(), ho appena usato max() in questo esempio perché non c'è tristemente built-in mean() in PHP. Quale misura si utilizza (media, max, ecc.) Rispetto a quale soglia (ad esempio 200) dipende dal profilo di utilizzo stimato.

In conclusione, l'unica mossa vincente non è quella di giocare. Cercherò di evitare di dover discernere base64 in primo luogo.

+0

sconsigliato ... – catbadger

3

Stavo per costruire una ginocchiera Base64 in php, questo è quello che ho fatto:

function base64Toggle($str) { 
    if (!preg_match('~[^0-9a-zA-Z+/=]~', $str)) { 
     $check = str_split(base64_decode($str)); 
     $x = 0; 
     foreach ($check as $char) if (ord($char) > 126) $x++; 
     if ($x/count($check)*100 < 30) return base64_decode($str); 
    } 
    return base64_encode($str); 
} 

funziona perfettamente per me. Qui sono i miei pensieri complete su di esso: http://www.albertmartin.de/blog/code.php/19/base64-detection

E qui si può provare: http://www.albertmartin.de/tools

16

Ho avuto lo stesso problema, ho finito con questa soluzione:

if (base64_encode(base64_decode($data)) === $data){ 
    echo '$data is valid'; 
} else { 
    echo '$data is NOT valid'; 
} 
+4

L'unica cosa negativa è che avrei dovuto pensare prima ;-) – chrishiestand

+7

Se faccio $ data = 'iujhklsc' ottengo la validità, ma non lo è; – Mohit

+0

Lo controllerò .. – Amir

6

Siamo in grado di combinare tre cose in una funzione per verificare se la stringa data è una base 64 valida codificata o meno.

function validBase64($string) 
{ 
    $decoded = base64_decode($string, true); 

    // Check if there is no invalid character in string 
    if (!preg_match('/^[a-zA-Z0-9\/\r\n+]*={0,2}$/', $string)) return false; 

    // Decode the string in strict mode and send the response 
    if (!base64_decode($string, true)) return false; 

    // Encode and compare it to original one 
    if (base64_encode($decoded) != $string) return false; 

    return true; 
} 
+0

Penso che "$ str" dovrebbe in realtà essere "$ stringa" sulla seconda riga. – Wireblue

+0

@Wireblue: Grazie ho modificato $ str con $ stringa –

+0

se non dovessi controllare anche che la lunghezza dell'input mod 4 == 0? – frumbert

0

In genere un testo in base64 non ha spazi.

Ho usato questa funzione che ha funzionato bene per me. Verifica se il numero di spazi nella stringa è inferiore a 1 su 20.

ad esempio: almeno 1 spazio per ogni 20 caratteri --- (spazi/strlen) < 0.05

function normalizaBase64($data){ 
    $spaces = substr_count ($data ," "); 
    if (($spaces/strlen($data))<0.05) 
    { 
     return base64_decode($data); 
    } 
    return $data; 
} 
1

base64_decode() non restituirà FALSE se l'input non è valido dati codificati Base64. Utilizzare imap_base64() contrario, restituisce FALSE se $ testo contiene caratteri al di fuori l'alfabeto Base64 imap_base64() Reference

9
function is_base64_encoded($data) 
{ 
    if (preg_match('%^[a-zA-Z0-9/+]*={0,2}$%', $data)) { 
     return TRUE; 
    } else { 
     return FALSE; 
    } 
}; 

is_base64_encoded("iash21iawhdj98UH3"); // true 
is_base64_encoded("#iu3498r"); // false 
is_base64_encoded("asiudfh9w=8uihf"); // false 
is_base64_encoded("a398UIhnj43f/1!+sadfh3w84hduihhjw=="); // true 

http://php.net/manual/en/function.base64-decode.php#81425

+0

Questo è molto utile, ma il tuo quarto esempio 'is_base64_encoded (" a398UIhnj43f/1! + Sadfh3w84hduihhjw == "); // true' restituisce FALSE nei miei test. – Dylan

0

Può essere che non è esattamente quello che hai chiesto. Ma spero che possa essere utile per qualcuno.

Nel mio caso la soluzione è stata per codificare tutti i dati con json_encode e poi base64_encode.

$encoded=base64_encode(json_encode($data)); 

questo valore può essere memorizzato o utilizzato in qualsiasi momento. Poi, per verificare se questo valore non è solo una stringa di testo, ma i dati codificati è sufficiente utilizzare

function isData($test_string){ 
    if(base64_decode($test_string,true)&&json_decode(base64_decode($test_string))){ 
     return true; 
    }else{ 
    return false; 
    } 

o in alternativa

function isNotData($test_string){ 
    if(base64_decode($test_string,true)&&json_decode(base64_decode($test_string))){ 
     return false; 
    }else{ 
    return true; 
    } 

Grazie a tutti gli autori risposte precedenti in questa discussione :)

0

Ecco la mia soluzione:

if(empty(htmlspecialchars(base64_decode($string, true)))) { return false; }

Restituisce falso se il decodificato $string non è valido, ad esempio: "nodo", "123", "", ecc.