Kaev
Kaev

Reputation: 31

Rijndael: C++ encryption, C# decryption

My situation: I'm rewriting a server in C# which was written in C++ for learning purposes. At some point the client will send a password to the server which is encrypted. They used the Rijndael encryption for the password. You can find the original encryption class here:

Rijndael.h: https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.h

Rijndael.cpp: https://github.com/astorks/FlyFF/blob/master/Source/_Common/Rijndael.cpp#L926

As you can see in the .cpp-file, they use this key and IV:

char const* CRijndael::sm_chain0 = "\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";

char    szDefaultKey[32] = "dldhsvmflvm";

Here's the part, where they actually decrypt the password in the original server (https://github.com/astorks/FlyFF/blob/master/Source/CERTIFIER/DPCertifier.cpp#L256)

// MAX_PASSWORD is actually 42. So 16*42 = 672 byte
char szEnc[ 16 * MAX_PASSWORD ] = {0, };
char szDec[ 16 * MAX_PASSWORD ] = {0, };

ar.Read( szEnc, 16 * MAX_PASSWORD );

g_xRijndael->ResetChain();
g_xRijndael->Decrypt( szEnc, szDec, 16 * MAX_PASSWORD, CRijndael::CBC );

Now i'm at the part where i correctly get the packet from the client and where i need to decrypt the password. My current C# code doesn't decrypt the data correctly and i can't figure out why. This is my code:

public static class Rijndael
    {
        private static ICryptoTransform decryptor { get; set; }
        private static RijndaelManaged rijndael { get; set; }

        public static void Init()
        {
            byte[] decryptKey = Encoding.ASCII.GetBytes("dldhsvmflvm").Concat(Enumerable.Repeat((byte)0, 21).ToArray()).ToArray();
            byte[] decryptIV = Enumerable.Repeat((byte)0, 16).ToArray();
            // I've tried BlockSize 128 and 256. It actually should be 128 since it's 16 on the original server (16 * 8 = 128)
            rijndael = new RijndaelManaged() { Padding = PaddingMode.Zeros, Mode = CipherMode.CBC, KeySize = 256, BlockSize = 128, Key = decryptKey, IV = decryptIV };
            decryptor = rijndael.CreateDecryptor(decryptKey, decryptIV);
        }


        public static string decrypt(byte[] data)
        {
            string password = null;
            using (MemoryStream ms = new MemoryStream(data))
                using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    using (StreamReader sr = new StreamReader(cs))
                        password = sr.ReadToEnd();
            return password;
        }
    }

They picked 32 bytes at the serverside but only filled them with 11 characters: dldhsvmflvm. That's why i fill the other 21 bytes with 0. 32*8 = 256 Bit = KeySize

I get an error when i would use a IV like byte[32] and fill it with 0. It said smth like the IV doesn't fit to the blocksize. That's why it has 16 bytes now and is filled with 0. Could this be the problem and if so, how could i fix it?

Besides that, i have no idea what could went wrong. Hopefully you can save my day, Stackoverflow. :)

Upvotes: 2

Views: 2819

Answers (1)

Kaev
Kaev

Reputation: 31

As xanatos said i've added 5 Zeros instead instead of 21, because they key should only be 16 bytes instead of 32 bytes. It's working without problems now. Thanks to everyone!

Upvotes: 1

Related Questions