32

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

Использование 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; 
     } 
    } 
 

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

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

+0

Этот вопрос вышел из обсуждения: http://stackoverflow.com/questions/939040/when-will-c-aes-algorithm-be-fips-compliant –

ответ

40

Ответ от Microsoft:

RijndaelManaged класс и AesCryptoServiceProvider класс два различных реализаций. RijndaelManaged класс является своего рода реализации алгоритма Rijndael в .NET Framework, который не был утвержден в соответствии с NIST (Национальный институт стандартов и технологий) Cryptographic Module Validation программы (CMVP).

Однако AesCryptoServiceProvider класса вызывает винда Crypto API, который использует 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 Property

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

6

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

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

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

+0

Да, алгоритм VHDL, который мы приобрели для взаимодействия с программным обеспечением поддерживает только режим CFB. – SwDevMan81

+0

Я предполагаю, что AesCryptoServiceProvider - это тот, который работает с вашим клиентом? –

+0

Да, согласно другому обсуждению, это версия, совместимая с FIPS, которую хочет клиент – SwDevMan81

1
информация

Дополнение от this post говорит:

По существу, если вы хотите использовать 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 что Wouldnt поддерживает это, или мне нужно изменить что-то другое?

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

+0

Если вы можете заставить ее работать с 8, я бы взял ее и запустил :-) –

+0

Желаю, чтобы алгоритм VHDL снова кажется, что поддерживает 128 для FeedbackSize :( – SwDevMan81

+0

Возможно, FeedbackSize выражается в байтах, а не в битах. 8 * 16 = 128. – Cheeso