C# 为什么 RijndaelManaged 和 AesCryptoServiceProvider 返回不同的结果?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/957388/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why are RijndaelManaged and AesCryptoServiceProvider returning different results?
提问by SwDevMan81
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.
这是我运行的示例。它具有相同的 Mode、Padding、BlockSize、KeySize。我使用相同的初始化向量、键和数据。
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
使用 RijndaelManaged 会产生一个加密值:0x8d,0x81,0x27,0xc6,0x3c,0xe2,0x53,0x2f,0x35,0x78,0x90,0xc2,0x2e,0x3b,0x8a,0x61,x0x0x4,0x4,0 ,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
使用 AesCryptoServiceProvider 会产生一个加密值: 0x8d,0x9f,0x6e,0x99,0xe9,0x54,0x8b,0x12,0xa9,0x88,0x1a,0x3d,0x65,0x23,0x9c,0x4e,x01,x50 ,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 AesManagedwill 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 AesCryptoServiceProvidershould do that same, but it doesnt. Seems funny that the FIPS Certified class allows invalid cipher modes.
更新:事实证明,如果您尝试将 CipherMode 设置为 CFB ,AesManaged将抛出 CryptographicException(“指定的密码模式对该算法无效”)。我觉得AesCryptoServiceProvider 也应该这样做,但事实并非如此。FIPS 认证类允许无效的密码模式似乎很有趣。
采纳答案by goodguys_activate
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).
RijndaelManaged
class 和
AesCryptoServiceProvider
class 是两种不同的实现。
RijndaelManaged
class 是 .net 框架中 Rijndael 算法的一种实现,未在 NIST(美国国家标准与技术研究院)密码模块验证计划 (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.
但是,
AesCryptoServiceProvider
类调用 Windows Crypto API,它使用 RSAENH.DLL,并已在 CMVP 中由 NIST 验证。尽管 Rijndael 算法是 NIST 选择成为 AES 的算法的竞赛的获胜者,但 Rijndael 和官方 AES 之间存在一些差异。因此,RijndaelManaged 类和
AesCryptoServiceProvider
类在实现上存在细微差别。
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.
此外,RijndaelManaged
类不能提供与 AES 等效的实现。在 .net 框架中实现了另一个类,AesManaged
class。这个类只是用RijndaelManaged
固定的块大小和迭代次数包装类来实现 AES 标准。但是,它不支持反馈大小,特别是当模式设置为 CFB 或 OFB 时,
CryptographicException
将被抛出。
For more information, please refer to the following MSDN documents.
有关更多信息,请参阅以下 MSDN 文档。
AesManaged Classand AesManaged.Mode Property
AesManaged 类和AesManaged.Mode 属性
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.
如果您想在应用程序中选择标准 AES 作为安全算法,我们建议使用
AesCryptoServiceProvider
该类。如果你想在你的应用程序中混合使用RijndaelManged
类和AesCryptoServiceProvider
类,我们建议在你的程序中使用 CBC 模式而不是 CFB 模式,因为 CBC 模式在两个类中的实现是相同的。
回答by Jeff Moser
I think it has to do with the CipherMode.CFB. See this postdescribing AesManaged:
我认为这与 CipherMode.CFB 有关。请参阅这篇描述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).
AesManaged 实际上只是 RinjdaelManaged 的一个包装器,其中添加了一些代码以确保您不会将算法设置为以非 AES 兼容的方式运行。例如,AesManaged 不允许您更改块大小。(它也将禁止使用 CFB 和 OFB 模式,因为 RijndaelManaged 使用这些模式的方式)。
Note that if you use CipherMode.ECB or CipherMode.CBC, you'll see identical results. Any reason why you need CFB and not CBC?
请注意,如果您使用 CipherMode.ECB 或 CipherMode.CBC,您将看到相同的结果。您需要CFB而不是CBC的任何理由?
回答by SwDevMan81
Addition information from this postsays:
这篇文章的补充信息说:
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
本质上,如果您想使用 RijndaelManaged 作为 AES,您需要确保:
1) 块大小设置为 128 位
2) 您没有使用 CFB 模式,或者如果您是反馈大小也是 128 位
Ok, great. I added mEncryptionType.FeedbackSize = 128; to my above example and I get an CryptographicExecption:
太好了。我添加了 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
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?
System.Core dll 是否有问题不支持此功能,或者我是否需要更改其他内容?
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)?
附带说明一下,如果我将两者的 FeedbackSize 都更改为 8,它似乎可以工作!即使对于 CFB 模式。所以我想我的下一个问题是,我如何让 128 工作(希望这会结束这个问题)?