0

I'm unable to make the C# RijndaelManaged encryption work with PHP mcrypt_encrypt as I kept getting "Specified key is not a valid size for this algorithm".

The PHP specification use 256 bit, with ECB cipher mode. My understanding is Initization Vector is not used when in ECB mode.

We're using temporary key to get this working in development project, to keep on building the developmental application and we'll issue a new secure key much later.

[PHP]
$plaintext = '1~ABCDEFG~1408740350~0~';

for($i = 1; $i <= 32; $i++) { $key .= chr($i); }

$encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $plaintext, 'ecb', '');


[C#]
string postFormData = "1~ABCDEFG~1408740350~0~";
StringBuilder sb = new StringBuilder();
foreach (var b in Encoding.ASCII.GetBytes(String.Concat(Enumerable.Range(1, 32)))) { sb.AppendFormat("{0}", b); }
postedFormData = RijndaelAES.Encrypt(postedFormData, sb.ToString());

public static string Encrypt(string plainText, string key)
{
    string cipherText;
    var rijndael = new RijndaelManaged()
    {
        Key = Encoding.UTF8.GetBytes(key),
        Mode = CipherMode.ECB,
        BlockSize = 256, //128,
        Padding = PaddingMode.Zeros//, 
        //IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
    };
    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(memoryStream.ToArray());
        }
    }
    return cipherText;
}
fletchsod
  • 3,560
  • 7
  • 39
  • 65
  • http://simpledotnetsolutions.wordpress.com/2012/03/22/using-rijndaelmanaged-to-encryptdecrypt/ – Donal Aug 25 '14 at 21:27
  • `for($i = 1; $i <= 32; $i++) { $key .= chr($i); }` is not the same thing as `foreach (var b in Encoding.ASCII.GetBytes(String.Concat(Enumerable.Range(1, 32))))`. If instead of using this looping method in your PHP can you hardcode a fixed, non calculated key you can copy and paste? – Scott Chamberlain Aug 25 '14 at 21:32
  • I have a previous answer on this. check out: http://stackoverflow.com/questions/11873878/c-sharp-encryption-to-php-decryption I marked the answer that helped me get there, but the complete solution is below that. – solidau Aug 25 '14 at 21:34
  • @Juventus18 I noticed it's using CBC Cipher Mode, not ECB Cipher Mode. – fletchsod Aug 25 '14 at 21:42
  • @ScottChamberlain - We're not using PHP script but a programmer from different company is using it. As for the PHP looping, I look it up and the chr() change the number to ASCII code. – fletchsod Aug 25 '14 at 21:46
  • 1
    @fletchsod yes that is what the PHP function does, but that is not what `String.Concat(Enumerable.Range(1, 32))` does. That will give you "123..." where you need "\0x1\0x2\0x3...". you don't need strings at all in your C# code, just make a `byte[32] key;` and do `for(int i = 0; i < 32; i++) { key[i] = i + 1; }` – Scott Chamberlain Aug 25 '14 at 22:13
  • did you try it with ECB? I almost positive it should work if you change the mode and set the proper block size. I would recommend against using ECB anyway (unless it is a strict requirement) because it is less secure than CBC, see https://www.adayinthelifeof.nl/2010/12/08/encryption-operating-modes-ecb-vs-cbc/ – solidau Aug 25 '14 at 23:08
  • Don't forget to ask a question. That you cannot get your program working is a fact, not a question. Ask a question! – Eric Lippert Aug 26 '14 at 01:09

1 Answers1

1

Rijndael/AES has a fixed block size of 128 (in all implementations). You probably meant to set the key size, not the block size.

Also, the way you convert the key to bytes is highly unusual (it is amazing, actually). I don't think you really understand encodings. This is an important topic to research. Probably, that PHP version is assuming the string to be ASCII. In C#, you can do it like this:

string keyStr = ...;
Debug.Assert(keyStr.Length == (256 / 8));

byte[] keyBytesASCII = Encoding.ASCII.GetBytes(keyStr);
Debug.Assert(keyBytesASCII.Length == (256 / 8));
Debug.Assert(keyBytesASCII.Length == keyStr.Length);

In the future you can debug problems like this by looking at important values using the debugger. I think you'd find that the key you set is not of the expected length.

usr
  • 168,620
  • 35
  • 240
  • 369