33

这是我运行的示例。它具有相同的 Mode、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;
      }
   }

我想我只是想知道我是否错过了什么。

更新:事实证明,如果您尝试将 CipherMode 设置为 CFB, AesManaged将抛出 CryptographicException(“指定的密码模式对此算法无效”)。我觉得AesCryptoServiceProvider也应该这样做,但事实并非如此。FIPS 认证类允许无效密码模式似乎很有趣。

4

3 回答 3

46

微软的回应:

RijndaelManagedclass 和 AesCryptoServiceProviderclass 是两个不同的实现。 RijndaelManagedclass 是 .net 框架中 Rijndael 算法的一种实现,未在 NIST(美国国家标准与技术研究院)密码模块验证程序(CMVP)下验证。

但是, AesCryptoServiceProvider类调用 Windows Crypto API,它使用 RSAENH.DLL,并已由 NIST 在 CMVP 中验证。尽管 Rijndael 算法是 NIST 竞赛的获胜者,以选择将成为 AES 的算法,但 Rijndael 与官方 AES 之间存在一些差异。因此,RijndaelManaged 类和 AesCryptoServiceProvider类在实现上有细微的差别。

此外,RijndaelManaged类不能提供与 AES 等效的实现。.net 框架中实现了另一个类,AesManagedclass。这个类只是用RijndaelManaged 固定的块大小和迭代次数包装了类,以达到 AES 标准。但是,它不支持反馈大小,特别是当模式设置为 CFB 或 OFB 时, CryptographicException会抛出 。

有关详细信息,请参阅以下 MSDN 文档。

AesManaged 类AesManaged.Mode 属性

如果您想在应用程序中选择标准 AES 作为安全算法,我们建议使用 AesCryptoServiceProvider该类。如果您想在应用程序中混合使用RijndaelManged类和AesCryptoServiceProvider类,我们建议在您的程序中使用 CBC 模式而不是 CFB 模式,因为这两个类中 CBC 模式的实现是相同的。

于 2011-02-01T14:44:07.640 回答
7

我认为这与 CipherMode.CFB 有关。请参阅描述AesManaged的​​这篇文章

AesManaged 实际上只是 RinjdaelManaged 的​​一个包装器,添加了一些代码以确保您不会将算法设置为以非 AES 兼容的方式运行。例如,AesManaged 不允许您更改块大小。(它也将禁止使用 CFB 和 OFB 模式,因为 RijndaelManaged 使用这些模式的方式)。

请注意,如果您使用 CipherMode.ECB 或 CipherMode.CBC,您将看到相同的结果。为什么需要 CFB 而不是 CBC?

于 2009-06-05T18:46:43.443 回答
1

这篇文章的附加信息说:

本质上,如果您想将 RijndaelManaged 用作 AES,您需要确保:
1)块大小设置为 128 位
2)您没有使用 CFB 模式,或者如果您是反馈大小也是 128 位

好的,不错。我添加了 mEncryptionType.FeedbackSize = 128; 到我上面的例子,我得到一个 CryptographicExecption:

System.Security.Cryptography.CryptographicException 未处理
  消息="错误数据。\r\n"
  源="系统.核心"
  堆栈跟踪:
       在 System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle 键,KeyParameter 参数,字节 [] 值)
       在 System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle 键,KeyParameter 参数,Int32 值)
       在 System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey(SafeCapiKeyHandle 密钥,字节 [] iv,CipherMode cipherMode,Int32 反馈大小)
       在 System.Security.Cryptography.CapiSymmetricAlgorithm..ctor(Int32 块大小,Int32 反馈大小,SafeCspHandle 提供程序,SafeCapiKeyHandle 密钥,字节 [] iv,CipherMode cipherMode,PaddingMode paddingMode,EncryptionMode 加密模式)
       在 System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle 密钥,字节 [] iv)
       在 System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(Byte[] key, Byte[] iv)
       在 C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.cs: 79 中的 AESTest.Form1.Encrypt(Byte[] unencryptedData)
       在 C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.cs:line 73 中的 AESTest.Form1..ctor()
       在 C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Program.cs:line 17 中的 AESTest.Program.Main()

不支持此功能的 System.Core dll 是否有问题,或者我是否需要更改其他内容?

附带说明一下,如果我将两者的 FeedbackSize 都更改为 8,它似乎可以工作!即使是 CFB 模式。所以我想我的下一个问题是,我如何让 128 工作(希望这将结束这个问题)?

于 2009-06-08T23:05:47.187 回答