Подтвердить что ты не робот

Почему RijndaelManaged и AesCryptoServiceProvider возвращают разные результаты?

Вот пример, который я выполнил. Он имеет тот же режим, Padding, BlockSize, KeySize. Я использую один и тот же вектор, ключ и данные инициализации.

Использование RijndaelManaged создает зашифрованное значение: 0x8d, 0x81,0x27,0xc6,0x3c, 0xe2,0x53,0x2f, 0x35,0x78,0x90,0xc2,0x2e, 0x3b, 0x8a, 0x61, 0x41,0x47,0xd6,0xd0,0xff, 0x92,0x72,0x3d, 0xc6,0x16,0x2b, 0xd8,0xb5,0xd9,0x12,0x85

Использование AesCryptoServiceProvider создает зашифрованное значение: 0x8d, 0x9F, 0x6e, 0x99,0xe9,0x54,0x8b, 0x12,0xa9,0x88,0x1a, 0x3d, 0x65,0x23,0x9c, 0x4e, 0x18,0x5a, 0x89,0x31,0xf5,0x75,0xc5,0x9e, 0x0D, 0x43,0xe9,0x86,0xd4,0xf3,0x64,0x3a

Вот код, который я использовал для создания этих результатов


   public partial class AesTest
   {
      private SymmetricAlgorithm mEncryptionType;
      private byte[] mPrivateKey;
      private byte[] mInitializationVector;
      private byte[] mData;

      public AesTest()
      {
         mPrivateKey = new byte[32] 
         { 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22,
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22, 
            0x22, 0x22, 0x22, 0x22
         };

         mInitializationVector = new byte[16]
         { 
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33,
            0x33, 0x33, 0x33, 0x33
         };

         mData = new byte[16]
         {
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44,
            0x44, 0x44, 0x44, 0x44
         };

         mEncryptionType = new RijndaelManaged();
         mEncryptionType.Mode = CipherMode.CFB;
         mEncryptionType.Padding = PaddingMode.PKCS7;
         mEncryptionType.BlockSize = 128;
         mEncryptionType.KeySize = 256;

         byte[] rij_encrypted_data = Encrypt(mData);

         mEncryptionType = new AesCryptoServiceProvider();
         mEncryptionType.Mode = CipherMode.CFB;
         mEncryptionType.Padding = PaddingMode.PKCS7;
         mEncryptionType.BlockSize = 128;
         mEncryptionType.KeySize = 256;

         byte[] aes_encrypted_data = Encrypt(mData);
      }

      public virtual byte[] Encrypt(byte[] unencryptedData)
      {
         return TransformData(unencryptedData, mEncryptionType.CreateEncryptor(mPrivateKey, mInitializationVector));
      }

      private byte[] TransformData(byte[] dataToTransform, ICryptoTransform cryptoTransform)
      {
         byte[] result = new byte[0];
         if (dataToTransform != null && cryptoTransform != null && dataToTransform.Length > 0)
         {
            // Create the memory stream to store the results
            MemoryStream mem_stream = new MemoryStream();
            // Create the crypto stream to do the transformation
            CryptoStream crypto_stream = new CryptoStream(mem_stream, cryptoTransform, CryptoStreamMode.Write);
            // bytes are transformed on a write
            crypto_stream.Write(dataToTransform, 0, dataToTransform.Length);
            // Flush the final block
            crypto_stream.FlushFinalBlock();
            // Convert the transformed memory stream back to a byte array
            result = mem_stream.ToArray();
            // Close the streams
            mem_stream.Close();
            crypto_stream.Close();
         }
         return result;
      }
   }

Я думаю, мне просто интересно, не пропустил ли я что-то.

Обновление: Оказывается, что AesManaged выдаст исключение CryptographicException ( "Указанный режим шифрования недействителен для этого алгоритма" ), если вы попытаетесь установить CipherMode в CFB. Я чувствую, что AesCryptoServiceProvider должен делать то же самое, но это не так. Кажется забавным, что класс FIPS Certified допускает неправильные режимы шифрования.

4b9b3361

Ответ 1

Ответ от Microsoft:

RijndaelManaged класс и  Класс AesCryptoServiceProvider - два  различные реализации.  RijndaelManaged класс - это своего рода  реализация алгоритма Рийндаля  в .net framework, который не был  подтверждено в соответствии с NIST (National  Институт стандартов и технологий)  Проверка криптографического модуля  Программа (CMVP).

Однако,  AesCryptoServiceProvider вызовы класса  API Windows Crypto, который использует  RSAENH.DLL, и был подтвержден  NIST в CMVP. Хотя Rijndael  Алгоритм был победителем NIST  конкурс на выбор алгоритма  это будет AES, есть некоторые  различия между Rijndael и  официальный AES. Следовательно,  RijndaelManaged класс и  Класс AesCryptoServiceProvider имеет  тонкие различия в реализации.

Кроме того, класс RijndaelManaged  не может обеспечить эквивалент  реализации с AES. Там есть  другой класс, реализованный в .net  framework, AesManaged. Эта  класс, только что завернутый RijndaelManaged  класс с фиксированным размером блока и  количество итераций для достижения AES  стандарт. Однако он не поддерживает  размер обратной связи, особенно, когда  режим установлен как CFB или OFB,   CryptographicException будет сброшен.

Для получения дополнительной информации см.  следующие документы MSDN.

AesManaged Class и Свойство AesManaged.Mode

Если вы хотите забрать стандартную AES как  алгоритм безопасности в вашем  приложения, мы рекомендуем использовать  AesCryptoServiceProvider. если ты  хотите смешать класс RijndaelManged  и AesCryptoServiceProvider в  ваше приложение, мы предлагаем использовать CBC  вместо режима CFB в вашем  программы, поскольку осуществление  режим CBC в обоих классах  то же самое.

Ответ 2

Я думаю, что это связано с CipherMode.CFB. См. этот пост, описывающий AesManaged:

AesManaged на самом деле просто оболочка вокруг Rinjdael Управляемый с помощью некоторого кода добавлен, чтобы убедиться, что вы не настроить алгоритм для работы в не-AES-совместимый способ. Например, AesManaged не позволяет вам измените размер блока. (Он также будет запретить использование режимов CFB и OFB из-за того, что RijndaelManaged работает с теми режимы).

Обратите внимание, что если вы используете CipherMode.ECB или CipherMode.CBC, вы увидите идентичные результаты. Любая причина, по которой вам нужен CFB, а не CBC?

Ответ 3

Информация о добавлении из этот пост говорит:

По сути, если вы хотите использовать RijndaelManaged как AES, вам необходимо убедиться, что:
1) Размер блока равен 128 бит
2) Вы не используете режим CFB, или если вы размер обратной связи также составляет 128 бит

Хорошо, отлично. Я добавил mEncryptionType.FeedbackSize = 128; к моему приведенному выше примеру, и я получаю CryptographicExecption:

System.Security.Cryptography.CryptographicException was unhandled
  Message="Bad Data.\r\n"
  Source="System.Core"
  StackTrace:
       at System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle key, KeyParameter parameter, Byte[] value)
       at System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle key, KeyParameter parameter, Int32 value)
       at System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey(SafeCapiKeyHandle key, Byte[] iv, CipherMode cipherMode, Int32 feedbackSize)
       at System.Security.Cryptography.CapiSymmetricAlgorithm..ctor(Int32 blockSize, Int32 feedbackSize, SafeCspHandle provider, SafeCapiKeyHandle key, Byte[] iv, CipherMode cipherMode, PaddingMode paddingMode, EncryptionMode encryptionMode)
       at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle key, Byte[] iv)
       at System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(Byte[] key, Byte[] iv)
       at AESTest.Form1.Encrypt(Byte[] unencryptedData) in C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.cs:line 79
       at AESTest.Form1..ctor() in C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.cs:line 73
       at AESTest.Program.Main() in C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Program.cs:line 17

Что-то не так с dll System.Core, которое не поддерживает это, или мне нужно что-то изменить?

С другой стороны, если я изменил значение FeedbackSize на 8 для обоих, это, похоже, сработает! Даже для режима CFB. Поэтому я предполагаю, что мой следующий вопрос: как мне заставить работать 128 (и, надеюсь, это положит конец этому вопросу)?