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.
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!