Почему RijndaelManaged и AesCryptoServiceProvider возвращают разные результаты? - PullRequest
33 голосов
/ 05 июня 2009

Вот пример, который я запустил. Он имеет тот же режим, 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 допускает недопустимые режимы шифрования.

Ответы [ 3 ]

45 голосов
/ 01 февраля 2011

Ответ от Microsoft:

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

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

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

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

Класс AesManaged и Свойство AesManaged.Mode

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

7 голосов
/ 05 июня 2009

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

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

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

1 голос
/ 09 июня 2009

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

По сути, если вы хотите использовать 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 (и, надеюсь, это положит конец этому вопросу)?

...