Saturday, December 6, 2014

PHP mcrypt and C# Encryptor - Encryption and decryption


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:
".$enced."
";
$unced = mc_decrypt($enced, $key, $iv);
echo "Decrypted:
".$unced."
"; 

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)


TAKEN from http://blog.nikoroberts.com/post/45834708375/php-mcrypt-and-c-encryptor  , all credits goes there