Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How are my C# and PHP decryption methods different?

I've inherited some C# code and need to port it to PHP. Here it is:

string key = "some key";
string strEncrypted = "some encrypted string";

byte[] hashedKey = new MD5CryptoServiceProvider().ComputeHash(UTF8Encoding.UTF8.GetBytes(key));
byte[] strToDecrypt = Convert.FromBase64String(strEncrypted);

TripleDESCryptoServiceProvider tripleDES = new TripleDESCryptoServiceProvider();
tripleDES.Key = hashedKey;
tripleDES.Mode = CipherMode.ECB;

string strDecrypted = UTF8Encoding.UTF8.GetString(tripleDES.CreateDecryptor().TransformFinalBlock(strToDecrypt, 0, strToDecrypt.Length));

My PHP code looks like this:

$key = 'some key';
$str_encrypted = 'some encrypted string';

$hashed_key = md5($key, TRUE);
$str_to_decrypt = base64_decode($str_encrypted);

// The IV isn't used for ECB, but it prevents a warning.
$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_TRIPLEDES, MCRYPT_MODE_ECB), MCRYPT_RAND); 

$str_decrypted = mcrypt_decrypt(MCRYPT_TRIPLEDES, $hashed_key, $str_to_decrypt, MCRYPT_MODE_ECB, $iv);

But the two decrypted values are not the same, and I can't figure out why. I've read a lot of similar questions here and elsewhere, but none of them seem to explain the issue I'm having.

I'd really appreciate any help in figuring out why the decrypted PHP string doesn't match the decrypted C# string.

like image 470
matthewwithanm Avatar asked Sep 17 '10 22:09

matthewwithanm


2 Answers

You might want to review this forum: http://forums.asp.net/t/1498290.aspx Apparently someone last year had what appears to be the exact same problem.

From that site it looks like the C# stuff should be UTF-7 encoded.. Not UTF-8.

like image 87
NotMe Avatar answered Oct 23 '22 12:10

NotMe


I finally managed to find the answer in a comment on the Mcrypt page of the PHP manual:

When using 3DES between PHP and C#, it is to be noted that there are subtle differences that if not strictly observed, will result in annoying problem encrypt/decrypt data.

1), When using a 16 bytes key, php and c# generates total different outcome string. it seems that a 24 bytes key is required for php and c# to work alike.

2), php doesnt have a "padding" option, while c# has 3 (?). My work around is to add nulls i.e. chr(0) to the end of the source string to make its size times of 8, while in c#, PaddingMode.Zeros is required.

3) the key size has to be times of 8, in php, to make it work for c#.

The key point here is #1. Since the key used is the result of md5 hashing, it'll be 16 bytes. If instead I use a 24-byte key to encrypt (and then decrypt) everything is hunky-dory.

So far, I haven't been able to find an explanation of why 16-byte keys produce a different result (or whether there's a workaround). If you've got any info about that, please share!

like image 24
matthewwithanm Avatar answered Oct 23 '22 10:10

matthewwithanm