There's a project written in C# which uses the following code to encrypt/decrypt data to/from database:
public string EncryptString(string Text)
{
byte[] IV = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
string Key = "abcdef";
byte[] buffer = Encoding.UTF8.GetBytes(Text);
TripleDESCryptoServiceProvider triple = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
triple.IV = IV;
triple.Key = md5.ComputeHash(ASCIIEncoding.UTF8.GetBytes(Key));
byte[] encodeText = triple.CreateEncryptor().TransformFinalBlock(buffer, 0, buffer.Length);
string user = Convert.ToBase64String(encodeText);
return user;
}
public static string DecryptString(string EncryptText)
{
byte[] IV = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 };
string Key = "abcdef";
byte[] decodeText = null;
byte[] buffer = Convert.FromBase64String(EncryptText);
TripleDESCryptoServiceProvider triple = new TripleDESCryptoServiceProvider();
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
triple.IV = IV;
triple.Key = md5.ComputeHash(ASCIIEncoding.UTF8.GetBytes(Key));
decodeText = triple.CreateDecryptor().TransformFinalBlock(buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(decodeText);
}
Now I'm supposed to do the same in PHP. So far I came as close as the following code:
define('CIPHER', 'tripledes');
define('MODE', 'cbc');
function Encrypt($data)
{
$iv = chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8);
$key = 'abcdef';
$tripleKey = substr(md5($key), 0, mcrypt_get_key_size(CIPHER, MODE));
$encodedText = mcrypt_encrypt(CIPHER, $tripleKey, $data, MODE, $iv);
return base64_encode($encodedText);
}
function Decrypt($data)
{
$iv = chr(1) . chr(2) . chr(3) . chr(4) . chr(5) . chr(6) . chr(7) . chr(8);
$key = 'abcdef';
$tripleKey = substr(md5($key), 0, mcrypt_get_key_size(CIPHER, MODE));
$decodedText = mcrypt_decrypt(CIPHER, $tripleKey, base64_decode($data), MODE, $iv);
return $decodedText;
}
But I can not decrypt a string encrypted by the C#'s code! I'm no encryption expert, could someone please tell me which encryption algorithm and which mode should I use?
Your main problem lies in the handling of the key. One issue is trivial: In PHP, the
md5
function by default returns a hexadecimal dump of the hash, while you need the raw binary value to match C#’sMD5CryptoServiceProvider.ComputeHash()
. For that, just add onetrue
parameter to the PHP call (md5(key, true)
).The other issue is a tiny bit more complicated: MD5 returns a 128-bit hash, while 3DES uses a 192-bit key (actually, 168-bit of key with the rest being parity bits, but let’s ignore that here). When you supply a too short key to the PHP implementation, it pads the key using zero bytes; however the .NET/CSP implementation of 3DES seems to repeat the key bytes from the beginning (wrapping the key around). Therefore, to match the .NET behavior in PHP, you need to wrap the key manually (
$key . $key
).And the final issue is padding: PHP pads the data using zeros, while .NET uses PKCS#7 padding by default. If you need to handle padding correctly, you need to add it when encrypting, and remove it when decrypting.
But, as a commentator above has already said, this is not really a good cryptographic implementation for many reasons. (And my implementation of the tweaks is not really hardened, either.)