it-roy-ru.com

Определить кодировку base64 в PHP?

Есть ли какой-нибудь способ определить, была ли строка base64_encoded () в PHP? 

Мы конвертируем некоторое хранилище из обычного текста в base64, и часть его хранится в файле cookie, который необходимо обновить. Я хотел бы сбросить их cookie, если текст еще не был закодирован, в противном случае оставьте его в покое.

26
Ian McIntyre Silber

Извиняюсь за поздний ответ на уже отвеченный вопрос, но я не думаю, что base64_decode ($ x, true) является достаточно хорошим решением для этой проблемы. На самом деле, не может быть очень хорошего решения, которое работает против любого данного входа. Например, я могу положить много неправильных значений в $ x и не получить ложное возвращаемое значение.

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

Я думаю, что в дополнение к строгой проверке возвращаемого значения вам также потребуется выполнить проверку после декодирования. Самый надежный способ - если вы могли бы декодировать, а затем сверять с известным набором возможных значений.

Более общее решение с точностью менее 100% (ближе к длинным строкам, неточное для коротких строк) заключается в том, что вы проверяете свои выходные данные, чтобы увидеть, находятся ли многие из них вне нормального диапазона символов utf-8 (или любой другой кодировки, которую вы используете).

Смотрите этот пример:

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

?>

Результаты:

Max value english = 195
Max nonsense = 233

Так что вы можете сделать что-то вроде этого:

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

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

Вы, вероятно, должны использовать mean () декодированных значений вместо max (), я просто использовал max () в этом примере, потому что, к сожалению, в PHP нет встроенного mean (). Какой показатель вы используете (в среднем, максимум и т.д.) И какой порог (например, 200) зависит от вашего предполагаемого профиля использования.

В заключение, единственный выигрышный ход - не играть. Я бы постарался избежать необходимости распознавать base64.

24
chrishiestand

У меня была такая же проблема, я закончил с этим решением:

if ( base64_encode(base64_decode($data)) === $data){
    echo '$data is valid';
} else {
    echo '$data is NOT valid';
}
15
Amir
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

12
alex

Мы можем объединить три вещи в одну функцию, чтобы проверить, является ли данная строка верным в кодировке base 64 или нет.

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
Abhinav bhardwaj

Я собирался создать base64-переключатель в php, вот что я сделал:

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

Это прекрасно работает для меня . Вот мои полные мысли об этом: http://www.albertmartin.de/blog/code.php/19/base64-detection

И здесь вы можете попробовать это: http://www.albertmartin.de/tools

3
Albert

base64_decode () не вернет FALSE, если введенные данные недопустимы в кодировке base64. Вместо этого используйте imap_base64(), он возвращает FALSE, если $ text содержит символы вне алфавита Base64 imap_base64 () Справочник

2
Sivaguru

Вот мое решение:

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

Он вернет false, если декодированный $string недействителен, например: «узел», «123», «» и т.д.

1
Special K.

Может быть, это не совсем то, что вы просили. Но надеюсь, что это будет полезно для кого-то.

В моем случае решением было закодировать все данные с помощью json_encode, а затем base64_encode.

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

это значение может быть сохранено или использовано как вам нужно .. Затем, чтобы проверить, является ли это значение не просто текстовой строкой, а закодированными вашими данными, вы просто используете

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

или в качестве альтернативы

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

Спасибо всем предыдущим ответам авторов в этой теме :)

0
Mikhail.root

Ваш лучший вариант:

$base64_test = mb_substr(trim($some_base64_data), 0, 76);
return (base64_decode($base64_test, true) === FALSE ? FALSE : TRUE);
0
Digital Human

Обычно текст в base64 не имеет пробелов. 

Я использовал эту функцию, которая работала нормально для меня. Он проверяет, меньше ли количество пробелов в строке, чем 1 на 20.

например: по крайней мере 1 пробел на каждые 20 символов --- (пробел/стр.) <0,05

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

Лучше поздно, чем никогда: возможно, вы можете использовать mb_detect_encoding(), чтобы выяснить, является ли закодированная строка неким текстом:

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
Marki