3

I am experiencing a strange problem with RijndaelManaged. Basically I have a new instance of it where I set up the CipherMode, Padding, IV and Key. Then I create another instance and assign the same values of the following properties from the original instance to the 2nd instance: Mode, Padding, KeySize, FeedbackSize, BlockSize, IV and Key.

So, having copied ALL property values from instance 1 to instance 2 I should get the same results, right? WRONG! the GetHashCode() of both instances differ somehow, but if I dump their properties (named above) then they are all the same.

If I encrypt a string of text with a length equal to the block size (16 bytes, 128 bits) then both produce the same result, if the input is less than BlockSize then the encryption results are NOT the same.

I have this to create the initial Rijndael instance.

    public static RijndaelManaged CreateSymmetricKey(string passphrase)
    {
        RijndaelManaged symCrypto = new RijndaelManaged();
        symCrypto.Mode = CipherMode.CBC;               
        symCrypto.Padding = PaddingMode.PKCS7;
        byte[] salt = Encoding.UTF8.GetBytes("dummy dummy dummy dummy test");
        Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(passphrase, salt);
        symCrypto.Key = key.GetBytes(symCrypto.KeySize / 8);
        symCrypto.IV = key.GetBytes(symCrypto.BlockSize / 8);

        return symCrypto;
    }

To encrypt the string for the sake of an example:

private string Encrypt(RijndaelManaged rm, string text)
    {
        byte[] encrypted;
        // Create a decrytor to perform the stream transform.
            ICryptoTransform encryptor = rm.CreateEncryptor(rm.Key, rm.IV);
        using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(text);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        return BitConverter.ToString(encrypted);
    }

So then do this

RijndaelManaged rm1 = CreateSymmetricKey("there is something weird happening");
RijndaelManaged rm2 = new RijndaelManaged();
// copy ALL public properties to the new instance so that it has the same parameters
rm2.BlockSize = rm1.BlockSize; // 128
rm2.FeedbackSize = rm1.FeedbackSize; // 128
rm2.KeySize = rm1.KeySize; // 256
rm2.Mode = rm1.Mode; // CBC
rm2.Padding = rm1.Padding; // PKCS7
rm2.IV = rm1.IV;
rm2.Key = rm1.Key;
// Encryption
string cypher1 = Encrypt(rm1, "this is a test 6");  // length equal to BlockSize
string cypher2 = Encrypt(rm2, "this is a test 6");  // length equal to BlockSize
string cypher11 = Encrypt(rm1, "this is a test");  // length less than BlockSize
string cypher21 = Encrypt(rm2, "this is a test");  // length less than BlockSize

I am getting that cyper1 == cypher2 and cypher11 != cypher21 also rm1.GetHashCode() != rm2.GetHashCode() yet all public parameters are the same!

I also dumped all the public properties of both instances to see if I was missing something but not, all values are the same.

Lord of Scripts
  • 3,579
  • 5
  • 41
  • 62

1 Answers1

0

You should not use GetHashCode() in this way. For classes that did not override the base object.GetHashCode() implementation, it will return the integer handler of this specific instance.
Since the handle for two different instances will always be different this will never match.

Also GetHashCode() never actually guarantees uniqueness, it's merely meant to be used as a light weight pre check, before the actual equality is tested.
This is heavily used in any kind of Hashing data structure like Dictionary etc.

For more info on this topic:
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

I also executed your code and for me the following was the case:

cyper1 == cypher2 and cypher11 == cypher21

I'm pretty sure the issue was the comparison of GetHashCode().

ntziolis
  • 10,091
  • 1
  • 34
  • 50