Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

base64_* functions disabled, what to do now?

I am getting following warning when I try to use base64_decode() function

"Warning: base64_decode() has been disabled for security reasons"

Looks like my host has disabled base64_* functions.

I have few questions

  1. I think base64_* functions can be enabled by default in php, correct?
  2. Is there any security reason why base64_* functions are not enabled? Any security breach?
  3. Alternative to base64_* functions, which are available by default?
  4. Where can I find custom class/functions for base64_* implementation, so that I can have them in my PHP file, and use them if PHP's base64_* functions are not available?

Help appreciated.

like image 836
I-M-JM Avatar asked Apr 19 '12 17:04

I-M-JM


2 Answers

I have written alternative functions for all base64 purposes.

Look here:

function base64_decode($input) {
    $keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    $chr1 = $chr2 = $chr3 = "";
    $enc1 = $enc2 = $enc3 = $enc4 = "";
    $i = 0;
    $output = "";

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    $filter = $input;
    $input = preg_replace("[^A-Za-z0-9\+\/\=]", "", $input);
    if ($filter != $input) {
        return false;
    }

    do {
        $enc1 = strpos($keyStr, substr($input, $i++, 1));
        $enc2 = strpos($keyStr, substr($input, $i++, 1));
        $enc3 = strpos($keyStr, substr($input, $i++, 1));
        $enc4 = strpos($keyStr, substr($input, $i++, 1));
        $chr1 = ($enc1 << 2) | ($enc2 >> 4);
        $chr2 = (($enc2 & 15) << 4) | ($enc3 >> 2);
        $chr3 = (($enc3 & 3) << 6) | $enc4;
        $output = $output . chr((int) $chr1);
        if ($enc3 != 64) {
            $output = $output . chr((int) $chr2);
        }
        if ($enc4 != 64) {
            $output = $output . chr((int) $chr3);
        }
        $chr1 = $chr2 = $chr3 = "";
        $enc1 = $enc2 = $enc3 = $enc4 = "";
    } while ($i < strlen($input));
    return urldecode($output);
}

function base64_encode($data) {
    $b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
    $o1 = $o2 = $o3 = $h1 = $h2 = $h3 = $h4 = $bits = $i = 0;
    $ac = 0;
    $enc = '';
    $tmp_arr = array();
    if (!$data) {
        return data;
    }
    do {
    // pack three octets into four hexets
    $o1 = charCodeAt($data, $i++);
    $o2 = charCodeAt($data, $i++);
    $o3 = charCodeAt($data, $i++);
    $bits = $o1 << 16 | $o2 << 8 | $o3;
    $h1 = $bits >> 18 & 0x3f;
    $h2 = $bits >> 12 & 0x3f;
    $h3 = $bits >> 6 & 0x3f;
    $h4 = $bits & 0x3f;
    // use hexets to index into b64, and append result to encoded string
    $tmp_arr[$ac++] = charAt($b64, $h1).charAt($b64, $h2).charAt($b64, $h3).charAt($b64, $h4);
    } while ($i < strlen($data));
    $enc = implode($tmp_arr, '');
    $r = (strlen($data) % 3);
    return ($r ? substr($enc, 0, ($r - 3)) . substr('===', $r) : $enc);
}

function charCodeAt($data, $char) {
    return ord(substr($data, $char, 1));
}

function charAt($data, $char) {
    return substr($data, $char, 1);
}

But don't forget the charCodeAt and the charAt function. They are both necessary for base64_encode. The two functions base64_encode and base64_decode both are working like the inbuilt PHP functions. But only use them, if the inbuilt ones are not availible because they're not as fast as the inbuilt ones.

Hope it helps!

like image 116
jankal Avatar answered Sep 24 '22 13:09

jankal


Just registered to comment jankal's answer, but can't do it without reputation.

Last line of function base64_encode code in jankal's answer is

return ($r ? substr($enc, 0, ($r - 3)) : $enc) . substr('===', ($r || 3));

where $r can be 0, 1 or 2. As I understand, ($r || 3) expression value by code logic must be 3 when $r = 0, and $r in other two cases, but in practice (PHP 5.6/7.0) value of this expression always equals to 1, so our BASE64-encoded string always ends with two '=' symbols, which is definitely wrong.

My solution:

return ($r ? substr($enc, 0, ($r - 3)) . substr('===', $r) : $enc);
like image 41
Ivan Shatsky Avatar answered Sep 25 '22 13:09

Ivan Shatsky