加密AesCryptoServiceProvider返回零字节数组吗? [英] Encrypt AesCryptoServiceProvider return zero byte array?
问题描述
使用AesCryptoServiceProvider加密某些文件配置时遇到错误.摘要代码如下
I encounter an error when using the AesCryptoServiceProvider to Encrypt some files config. The summary code is below
private static byte[] secretKey = {
(byte)0x63, (byte)0x23, (byte)0xdf, (byte)0x2a,
(byte)0x59, (byte)0x1a, (byte)0xac, (byte)0xcc,
(byte)0x50, (byte)0xfa, (byte)0x0d, (byte)0xcc,
(byte)0xff, (byte)0xfd, (byte)0xda, (byte)0xf0
};
private static byte[] iv = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
public static byte[] EncryptStringToBytes(String plainText, byte[] secretKey, byte[] IV)
{
try
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (secretKey == null || secretKey.Length <= 0)
throw new ArgumentNullException("secretKey");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("secretKey");
byte[] encrypted;
// Create an AesCryptoServiceProvider object
// with the specified key and IV.
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = secretKey;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
catch (System.Exception ex)
{
LogWriter.Instance.LogError(ClassName, "EncryptStringToBytes()", ex.Message + ";\tplainText=" + plainText + ";\t" + ex.StackTrace);
return null;
}
}
int main()
{
byte[] encryptText = EncryptStringToBytes("some plain text", secretKey, iv);
if (encryptText != null)
{
try
{
File.WriteAllBytes(filePath, encryptText);
}
catch (Exception ex)
{
LogWriter.Instance.LogError(ClassName, "SaveBuffToFile()", ex.Message + ";\tFilePath=" + path + ";\t" + ex.StackTrace);
}
}
}
在主函数中,我加密纯文本并将其结果通过调用File.WriteAllBytes(filePath, encryptText);
保存到文件中.但是有时内容文件包含所有Null字符('\ 0').当我使用HexaEditor打开文件时,波纹管图像是文件的内容
In the main function, I Encrypt the plain text and save the result to the file by calling File.WriteAllBytes(filePath, encryptText);
. But sometime the content file contains all Null character ('\0'). The bellow image is the content of file when I open with HexaEditor
对于每天运行8小时的应用程序,此错误大约每月发生一次.
This error happen about once a month for the app running 8 hours per day.
我认为该文件可能已损坏.但是我认为这种情况不是由损坏引起的,因为一个文件夹中有10个配置文件,但是只有7个文件使用加密遇到此错误,而3个以纯文本(不使用加密)保存的文件从未出现过此错误.遇到此错误.
I considered that the file may be corrupted. But I think that this case is not caused by corruption, because there are 10 config files in a folder, but only have 7 files that using Encryption is encountered this error, whereas 3 files that saved by plain text (not using Encryption) has never encountered this error.
所以我认为问题是由AesCryptoServiceProvider引起的. 任何人都可以帮助我.
So I think the problem caused by AesCryptoServiceProvider. Anyone please help me.
谢谢!
推荐答案
NOTE: Thanks to Damien_The_Unbeliever and his testing, this answer has been found to be WRONG and may be deleted soon. Until then, it should help others avoid going down this path.
您可能在MemoryStream
上通过ToArray()
调用出现了竞争状况.
You may have a race condition with the ToArray()
call on your MemoryStream
.
您发布的代码调用using
语句的using
语句的方法 outside ,这样该对象将在此时将其可能使用的所有缓冲区刷新到基础CryptoStream
,但调用是在MemoryStream
点.
The code you posted calls that method outside of the using
statement for StreamWriter
, so that object will have flushed any buffers it may be using to the underlying CryptoStream
by that point, but the call is inside the using statement for CryptoStream
, which means there is no guarantee that that object will have flushed any buffers to the underlying MemoryStream
by that point.
这将解释该错误的间歇性:
That would explain the intermittent nature of the bug:
在获得理想结果的情况下,可能是由于运气,CryptoStream
的缓冲区会在调用ToArray()
之前自动刷新到MemoryStream
.
In the cases where you get the desired result, it might be that the CryptoStream
's buffer is being automatically flushed to the MemoryStream
before the call to ToArray()
, just by luck.
在得到错误结果的情况下,ToArray()
调用将在MemoryStream
收到之前从MemoryStream
的内部缓冲区(很可能已初始化为零)中返回数据. CryptoStream
中的所有(或任何)数据.
In the cases where you're getting the erroneous result, the ToArray()
call is returning the data from the MemoryStream
's internal buffer (which is most likely being initialized to zeros) before the MemoryStream
has received all (or any) of the data from the CryptoStream
.
If that is all correct, you can make the buffer flushing deterministic and guarantee a correct result every time by calling FlushFinalBlock()
on the CryptoStream
object before accessing the data from its underlying MemoryStream
.
更改之后,代码将为:
[...]
// Create the streams used for encryption.
using ( MemoryStream msEncrypt = new MemoryStream() ) {
using ( CryptoStream csEncrypt = new CryptoStream( msEncrypt, encryptor, CryptoStreamMode.Write ) ) {
using ( StreamWriter swEncrypt = new StreamWriter( csEncrypt ) ) {
swEncrypt.Write( plainText );
}
csEncrypt.FlushFinalBlock();
encrypted = msEncrypt.ToArray();
}
}
[...]
请参阅:
CryptoStream.HasFlushedFinalBlock
此StackOverflow答案与您的问题密切相关: https://stackoverflow.com/a/19742806
This StackOverflow answer is tangentially related to your issue: https://stackoverflow.com/a/19742806
这篇关于加密AesCryptoServiceProvider返回零字节数组吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!