2010-03-31 10 views
23

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

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

ответ

24

Извинения за поздний ответ на уже ответили на вопрос, но я не думаю, что 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 

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

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

+0

... – catbadger

3

Я собирался построить 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

16

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

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

препятствуя Единственная плохая вещь о том, что я должен был думать о это сначала ;-) – chrishiestand

+7

Если я делаю $ data = 'iujhklsc', я получаю действительный, но это не так; – Mohit

+0

Я проверю это. – Amir

6

Мы можем объединить три вещи в одну функцию, чтобы проверить, является ли заданная строка действительной базой 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; 
} 
+0

Я думаю, что «$ str» на самом деле должна быть «$ string» на второй строке. – Wireblue

+0

@Wireblue: Спасибо. У меня есть редактирование $ str с $ string –

+0

если вы не можете также проверить, что длина ввода mod 4 == 0? – frumbert

0

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

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

например: не менее 1 места для каждых 20 символов --- (пробелы/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() не будет возвращать FALSE, если вход недействителен для кодированных данных base64. Используйте imap_base64() вместо этого, он возвращает FALSE, если $ текст содержит символы вне алфавита 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

Это очень полезно, но ваш четвертый пример 'is_base64_encoded (" a398UIhnj43f/1! + Sadfh3w84hduihhjw == "); // true' возвращает FALSE в моих тестах. – Dylan

0

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

В моем случае решение заключалось в кодировании всех данных с помощью 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

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

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

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