为什么RijndaelManaged和AesCryptoServiceProvider返回不同的结果? [英] Why are RijndaelManaged and AesCryptoServiceProvider returning different results?

查看:260
本文介绍了为什么RijndaelManaged和AesCryptoServiceProvider返回不同的结果?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我已经运行的例子。它具有相同的模式,填充,块大小,KeySize。我使用相同的初始化向量,密钥和数据。

Here is the example that I have run. It has the same Mode, Padding, BlockSize, KeySize. I am using the same init vector, key and data.

使用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

Using the RijndaelManaged produces an encrypted value of: 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

Using the AesCryptoServiceProvider produces an encrypted value of: 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

以下是用于生成这些结果的代码

Here is the code I used to generate these results



   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;
      }
   }

我想我只是想知道如果我错过了一些东西。

I guess I'm just wondering if I missed something.

更新:原来 AesManaged 将抛出CryptographicException(指定的密码模式对此算法无效),如果您尝试将CipherMode设置为CFB。我觉得 AesCryptoServiceProvider 应该这样做,但它没有。似乎有趣的是,FIPS认证类允许无效的密码模式。

Update: Turns out that AesManaged will throw a CryptographicException ("The specified cipher mode is not valid for this algorithm") if you try and set the CipherMode to CFB. I feel that the AesCryptoServiceProvider should do that same, but it doesnt. Seems funny that the FIPS Certified class allows invalid cipher modes.

推荐答案

来自Microsoft的回复:

Response from Microsoft:

RijndaelManaged class和
AesCryptoServiceProvider 类是两个
的不同实现。
RijndaelManaged class是一种
实现的.net框架中的Rijndael算法
,它不是
在NIST下验证(National
标准与技术研究所)
加密模块验证
程序(CMVP)。

RijndaelManaged class and AesCryptoServiceProvider class are two different implementations. RijndaelManaged class is a kind of implementation of Rijndael algorithm in .net framework, which was not validated under NIST (National Institute of Standards and Technology) Cryptographic Module Validation Program (CMVP).

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

However, AesCryptoServiceProvider class calls the Windows Crypto API, which uses RSAENH.DLL, and has been validated by NIST in CMVP. Although Rijndael algorithm was the winner of the NIST competition to select the algorithm that would become AES, there are some differences between Rijndael and official AES. Therefore, RijndaelManaged class and AesCryptoServiceProvider class have subtle differences on implementation.

此外, RijndaelManaged class
无法提供与AES相当的
实现。
另一个类在.net
框架中实现, AesManaged 类。这个
类只包含固定块大小和
迭代计数的 RijndaelManaged
类来实现AES
标准。然而,它不支持
的反馈大小,特别是当
模式设置为CFB或OFB时,
CryptographicException

In addition, RijndaelManaged class cannot provide an equivalent implementation with AES. There is another class implemented in .net framework, AesManaged class. This class just wrapped RijndaelManaged class with a fixed block size and iteration count to achieve the AES standard. However, it does not support the feedback size, especially, when the mode is set as CFB or OFB, the CryptographicException will be thrown.

有关更多信息,请参阅
以下MSDN文档。

For more information, please refer to the following MSDN documents.

< a href =http://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged.aspx =noreferrer> AesManaged Class 和 AesManaged.Mode属性

如果您要在
应用程序中将标准AES作为
安全算法,建议使用
AesCryptoServiceProvider 类。如果
想在
中混合 RijndaelManged class
AesCryptoServiceProvider 您的应用程序,我们建议您在
程序中使用CBC
模式而不是CFB模式,因为在两个类中的CBC模式执行

相同。

If you want to pick up standard AES as security algorithm in your application, we recommend using the AesCryptoServiceProvider class. If you want to mix the RijndaelManged class and AesCryptoServiceProvider class in your application, we suggest using CBC mode instead of CFB mode in your program, since the implementation of the CBC mode in both classes is the same.

这篇关于为什么RijndaelManaged和AesCryptoServiceProvider返回不同的结果?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆