加密AesCryptoServiceProvider返回零字节数组?

时间:2018-03-14 04:02:00

标签: c# encryption aes corruption

使用AesCryptoServiceProvider加密某些文件配置时遇到错误。摘要代码如下

1. Team1 91 Pts
2. Team2 89 Pts
3. Team3 87 Pts 

在main函数中,我通过调用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); } } } 来加密纯文本并将结果保存到文件中。但有时内容文件包含所有空字符(&#39; \ 0&#39;)。当我用HexaEditor

打开时,波纹管图像是文件的内容

enter image description here

每天运行8小时的应用程序每月发生一次此错误。

我认为该文件可能已损坏。但我认为这种情况不是由腐败引起的,因为文件夹中有10个配置文件,但只有7个使用Encryption的文件遇到此错误,而3个通过纯文本保存的文件(不使用加密)从未遇到这个错误。

所以我认为AesCryptoServiceProvider引起的问题。 有人请帮帮我。

谢谢!

1 个答案:

答案 0 :(得分:1)

注意:感谢Damien_The_Unbeliever和他的测试,我们发现这个答案是错误,很快就会被删除。在那之前,它应该帮助其他人避免走这条路。

ToArray()上的MemoryStream来电可能会遇到竞争条件。

您发布的代码调用using StreamWriter语句的 方法,因此该对象将刷新它可能使用的任何缓冲区CryptoStream CryptoStream 1}}到那时为止,但调用里面使用MemoryStream的using语句,这意味着无法保证 对象将刷新任何缓冲区到那时为基础的CryptoStream

这可以解释这个错误的间歇性:

在您获得所需结果的情况下,可能是MemoryStream的缓冲区在调用ToArray()之前自动刷新到ToArray(),只是运气好

在您收到错误结果的情况下,MemoryStream调用会在MemoryStream的内部缓冲区(最有可能被初始化为零)之前将数据返回到{ {1}}已收到CryptoStream

中的所有(或任何)数据

如果这一切都正确,您可以通过在CryptoStream对象上调用FlushFinalBlock()之前使缓冲区刷新确定性并保证每次正确的结果,然后才能从其基础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