PHP mcrypt and C# Encryptor
For the past day I have been looking for a solution to transfer encrypted information between a PHP web application and a C# desktop application.
This requires that both systems use the same algorithm, key and init vector (IV)
This isn't as easy as it sounds. The slightest difference in the setup of either system means that the encrypted information cannot be decoded on the other end and makes it basically useless.
(The following PHP code has been modified after some useful debugging and comments from Serge N.)
//Encryption function
function mc_encrypt($encrypt, $key, $iv)
{
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $encrypt);
$encode = base64_encode($encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encode;
}
//Decryption function
function mc_decrypt($decrypt, $key, $iv)
{
$decoded = base64_decode($decrypt);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_ECB, '');
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $decoded);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return trim($decrypted);
}
//Usage in PHP
$original = "original message";
$key = "abcdefg_abcdefg_abcdefg_abcdefg_";
$iv = "abcdefg_abcdefg_";
$keysize = 128;
$enced = mc_encrypt(stripslashes($original), $key, $iv);
echo "Encrypted:<br>".$enced."<br>";
$unced = mc_decrypt($enced, $key, $iv);
echo "Decrypted:<br>".$unced."<br>";
That is the PHP code done. We can generate a key and then at any point use the decrypt function to unencode it.
Now the trick is getting the exact same functionality in .NET (with C#)
I found that the class below does it pretty well (this uses the default Rijndael algorithm which is 128 in C#)
public static class Encrypter
{
public static String EncryptIt(String s, byte[] key, byte[] IV)
{
String result;
RijndaelManaged rijn = new RijndaelManaged();
rijn.Mode = CipherMode.ECB;
rijn.Padding = PaddingMode.Zeros;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(s);
}
}
}
result = Convert.ToBase64String(msEncrypt.ToArray());
}
rijn.Clear();
return result;
}
public static String DecryptIt(String s, byte[] key, byte[] IV)
{
String result;
RijndaelManaged rijn = new RijndaelManaged();
rijn.Mode = CipherMode.ECB;
rijn.Padding = PaddingMode.Zeros;
using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(s)))
{
using (ICryptoTransform decryptor = rijn.CreateDecryptor(key, IV))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader swDecrypt = new StreamReader(csDecrypt))
{
result = swDecrypt.ReadToEnd();
}
}
}
}
rijn.Clear();
return result;
}
}
//Usage
Encoding byteEncoder = Encoding.UTF8;
byte[] rijnKey = byteEncoder.GetBytes("abcdefg_abcdefg_abcdefg_abcdefg_");
byte[] rijnIV = byteEncoder.GetBytes("abcdefg_abcdefg_");
String message = "original message";
String encrypted = Encrypter.EncryptIt(message, rijnKey, rijnIV);
String decrypted = Encrypter.DecryptIt(encryption, rijnKey, rijnIV);
Console.WriteLine("Original: "+message);
Console.WriteLine("Encrypted: "+encrypted);
Console.WriteLine("Decrypted: "+decrypted);
I hope this shortens someone's search process when trying to do this.
PS. Yes this is my first try at using the [ code ] containers in Posterous (not the easiest thing in the world but after some tweaking eventually got the code to appear here nicely)

8 Comments
Your example is the first one comprehensive enough for me to understand where I've gone wrong. I've been killing myself over other code examples and the best one I had yielded the same encoding on first glance but with different hashes in php and C#.
This one works like a charm and hashes of encryption are the same.
Thank you.
P.S.
Few minor things -- missing "{" in 12-th line of C# code, and missing "String result;" declaration in Encrypter class, also after copy/paste in front of every line of code there's "#" symbol, just FYI. But that's nothing compared to wasting 2 days trying to find a working piece of code to examine.
$iv = "qwe4592bull2ftw1";
I will see what I can do to find a solution to this problem.
//Encryption function
function mc_encrypt($encrypt, $key, $iv)
{
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $key, $iv);
$encrypted = mcrypt_generic($td, $encrypt);
$encode = base64_encode($encrypted);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return $encode;
}
//Decryption function
function mc_decrypt($decrypt, $key, $iv)
{
$decoded = base64_decode($decrypt);
$td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
mcrypt_generic_init($td, $key, $iv);
$decrypted = mdecrypt_generic($td, $decoded);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
return trim($decrypted);
}
I'm not sure even why this works and yours isn't, with my example. They seem to work in principle just the same. I just reworked your code with examples from PHP manual.
I don't really understand why my code wasn't working, but the whole process seemed pretty difficult, which is why I wrote this in the first place.
Thanks for your help.
By the way if you want to copy the code you just click the "view plain" link at the top of the code section to get the code without the # marks at the beginning of each line.
Leave a Comment