2010-03-31 14 views
23

Y at-il un moyen de détecter si une chaîne a été base64_encoded() en PHP?Détecter l'encodage base64 en PHP?

Nous convertissons du stockage du texte brut en base64 et une partie de celui-ci vit dans un cookie qui doit être mis à jour. Je voudrais réinitialiser leur cookie si le texte n'a pas encore été encodé, sinon le laisser seul.

Répondre

24

Excuses pour une réponse tardive à une question déjà répondu, mais je ne pense pas que base64_decode ($ x, true) est une solution assez bonne pour ce problème. En fait, il peut ne pas y avoir une très bonne solution qui fonctionne contre une entrée donnée. Par exemple, je peux mettre beaucoup de mauvaises valeurs dans $ x et ne pas avoir une fausse valeur de retour.

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Ǻ��ܡם" 

Je pense qu'en plus de la vérification stricte de la valeur de retour, vous devez également effectuer une validation post-décodage. Le moyen le plus fiable est de pouvoir décoder et vérifier par rapport à un ensemble connu de valeurs possibles. Une solution plus générale avec moins de 100% de précision (plus proche avec des chaînes plus longues, inexacte pour les chaînes courtes) est si vous vérifiez votre sortie pour voir si beaucoup sont en dehors d'une gamme normale de utf-8 (ou utiliser) caractères.

Voir cet exemple:

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

?> 

Résultats:

Max value english = 195 
Max nonsense = 233 

Ainsi, vous pouvez faire quelque chose comme ceci:

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

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

Vous devriez probablement utiliser la moyenne() du décodé Au lieu de max(), j'ai juste utilisé max() dans cet exemple car il n'y a malheureusement pas de mean() en PHP. Quelle mesure vous utilisez (moyenne, maximum, etc.) par rapport à quel seuil (par exemple 200) dépend de votre profil d'utilisation estimé. En conclusion, le seul coup gagnant est de ne pas jouer. J'essaierais d'éviter d'avoir à discerner base64 en premier lieu.

+0

décourager ... – catbadger

3

j'étais sur le point de construire une bascule base64 en php, voici ce que je faisais:

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

Il fonctionne parfaitement pour moi. Voici mes pensées complètes sur elle: http://www.albertmartin.de/blog/code.php/19/base64-detection

Et vous pouvez essayer: http://www.albertmartin.de/tools

16

J'ai eu le même problème, je me suis retrouvé avec cette solution:

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

La seule mauvaise chose à ce sujet est que j'aurais pensé le premier ;-) – chrishiestand

+7

Si je fais $ data = 'iujhklsc' je deviens valide, mais ce n'est pas le cas; – Mohit

+0

Je vais vérifier .. – Amir

6

Nous pouvons combiner trois les choses en une seule fonction pour vérifier si une chaîne donnée est une base valide 64 codée ou non.

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

Je pense que "$ str" devrait être "$ string" sur la deuxième ligne. – Wireblue

+0

@Wireblue: Merci d'avoir édité $ str avec $ string –

+0

si vous ne vérifiez pas que la longueur du mod d'entrée 4 == 0? – frumbert

0

Habituellement, un texte en base64 n'a pas d'espace. J'ai utilisé cette fonction qui a bien fonctionné pour moi. Il teste si le nombre d'espaces dans la chaîne est inférieur à 1 sur 20.

par exemple: au moins 1 espace pour chaque 20 caractères --- (espaces/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() ne retournera pas FALSE si l'entrée n'est pas une donnée codée base64 valide. Utilisez imap_base64() à la place, il retourne FALSE si le texte contient des caractères $ en dehors de l'alphabet 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

Ceci est très utile, mais votre quatrième exemple 'is_base64_encoded (" a398UIhnj43f/1! + Sadfh3w84hduihhjw == "); // true' retourne FAUX dans mes tests. – Dylan

0

Peut-être ce n'est pas exactement ce que vous avez demandé. Mais j'espère que ce sera utile pour quelqu'un. Dans mon cas, la solution consistait à coder toutes les données avec json_encode, puis base64_encode.

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

cette valeur peut être stockée ou utilisée selon vos besoins. ensuite pour vérifier si cette valeur est non seulement une chaîne de texte mais vos données codées utilisez simplement

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

ou bien

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

Merci à tous les réponses précédentes auteurs dans ce fil :)

0

Voici ma solution:

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

Il retourne false si le décodé $string est invalide, par exemple: « noeud », « 123 », « », etc.