2010-03-31 54 views
23

¿Hay alguna manera de detectar si una cadena ha sido base64_encoded() en PHP?¿Detecta codificación base64 en PHP?

Estamos convirtiendo algo de almacenamiento de texto sin formato a base64 y parte de él vive en una cookie que debe actualizarse. Me gustaría restablecer su cookie si el texto aún no se ha codificado, de lo contrario, déjalo en paz.

Respuesta

24

Disculpas por una respuesta tardía a una pregunta ya respondida, pero no creo que base64_decode ($ x, true) sea una solución suficientemente buena para este problema. De hecho, puede que no haya una solución muy buena que funcione en contra de cualquier entrada dada. Por ejemplo, puedo poner muchos valores incorrectos en $ x y no obtener un valor de retorno 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Ǻ��ܡם" 

creo que, además de la verificación estricta de valor de retorno, también tenía que hacer la validación posterior a la decodificación. La forma más confiable es si puede decodificar y luego verificar con un conjunto conocido de valores posibles.

Una solución más general con menos del 100% de precisión (más cerca con cadenas más largas, inexactas para cadenas cortas) es si verifica su salida para ver si hay muchas fuera de un rango normal de utf-8 (o lo que uso) caracteres.

ver este ejemplo:

<?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"; 

?> 

Resultados:

Max value english = 195 
Max nonsense = 233 

por lo que puede hacer algo como esto:

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

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

Probablemente debería utilizar la media() de la decodificado valores en lugar de max(), acabo de utilizar max() en este ejemplo porque lamentablemente no hay media incorporada() en PHP. Qué medida usa (promedio, máximo, etc.) contra qué umbral (por ejemplo, 200) depende de su perfil de uso estimado.

En conclusión, el único movimiento ganador es no jugar. Intentaré evitar tener que distinguir base64 en primer lugar.

+0

desalentador ... – catbadger

3

estaba a punto de construir una base 64 de palanca en php, esto es lo que hice:

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

funciona perfectamente para mí. Aquí están mis pensamientos completos en él: http://www.albertmartin.de/blog/code.php/19/base64-detection

y aquí se puede probar: http://www.albertmartin.de/tools

16

que tenían el mismo problema, que terminó con esta solución:

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

Lo único malo de esto es que debería haber pensado en primero ;-) – chrishiestand

+7

Si hago $ data = 'iujhklsc' me hago válido, pero no lo es; – Mohit

+0

Lo comprobaré .. – Amir

6

Podemos combinar tres cosas en una función para verificar si la cadena dada es una base 64 válida codificada o no.

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

Creo que "$ str" en realidad debería ser "$ string" en la segunda línea. – Wireblue

+0

@Wireblue: Gracias, he editado $ str con $ cadena –

+0

¿no debería verificar también que la longitud de la entrada mod 4 == 0? – frumbert

0

Normalmente, un texto en base64 no tiene espacios.

Utilicé esta función que funcionó bien para mí. Comprueba si el número de espacios en la cadena es menor que 1 en 20.

e.g: al menos 1 espacio para cada 20 caracteres --- (espacios/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() no devolverá FALSE si la entrada no es base64 válidos datos codificados. Utilice imap_base64() lugar, devuelve FALSO si $ texto contiene caracteres fuera del alfabeto base 64 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

Esto es muy útil, pero su cuarto ejemplo 'is_base64_encoded (" a398UIhnj43f/1! + Sadfh3w84hduihhjw == "); // true' devuelve FALSE en mis pruebas. – Dylan

0

Puede ser que no es exactamente lo que ha pedido. Pero espero que sea útil para alguien.

En mi caso, la solución era codificar todos los datos con json_encode y luego base64_encode.

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

este valor se puede almacenar o usar cuando lo necesite. Entonces, para comprobar si este valor no es más que una cadena de texto, pero sus datos codificado sólo tiene que utilizar

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

o alternativamente

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

Gracias a todos los autores anteriores respuestas en este hilo :)

0

aquí está mi solución:

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

Devolverá falso si el decodificado $string no es válido, por ejemplo: "nodo", "123", "", etc.

Cuestiones relacionadas