Détecter l'encodage base64 en PHP?

y a-t-il un moyen de détecter si une chaîne a été base64_encoded() dans PHP?

nous sommes en train de convertir du stockage de texte en base64 et une partie de celui-ci vit dans un cookie qui doit être mis à jour. J'aimerais réinitialiser leur cookie si le texte n'a pas encore été encodé, sinon laissez tomber.

25
demandé sur Ian McIntyre Silber 2010-04-01 00:45:45

11 réponses

excuses pour une réponse tardive à une question déjà répondue, mais je ne pense pas que base64_decode($x,true) soit une bonne solution pour ce problème. En fait, il se peut qu'il n'y ait pas de très bonne solution qui fonctionne contre un intrant donné. Par exemple, je peux mettre beaucoup de mauvaises valeurs dans $x et ne pas obtenir 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 stricte vérification de la valeur de retour, vous devrez également faire une validation post-décodage. La façon la plus fiable est si vous pouviez décoder et vérifier ensuite contre un ensemble de valeurs possibles.

une solution plus générale avec moins de 100% de précision (plus proche avec des chaînes plus longues, imprécis pour les chaînes courtes) est si vous vérifiez votre sortie pour voir si beaucoup sont en dehors d'une plage normale de caractères utf-8 (ou quel que soit l'encodage que vous utilisez).

par exemple:

<?php
$english = array();
foreach (str_split('az019AZ~~~!@#$%^*()_+|}?><": 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

Si 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 utilisez la moyenne () des valeurs décodées au lieu de la max (), j'ai juste utilisé max() dans cet exemple parce qu'il n'y a malheureusement pas de moyenne intégrée () dans PHP. Quelle mesure vous utilisez (moyenne,max, 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. Je voudrais essayer d'éviter d'avoir à discerner base64 en premier lieu.

24
répondu chrishiestand 2011-04-12 09:01:15

j'ai eu le même problème, j'ai fini avec cette solution:

if ( base64_encode(base64_decode($data)) === $data){
    echo '$data is valid';
} else {
    echo '$data is NOT valid';
}
19
répondu Amir 2013-06-10 07:35:08
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

11
répondu alex 2018-02-28 20:04:54

nous pouvons combiner trois choses en une seule fonction pour vérifier si une chaîne donnée est une base 64 valide encodé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;
}
7
répondu Abhinav bhardwaj 2016-12-15 09:04:13

j'étais sur le point de construire une base64 toggle en php, c'est ce que j'ai fait:

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 à ce sujet:http://www.albertmartin.de/blog/code.php/19/base64-detection

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

3
répondu Albert 2013-03-27 09:55:20

base64_decode () ne retournera pas FALSE si l'entrée n'est pas valide. Utilisez imap_base64() à la place, il retourne FALSE si $text contient des caractères en dehors de l'alphabet de Base64 imap_base64() Référence

2
répondu Sivaguru 2015-11-20 11:29:48

Habituellement, un texte en base64 n'a pas d'espaces.

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.

E. g: 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;
}
0
répondu Gustavo Gallas 2015-11-09 14:54:47

il est Peut-être pas exactement ce que vous avez demandé. Mais j'espère que ça sera utile pour quelqu'un.

dans mon cas, la solution était d'encoder 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 n'est pas juste une chaîne de texte mais vos données encodées vous utilisez simplement

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

ou sinon

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

merci à toutes les réponses précédentes fil de discussion:)

0
répondu Mikhail.root 2016-02-08 11:38:22

Voici ma solution:

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

Elle retourne false si le décodé $string n'est pas valide, par exemple: "nœud", "123", " ", etc.

0
répondu Special K. 2017-11-25 12:56:23

votre meilleure option est:

$base64_test = mb_substr(trim($some_base64_data), 0, 76);
return (base64_decode($base64_test, true) === FALSE ? FALSE : TRUE);
0
répondu Digital Human 2018-06-06 11:06:56

Mieux vaut tard que jamais: Vous pourriez peut-être utiliser mb_detect_encoding() pour savoir si la chaîne codée semble avoir été une sorte de texte:

function is_base64_string($s) {
  // first check if we're dealing with an actual valid base64 encoded string
  if (($b = base64_decode($s, TRUE)) === FALSE) {
    return FALSE;
  }

  // now check whether the decoded data could be actual text
  $e = mb_detect_encoding($b);
  if (in_array($e, array('UTF-8', 'ASCII'))) { // YMMV
    return TRUE;
  } else {
    return FALSE;
  }
}
0
répondu Marki 2018-08-16 13:09:55