8

I have written the same methods in two platforms which I believe should result same thing but its not happening. I have encrypted the same text with same key which result different. Can someone figure it out why is it happening ?

String: this is test

Key: 1234567812345678

PHP encrypted string: ybUaKwQlRNwOjJhxLWtLYQ==

C# encrypted string: r2YjEFPyDDacnPmDFcGTLA==

C# functions

static string Encrypt(string plainText, string key)
{
    string cipherText;
    var rijndael = new RijndaelManaged()
    {
        Key = Encoding.UTF8.GetBytes(key),
        Mode = CipherMode.ECB,
        BlockSize = 128,
    };
    ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, rijndael.IV);

    using (var memoryStream = new MemoryStream())
    {
        using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
        {
            using (var streamWriter = new StreamWriter(cryptoStream))
            {
                streamWriter.Write(plainText);
                streamWriter.Flush();
            }
            cipherText = Convert.ToBase64String(memoryStream.ToArray());
            //cryptoStream.FlushFinalBlock();
        }
    }
    return cipherText;
}

private static string Decrypt(string cipherText, string key)
{
    string plainText;
    byte[] cipherArray = Convert.FromBase64String(cipherText);
    var rijndael = new RijndaelManaged()
    {
        Key = Encoding.UTF8.GetBytes(key),
        Mode = CipherMode.ECB,
        BlockSize = 128
    };
    ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

    using (var memoryStream = new MemoryStream(cipherArray))
    {
        using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
        {
            using (var streamReader = new StreamReader(cryptoStream))
            {
                plainText = streamReader.ReadToEnd();
            }
        }
    }
    return plainText;
}

PHP functions

function string_encrypt($string, $key) {
    $crypted_text = mcrypt_encrypt(
                            MCRYPT_RIJNDAEL_128, 
                            $key, 
                            $string, 
                            MCRYPT_MODE_ECB
                        );
    return base64_encode($crypted_text);
}

function string_decrypt($encrypted_string, $key) {
    return mcrypt_decrypt(
                    MCRYPT_RIJNDAEL_128, 
                    $key, 
                    base64_decode($encrypted_string), 
                    MCRYPT_MODE_ECB
                    );
}

I am not so good in C# and I know the PHP function is working fine. So, there must be something done on C# functions. May be the string to be encrypted should converted to Latin chars.

4
  • Is there anything wrong with the answer you have been given hsuk? It seems rather extensive... Commented Sep 22, 2013 at 12:16
  • Actually I don't want to change my PHP function ... Commented Sep 22, 2013 at 15:57
  • 1
    What about the second block of code written by StigM? That looks like C# to me. He first showed you the correct way, and then the way to make C# comply with the braindead PHP mcrypt_decrypt functionality. Commented Sep 22, 2013 at 16:25
  • Also note that you should explicitly define the character-encoding to be used within both PHP and C#. Also note that keys and passwords are not the same, and that ECB mode is not secure for encrypting text (or for most data, really). Commented Sep 22, 2013 at 16:27

1 Answer 1

8

C# does Rijndael padding by default and uses PKCS7.

This means you have to pad your PHP side as per PKCS7, code below should work:

function string_encrypt($string, $key) {

  $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
  $padding = $block - (strlen($string) % $block);
  $string .= str_repeat(chr($padding), $padding);

    $crypted_text = mcrypt_encrypt(
                            MCRYPT_RIJNDAEL_128, 
                            $key, 
                            $string, 
                            MCRYPT_MODE_ECB
                        );
    return base64_encode($crypted_text);
}

For further information, see the first answer here

I should add also, that if you want to change the C# side and not use padding, make the below modification instead and leave the PHP side alone:

static string Encrypt(string plainText, string key)
{
  string cipherText;
  var rijndael = new RijndaelManaged()
  {
    Key = Encoding.UTF8.GetBytes(key),
    Mode = CipherMode.ECB,
    BlockSize = 128,
    Padding = PaddingMode.Zeros,
  };
  ICryptoTransform encryptor = rijndael.CreateEncryptor(rijndael.Key, null);

  using (var memoryStream = new MemoryStream())
  {
    using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
    {
      using (var streamWriter = new StreamWriter(cryptoStream))
      {
        streamWriter.Write(plainText);
        streamWriter.Flush();
      }
      //cipherText = Convert.ToBase64String(Encoding.UTF8.GetBytes(Encoding.UTF8.GetString(memoryStream.ToArray())));
      cipherText = Convert.ToBase64String(memoryStream.ToArray());
      //cryptoStream.FlushFinalBlock();
    }
  }
  return cipherText;
}
Sign up to request clarification or add additional context in comments.

1 Comment

It would be great if the PaddingMode.Zeros was more prominent in this answer. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.