RijndaelManaged加密的行为不一致

时间:2012-02-09 21:36:43

标签: c# encryption rijndael encryption-symmetric

我遇到了RijndaelManaged的一个奇怪问题。基本上我有一个新的实例,我设置了CipherMode,Padding,IV和Key。然后我创建另一个实例,并将以下属性的相同值从原始实例分配给第二个实例:Mode,Padding,KeySize,FeedbackSize,BlockSize,IV和Key。

因此,将所有属性值从实例1复制到实例2我应该得到相同的结果,对吧?错误!两个实例的GetHashCode()在某种程度上有所不同,但如果我转储它们的属性(如上所述),那么它们都是相同的。

如果我加密长度等于块大小(16字节,128位)的文本字符串,则两者都产生相同的结果,如果输入小于BlockSize,则加密结果不相同。

我有这个来创建最初的Rijndael实例。

    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;
    }

为了示例,要加密字符串:

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);
    }

然后这样做

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

我得到的是cyper1 == cypher2和cypher11!= cypher21也是rm1.GetHashCode()!= rm2.GetHashCode()但所有公共参数都是一样的!

我还抛弃了两个实例的所有公共属性,看看我是否遗漏了一些东西但是没有,所有的值都是一样的。

1 个答案:

答案 0 :(得分:0)

您不应该以这种方式使用GetHashCode()。对于未覆盖基本object.GetHashCode()实现的类,它将返回此特定实例的整数处理程序 由于两个不同实例的句柄总是不同,因此永远不会匹配。

同样GetHashCode()从未真正保证唯一性,它仅仅意味着在测试实际相等性之前用作轻量级预检。
这大量用于任何类型的Hashing数据结构,如Dictionary等。

有关此主题的更多信息:
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

我也执行了你的代码,对我而言,情况如下:

cyper1 == cypher2 and cypher11 == cypher21

我很确定问题是GetHashCode()的比较。