tags:

views:

149

answers:

3

Hi

I'm writing an error handler script which encrypts the error data (file, line, error, message etc) and passes the serialized array as a POST variable (using curl) to a script which then logs the error in a central db.

I've tested my encrypt/decrypt functions in a single file and the data is encrypted and decrypted fine:

define('KEY', 'abc');
define('CYPHER', 'blowfish');
define('MODE', 'cfb');


function encrypt($data) {
    $td = mcrypt_module_open(CYPHER, '', MODE, '');
    $iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
    mcrypt_generic_init($td, KEY, $iv);
    $crypttext = mcrypt_generic($td, $data);
    mcrypt_generic_deinit($td);
    return $iv.$crypttext;
}

function decrypt($data) {
    $td = mcrypt_module_open(CYPHER, '', MODE, '');
    $ivsize = mcrypt_enc_get_iv_size($td);
    $iv = substr($data, 0, $ivsize);
    $data = substr($data, $ivsize);
    if ($iv)
    {
        mcrypt_generic_init($td, KEY, $iv);
        $data = mdecrypt_generic($td, $data);
    }
    return $data;
}

echo "<pre>";
$data = md5('');
echo "Data: $data\n";
$e = encrypt($data);
echo "Encrypted: $e\n";
$d = decrypt($e);
echo "Decrypted: $d\n";

Output:

Data: d41d8cd98f00b204e9800998ecf8427e
Encrypted: ê÷#¯KžViiÖŠŒÆÜ,ÑFÕUW£´Œt?†÷>c×åóéè+„N
Decrypted: d41d8cd98f00b204e9800998ecf8427e

The problem is, when I put the encrypt function in my transmit file (tx.php) and the decrypt in my recieve file (rx.php), the data is not fully decrypted (both files have the same set of constants for key, cypher and mode).

Data before passing: a:4:{s:3:"err";i:1024;s:3:"msg";s:4:"Oops";s:4:"file";s:46:"/Applications/MAMP/htdocs/projects/txrx/tx.php";s:4:"line";i:80;}
Data decrypted: Mª4:{s:3:"err";i:1024@7OYªç`^;g";s:4:"Oops";s:4:"file";sôÔ8F•Ópplications/MAMP/htdocs/projects/txrx/tx.php";s:4:"line";i:80;}

Note the random characters in the middle.

My curl is fairly simple:

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'data=' . $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);

Things I suspect could be causing this:

  • Encoding of the curl request
  • Something to do with mcrypt padding missing bytes
  • I've been staring at it too long and have missed something really really obvious

If I turn off the crypt functions (so the transfer tx->rx is unencrypted) the data is received fine.

Any and all help much appreciated!

Thanks, Adam

+3  A: 

The encrypted data is binary but you didn't URL encoded it. Do this in the CURL,

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'data=' . urlencode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
ZZ Coder
Thanks for the suggestion, but I've added that and it's not fixed the problem.
adam
+1  A: 

I figured it out - had to base64_encode the data after encryption and then base64_decode before decrypting.

Thanks to those who had a think on my behalf!

adam
A: 

Neither this answers were ok for me. Base64_encode is still not safe and has issues with spaces and plus signs for longer strings. I found this functions helpful:

<?php 
function urlsafe_b64encode($string)
{
    $data = base64_encode($string);
    $data = str_replace(array('+','/','='),array('-','_','.'),$data);
    return $data;
}
function urlsafe_b64decode($string)
{
    $data = str_replace(array('-','_','.'),array('+','/','='),$string);
    $mod4 = strlen($data) % 4;
    if ($mod4) {
        $data .= substr('====', $mod4);
    }
    return base64_decode($data);
}
?>

Hope this helps somebody.

Elzo Valugi