Search This Blog

Loading...

Wednesday, June 24, 2009

How to Encrypt a String in .Net and Decrypt it Using mcrypt_encrypt in PHP

Sometimes you have to encrypt a string using .Net library, and decrypt it back in PHP, or vice versa, or across other languages. I have a webservice which is written in PHP and a .Net program that calls the webservice. In the exchange I would have to encrypt a string at .Net's end and decrypt it in PHP end.

The encryption and decryption in .Net is pretty straightforward; all you have to use is the Cryptography library in .Net.  Examples are abound on Internet, so you don't have to crack your head to find a working solution and modify them to suit your needs. Similarly, it's easy if you want to do encryption and decryption in PHP.

But to get encryption and decryption thing to work on different languages can be a bit tricky. I have spent quite a lot of time to make things to work. So here I am now posting my code, and hope that it will help other people.

Encryption in .Net. In this example I take a string, and convert it into encrypted hexadecimal string.

private static string CreateEncryptedString(string myString, string hexiv, string key)
        {
            RijndaelManaged alg = new RijndaelManaged();
            alg.Padding = PaddingMode.Zeros;
            alg.Mode = CipherMode.CBC;
            alg.BlockSize = 16 * 8;
            alg.Key = ASCIIEncoding.UTF8.GetBytes(key);
            alg.IV = StringToByteArray(hexiv);
            ICryptoTransform encryptor = alg.CreateEncryptor(alg.Key, alg.IV);

            MemoryStream msStream = new MemoryStream();
            CryptoStream mCSWriter = new CryptoStream(msStream, encryptor, CryptoStreamMode.Write);
            StreamWriter mSWriter = new StreamWriter(mCSWriter);
            mSWriter.Write(myString);
            mSWriter.Flush();
            mCSWriter.FlushFinalBlock();

            var EncryptedByte = new byte[msStream.Length];
            msStream.Position = 0;
            msStream.Read(EncryptedByte, 0, (int)msStream.Length);

            return ByteArrayToHexString(EncryptedByte);
          
        }
        public static byte[] StringToByteArray(String hex)
        {
            int NumberChars = hex.Length;
            byte[] bytes = new byte[NumberChars / 2];
            for (int i = 0; i < NumberChars; i += 2)
                bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
            return bytes;
        }
        public static string ByteArrayToHexString(byte[] ba)
        {
            StringBuilder hex = new StringBuilder(ba.Length * 2);
            foreach (byte b in ba)
                hex.AppendFormat("{0:x2}", b);
            return hex.ToString();
        }
There is one thing to note. The key size must be 16. Which means that key parameter must be a string with 16 characters. Or else the encryption won't work and will throw a System.Security.Cryptography.CryptographicException : Specified key is not a valid size for this algorithm exception. Also note that the hexiv must be a hexadecimal string with 32 characters, meaning that every character inside the hexiv must be hexadecimal (0-9, a-f).

On the PHP end, here's how you do the decoding:
$cipher_alg = MCRYPT_RIJNDAEL_128;
$decrypted_string = mcrypt_decrypt($cipher_alg, $key, 
$encrypted_string , MCRYPT_MODE_CBC, trim(hex2bin(trim($hexiv))));

Where $encrypted_string is the encrypted string returned by the above function, and the hexiv is the same as the hexiv in the .Net code.

3 comments:

Anonymous said...

Can you explain the full php-code?

Anonymous said...

As it is impossible by the way.

PHP Web Development said...

This seems very useful and easy to use.I'll try this first.