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

发布于 2024-07-22 10:03:54 字数 3813 浏览 4 评论 0原文

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

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

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

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.

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

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

猫九 2024-07-29 10:03:54

Microsoft 的回应:

RijndaelManaged 类和
AesCryptoServiceProvider 类有两个
不同的实现。
RijndaelManaged 类是一种
Rijndael算法的实现
在.net框架中,这不是
经 NIST(国家标准技术研究院)验证
标准与技术研究所)
加密模块验证
计划(CMVP)。

然而,
AesCryptoServiceProvider 类调用
Windows Crypto API,它使用
RSAENH.DLL,并已通过验证
NIST 的 CMVP。 虽然莱因达尔
算法是 NIST 的获胜者
竞争选择算法
这将成为 AES,有一些
Rijndael 和 Rijndael 之间的区别
官方 AES。 所以,
Rijndael管理类和
AesCryptoServiceProvider 类有
实施上的细微差别。

另外,RijndaelManaged
无法提供同等的
使用 AES 实施。 有
.net 中实现的另一个类
框架,AesManaged 类。 这
刚刚包装的类RijndaelManaged
具有固定块大小的类和
实现 AES 的迭代次数
标准。 但是,它不支持
反馈大小,特别是当
模式设置为CFB或OFB时,
将抛出CryptographicException

欲了解更多信息,请参阅
以下 MSDN 文档。

AesManaged 类AesManaged.Mode 属性

如果您想选择标准 AES 作为
您的安全算法
应用程序,我们建议使用
AesCryptoServiceProvider 类。 如果你
想要混合 RijndaelManged
AesCryptoServiceProvider
您的应用程序,我们建议使用 CBC
模式而不是 CFB 模式
方案自实施以来
两类中的 CBC 模式都是
相同的。

Response from Microsoft:

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).

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.

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.

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

AesManaged Class and AesManaged.Mode Property

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.

痴者 2024-07-29 10:03:54

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

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

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

I think it has to do with the CipherMode.CFB. See this post describing AesManaged:

AesManaged is actually just a wrapper
around RinjdaelManaged with some code
added to make sure that you do not
setup the algorithm to operate in a
non-AES compatible way. For instance,
AesManaged does not allow you to
change the block size. (It will also
disallow the use of CFB and OFB mode
because of the way that
RijndaelManaged works with those
modes).

Note that if you use CipherMode.ECB or CipherMode.CBC, you'll see identical results. Any reason why you need CFB and not CBC?

过期情话 2024-07-29 10:03:54

来自 此的附加信息帖子 说:

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

太好了。 我添加了 mEncryptionType.FeedbackSize = 128; 对于上面的示例,我得到一个 CryptographicExecption:

System.Security.Cryptography.CryptographyException was unhandled 
    消息=“错误数据。\r\n” 
    来源=“系统核心” 
    堆栈跟踪: 
         在 System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle 密钥、KeyParameter 参数、Byte[] 值) 
         在 System.Security.Cryptography.CapiNative.SetKeyParameter(SafeCapiKeyHandle 密钥、KeyParameter 参数、Int32 值) 
         在 System.Security.Cryptography.CapiSymmetricAlgorithm.SetupKey(SafeCapiKeyHandle 密钥,Byte[] iv,CipherMode cipherMode,Int32 FeedbackSize) 
         在 System.Security.Cryptography.CapiSymmetricAlgorithm..ctor(Int32 blockSize、Int32 FeedbackSize、SafeCspHandle 提供程序、SafeCapiKeyHandle 密钥、Byte[] iv、CipherMode cipherMode、PaddingMode paddingMode、EncryptionMode 加密模式) 
         在 System.Security.Cryptography.AesCryptoServiceProvider.CreateEncryptor(SafeCapiKeyHandle 密钥,Byte[] 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 中的 AESTest.Form1.Encrypt(Byte[] unencryptedData):第 79 行 
         在 C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Form1.cs 中的 AESTest.Form1..ctor() 处:第 73 行 
         在 C:\Documents and Settings\nschoonmaker\My Documents\Visual Studio 2005\Projects\AESTest\AESTest\Program.cs 中的 AESTest.Program.Main() 处:第 17 行 
   

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

顺便说一句,如果我将两者的 FeedbackSize 更改为 8,它似乎有效! 即使对于 CFB 模式也是如此。 所以我想我的下一个问题是,如何让 128 工作(希望这能结束这个问题)?

Addition information from this post says:

Essentially, if you want to use RijndaelManaged as AES you need to make sure that:
1) The block size is set to 128 bits
2) You are not using CFB mode, or if you are the feedback size is also 128 bits

Ok, great. I added mEncryptionType.FeedbackSize = 128; to my above example and I get an 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

Is there something wrong with the System.Core dll that wouldnt support this, or do I need to change something else?

On a side note, if I change the FeedbackSize to 8 for both, its seems to work! Even for CFB mode. So I guess my next question is, how do I get 128 to work (and hopefully this will put an end to this question)?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文