Определить кодировку base64 в PHP?
Есть ли способ определить, была ли строка base64_encoded() в PHP?
Мы конвертируем некоторое хранилище из обычного текста в base64, а часть его находится в файле cookie, который необходимо обновить. Я бы хотел, чтобы reset их cookie, если текст еще не был закодирован, иначе оставьте его в покое.
Ответы
Ответ 1
Извинения за поздний ответ на уже ответивший вопрос, но я не думаю, что 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 в первую очередь.
Ответ 2
У меня была та же проблема, я закончил с этим решением:
if ( base64_encode(base64_decode($data)) === $data){
echo '$data is valid';
} else {
echo '$data is NOT valid';
}
Ответ 3
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=="); // false
http://php.net/manual/en/function.base64-decode.php#81425
Ответ 4
Мы можем объединить три вещи в одну функцию, чтобы проверить, является ли заданная строка допустимой базой 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;
}
Ответ 5
Я собирался создать 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
Ответ 6
Лучше поздно, чем никогда: возможно, вы можете использовать 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;
}
}
Ответ 7
base64_decode() не будет возвращать FALSE, если вход недействителен для кодированных данных base64. Вместо этого используйте imap_base64()
, он возвращает FALSE, если $text содержит символы вне алфавита Base64
imap_base64() Ссылка
Ответ 8
Здесь мое решение:
if(empty(htmlspecialchars(base64_decode($string, true)))) {
return false;
}
Он вернет false, если декодированный $string
недействителен, например: "node", "123", "" и т.д.
Ответ 9
Обычно текст в 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;
}
Ответ 10
Возможно, это не совсем то, о чем вы просили. Но надеюсь, что это будет полезно для кого-то.
В моем случае решение заключалось в кодировании всех данных с помощью 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;
}
Спасибо всем предыдущим авторам ответов в этой теме:)
Ответ 11
Ваш лучший вариант:
$base64_test = mb_substr(trim($some_base64_data), 0, 76);
return (base64_decode($base64_test, true) === FALSE ? FALSE : TRUE);
Ответ 12
$is_base64 = function(string $string) : bool {
$zero_one = ['MA==', 'MQ=='];
if (in_array($string, $zero_one)) return TRUE;
if (empty(htmlspecialchars(base64_decode($string, TRUE))))
return FALSE;
return TRUE;
};
var_dump('*** These yell false ***');
var_dump($is_base64(''));
var_dump($is_base64('This is definitely not base64 encoded'));
var_dump($is_base64('node'));
var_dump($is_base64('node '));
var_dump($is_base64('123'));
var_dump($is_base64(0));
var_dump($is_base64(1));
var_dump($is_base64(123));
var_dump($is_base64(1.23));
var_dump('*** These yell true ***');
var_dump($is_base64(base64_encode('This is definitely base64 encoded')));
var_dump($is_base64(base64_encode('node')));
var_dump($is_base64(base64_encode('123')));
var_dump($is_base64(base64_encode(0)));
var_dump($is_base64(base64_encode(1)));
var_dump($is_base64(base64_encode(123)));
var_dump($is_base64(base64_encode(1.23)));
var_dump($is_base64(base64_encode(TRUE)));
var_dump('*** Should these yell true? Might be edge cases ***');
var_dump($is_base64(base64_encode('')));
var_dump($is_base64(base64_encode(FALSE)));
var_dump($is_base64(base64_encode(NULL)));