加密AesCryptoServiceProvider返回零字节数组吗? [英] Encrypt AesCryptoServiceProvider return zero byte array?

查看:97
本文介绍了加密AesCryptoServiceProvider返回零字节数组吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用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 ,但调用是在的using语句中 ,这意味着不能保证 对象将已将所有缓冲区刷新到基础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屋!

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