Рейндаэль: та же строка, разные результаты - PullRequest
4 голосов
/ 04 августа 2011

У нас было небольшое настольное приложение, которое теперь необходимо предоставить в виде веб-функции (.Net). Это приложение содержит некоторый код для шифрования и использует классы Rijndael из .Net Framework. Код принимает входную строку, шифрует ее и записывает результаты в файл. Поскольку весь код содержится в одном классе, я просто скопировал этот класс в свое приложение веб-службы. Когда я зашифровываю одну и ту же строку с использованием одного и того же ключа в исходном приложении и новом приложении, результаты отличаются. Строка результата, заданная исходным приложением, является подмножеством строки результата, заданной моим веб-сервисом. Последний имеет дополнительные символы в конце зашифрованной строки.

Ниже приведен код, который я использую. Обратите внимание, что я не разработал этот код, и я не понимаю его полностью. Есть мысли о разнице в поведении? Пожалуйста, помогите !!

Вот код, который получает пользовательский ввод и вызывает шифратор.

    public void EncryptDomain(string EncryptValue, string outputDomainFile)
    {
            if (EncryptValue.Length > 0)
            {
                if ((outputDomainFile != null) && (outputDomainFile.Length > 0))
                {
                    _outputDomainFile = outputDomainFile;
                }

                byte[] input = Encoding.UTF8.GetBytes(EncryptValue);

                Transform(input, TransformType.ENCRYPT);

            }

Это код шифра:

    private byte[] Transform(byte[] input, TransformType transformType)
    {
        CryptoStream cryptoStream = null;      // Stream used to encrypt
        RijndaelManaged rijndael = null;        // Rijndael provider
        ICryptoTransform rijndaelTransform = null;// Encrypting object            
        FileStream fsIn = null;                 //input file
        FileStream fsOut = null;                //output file
        MemoryStream memStream = null;          // Stream to contain data
        try
        {
            // Create the crypto objects
            rijndael = new RijndaelManaged();
            rijndael.Key = this._Key;
            rijndael.IV = this._IV;
            rijndael.Padding = PaddingMode.Zeros;   

            if (transformType == TransformType.ENCRYPT)
            {
                rijndaelTransform = rijndael.CreateEncryptor();
            }
            else
            {
                rijndaelTransform = rijndael.CreateDecryptor();
            }

            if ((input != null) && (input.Length > 0))
            {
                //memStream = new MemoryStream();
                //string outputDomainFile = 
                FileStream fsOutDomain = new FileStream(_outputDomainFile,
                                            FileMode.OpenOrCreate, FileAccess.Write);

                cryptoStream = new CryptoStream(
                     fsOutDomain, rijndaelTransform, CryptoStreamMode.Write);

                cryptoStream.Write(input, 0, input.Length);

                cryptoStream.FlushFinalBlock();

                //return memStream.ToArray();
                return null;
            }
            return null;

        }
        catch (CryptographicException)
        {
            throw new CryptographicException("Password is invalid. Please verify once again.");
        }
        finally
        {
            if (rijndael != null) rijndael.Clear();
            if (rijndaelTransform != null) rijndaelTransform.Dispose();
            if (cryptoStream != null) cryptoStream.Close();
            if (memStream != null) memStream.Close();
            if (fsOut != null) fsOut.Close();
            if (fsIn != null) fsIn.Close();
        }
 }

Код, который устанавливает значения IV:

    private void GenerateKey(string SecretPhrase)
    {
        // Initialize internal values
        this._Key = new byte[24];
        this._IV = new byte[16];

        // Perform a hash operation using the phrase.  This will 
        // generate a unique 32 character value to be used as the key.
        byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);
        SHA384Managed sha384 = new SHA384Managed();
        sha384.ComputeHash(bytePhrase);
        byte[] result = sha384.Hash;

        // Transfer the first 24 characters of the hashed value to the key
        // and the remaining 8 characters to the intialization vector.
        for (int loop = 0; loop < 24; loop++) this._Key[loop] = result[loop];
        for (int loop = 24; loop < 40; loop++) this._IV[loop - 24] = result[loop];
    }

Ответы [ 2 ]

3 голосов
/ 31 октября 2011

Это классическая ошибка.Независимо от того, генерируете ли вы IV самостоятельно, Rijndael (AES) предоставит его вам.Хитрость заключается в том, чтобы всегда сохранять IV (в RijndaelManaged есть геттер).

  • Когда вы расшифровываете, вам нужно передать оба ключа и IV .

Если вы сохраняете данные в файл или базу данных, вы можете сохранить IV в виде простого текста.Вы даже можете передать IV по проводам (сеть, интернет) в виде простого текста.Злоумышленник не сможет (насколько я знаю) взломать ваш шифр, основываясь только на IV.Передача или хранение IV обычно выполняется путем добавления префикса перед зашифрованным текстом или добавления его в конце.(объединяя две строки)

например, CiphertextIV или IVCiphertext.(помните, что IV находится в незашифрованном виде, если он должен быть фиксированной длины, что облегчает разделение при получении для расшифровки или для вставки базы данных)

Итак, если ваш ключ имеет значение ABCDEFABCDEFABCD , а ваш IV - это ABCDEF0123456789 и этот открытый текст: 'это какой-то секретный текст' (скажем) создает шифр, например: abcd1234abcd00

Youбудет передавать (или хранить) как это: ABCDEF0123456789abcd1234abcd00

3 голосов
/ 04 августа 2011

Я думаю, это из-за IV (Вектор инициализации)

...