繁体   English   中英

为什么RijndaelManaged和AesCryptoServiceProvider会返回不同的结果?

[英]Why are RijndaelManaged and AesCryptoServiceProvider returning different results?

这是我运行的例子。 它具有相同的Mode,Padding,BlockSize,KeySize。 我使用相同的init向量,密钥和数据。

使用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认证课程允许无效的密码模式。

来自Microsoft的回复:

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

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

此外, RijndaelManaged类无法提供与AES等效的实现。 在.net框架中实现了另一个类, AesManaged类。 这个类只是用固定的块大小和迭代次数包装RijndaelManaged类来实现AES标准。 但是,它不支持反馈大小,尤其是当模式设置为CFB或OFB时,将抛出CryptographicException

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

AesManaged类AesManaged.Mode属性

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

我认为它与CipherMode.CFB有关。 这篇描述AesManaged的帖子

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

请注意,如果您使用CipherMode.ECB或CipherMode.CBC,您将看到相同的结果。 你需要CFB而不是CBC的任何理由?

这篇文章的补充信息说:

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

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

\n System.Security.Cryptography.CryptographicException未处理\n   消息=“错误数据。\\ r \\ n”\n   来源= “System.Core程序”\n   堆栈跟踪:\n        在System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle键,KeyParameter参数,Byte []值)\n        在System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle键,KeyParameter参数,Int32值)\n        在System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey(SafeCapiKeyHandle键,Byte [] iv,CipherMode cipherMode,Int32 feedbackSize)\n        在System.Security.Cryptography.CapiSymmetricAlgorithm..ctor(Int32 blockSize,Int32 feedbackSize,SafeCspHandle提供程序,SafeCapiKeyHandle键,Byte [] iv,CipherMode cipherMode,PaddingMode paddingMode,EncryptionMode encryptionMode)\n        在System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle key,Byte [] iv)\n        在System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(Byte []键,Byte [] iv)\n        at AESTest.Form1.Encrypt(Byte [] unencryptedData)在C:\\ Documents and Settings \\ nschoonmaker \\ My Documents \\ Visual Studio 2005 \\ Projects \\ AESTest \\ AESTest \\ Form1.cs:第79行\n        在C:\\ Documents and Settings \\ nschoonmaker \\ My Documents \\ Visual Studio 2005 \\ Projects \\ AESTest \\ AESTest \\ Form1.cs中的AESTest.Form1..ctor():第73行\n        在C:\\ Documents and Settings \\ nschoonmaker \\ My Documents \\ Visual Studio 2005 \\ Projects \\ AESTest \\ AESTest \\ Program.cs中的AESTest.Program.Main():第17行\n

System.Core dll是否有什么问题不支持这个,或者我是否需要更改其他内容?

另外,如果我将FeedbackSize更改为8,它似乎工作! 即使是CFB模式。 所以我想我的下一个问题是,如何让128工作(希望这会结束这个问题)?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM