Нежелательное поведение с шифрованием RijndaelManaged - PullRequest
3 голосов
/ 10 февраля 2012

У меня странная проблема с 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 голосов
/ 16 марта 2012

Вы не должны использовать GetHashCode() таким образом.Для классов, которые не переопределяют базовую реализацию object.GetHashCode(), он вернет целочисленный обработчик этого конкретного экземпляра.
Поскольку дескриптор для двух разных экземпляров всегда будет отличаться, он никогда не будет совпадать.

ТакжеGetHashCode() на самом деле никогда не гарантирует уникальность, она просто предназначена для использования в качестве легкой предварительной проверки перед проверкой фактического равенства.
Это активно используется в любой структуре хеширования данных, такой как Словарь и т. Д.

Для получения дополнительной информации по этой теме:
http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

Я также выполнил ваш код, и для меня было следующее:

cyper1 == cypher2 and cypher11 == cypher21

Я уверен, чтопроблема была в сравнении GetHashCode().

...