PHP / Mcrypt problem

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
User avatar
Neron
Forum Newbie
Posts: 5
Joined: Sun Oct 16, 2005 6:11 pm
Location: Bolivia / Switzerland

PHP / Mcrypt problem

Post by Neron »

Hi all together,

I have PHP 4.4 with Mcrypt support installed and I'm creating a crossplatform application which has to crypt and decrypt on different hosts. So I got the problem that if I crypt on the developer host PHP 5.x and decrypt on the PHP 4.4 host the result is not a plain text, it's just a scrambled text (decryption does not work the same). Does anyone had such a problem or does anybody has a solution beside upgrading to PHP 5.x ?

If I have to upgrade then I will loose all potential customers which run PHP 4.x...

I think it's not a padding problem (to solve with trim()) because it's ocurring allways on one machine...
I think it must be something with incompatibility between different versions of php or mcrypt...

Sorry about my English, but I can read manuals better than writing them

Thank's for your help !
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

post code, please.
User avatar
Neron
Forum Newbie
Posts: 5
Joined: Sun Oct 16, 2005 6:11 pm
Location: Bolivia / Switzerland

Sorry, here is the code...

Post by Neron »

Hi here I post the code. It took some time because I don't have an Internet Connection at home...
The two functions encrypt and decrypt

Code: Select all

function encrypt_data($key_chars, $data) {


  // ==============================================================
  // Specify the encryption settings.
  // ==============================================================
  $algorithm  = MCRYPT_BLOWFISH;
  $mode = MCRYPT_MODE_CBC;


  // ==============================================================
  // Open the cipher module.
  // ==============================================================
  $td = mcrypt_module_open($algorithm, '', $mode, '');


  // ==============================================================
  // Determine the keysize length.
  // ==============================================================
  $key_size = mcrypt_enc_get_key_size($td);


  // ==============================================================
  // Create an encryption key.
  // ==============================================================
  $key_string = md5($key_chars).md5(strrev($key_chars));
  $encryption_key = substr($key_string, 0, $key_size);


  // ==============================================================
  // Get the initialization vector size.
  // ==============================================================
  $iv_size = mcrypt_get_iv_size($algorithm, $mode);


  // ==============================================================
  // Check if the host is a windows host.
  // ==============================================================
  if (isset($_SERVER['WINDIR'])) {
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
  } else {
    $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM);
  }


  // ==============================================================
  // Encrypt the data.
  // ==============================================================
  $encrypted_data = mcrypt_encrypt($algorithm, $encryption_key, $data, $mode, $iv);


  // ==============================================================
  // Close the cipher module.
  // ==============================================================
  mcrypt_module_close($td);


  // ==============================================================
  // Encode the data to base64.
  // ==============================================================
  $crypt_array['data'] = base64_encode($encrypted_data);


  // ==============================================================
  // Store the initialization vector in the encrypt array.
  // ==============================================================
  $crypt_array['iv'] = base64_encode($iv);


  // ==============================================================
  // Return the encrypted data to the caller.
  // ==============================================================
  return $crypt_array;
}


function decrypt_data($key_chars, $data, $iv) {


  // ==============================================================
  // Specify the encryption settings.
  // ==============================================================
  $algorithm  = MCRYPT_BLOWFISH;
  $mode = MCRYPT_MODE_CBC;


  // ==============================================================
  // Open the cipher module.
  // ==============================================================
  $td = mcrypt_module_open($algorithm, '', $mode, '');


  // ==============================================================
  // Get the initialization vector size.
  // ==============================================================
  $iv_size = mcrypt_get_iv_size($algorithm, $mode);


  // ==============================================================
  // Decode the iv from base64.
  // ==============================================================
  $iv = base64_decode($iv);


  // ==============================================================
  // Check the initialization vector size.
  // ==============================================================
  if (strlen($iv) == $iv_size) {


    // ============================================================
    // Determine the keysize length.
    // ============================================================
    $key_size = mcrypt_enc_get_key_size($td);


    // ============================================================
    // Create an encryption key.
    // ============================================================
    $key_string = md5($key_chars).md5(strrev($key_chars));
    $encryption_key = substr($key_string, 0, $key_size);


    // ============================================================
    // Decode the data from base64.
    // ============================================================
    $data = base64_decode($data);


    // ============================================================
    // Decrypt the data.
    // ============================================================
    $decoded_data = mcrypt_decrypt($algorithm, $encryption_key, $data, $mode, $iv);
  } else {


    // ============================================================
    // The initialization vector size does not match.
    // ============================================================
    $decoded_data = "fail";
  }


  // ==============================================================
  // Return the decrypted data to the caller.
  // ==============================================================
  return $decoded_data;
}
Thank's a lot and have a nice day !
yum-jelly
Forum Commoner
Posts: 98
Joined: Sat Oct 29, 2005 9:16 pm

Post by yum-jelly »

Your missing your seed call srand();


This...

Code: Select all

if (isset($_SERVER['WINDIR'])) { 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); 
  } else { 
    $iv = mcrypt_create_iv($iv_size, MCRYPT_DEV_URANDOM); 
  }

Should be...

Code: Select all

if ( isset ( $_SERVER['WINDIR'] ) )
{
	srand ( ( double ) microtime () * 1000000 ); // or just, srand(); without the param would also work!

	$iv = mcrypt_create_iv ( $iv_size, MCRYPT_RAND );
}
else
{
	$iv = mcrypt_create_iv ( $iv_size, MCRYPT_DEV_URANDOM );
}

yj
User avatar
Neron
Forum Newbie
Posts: 5
Joined: Sun Oct 16, 2005 6:11 pm
Location: Bolivia / Switzerland

Thank's !

Post by Neron »

Hi !

Thank's for your reply ! That could be the problem because I have read the following on php.net:
Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically.
So if I use it on a system below php 4.2.0 it will not work without srand() ...

Thank's a lot and have a nice day !
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Your missing your seed call srand();
It's still valid even in later versions than 4.2.0, but yep not a requirement I think since that version. Unless mcrypt has special needs?
Post Reply