.NET AES 解密破坏了前几个字节

ygo*_*goe 5 c# encryption cryptography

我在用着AesCryptoServiceProvider来加密和解密磁盘上的 XML 文档。MSDN 参考中有一个很有帮助的示例。我根据给定密码的 SHA-256 哈希生成 AES 密钥。它的前半部分被指定为 IV,因为我不知道这里有什么更好的东西可以使用。据我所知,加密和解密时密钥和IV必须相同。

\n\n

当我解密文件时,它的开头是这样的:

\n\n
I\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdH\xe7\x92\xa7\xef\xbf\xbd-\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd[\xef\xbf\xbd="1.0" encoding="utf-8"?>\n
Run Code Online (Sandbox Code Playgroud)\n\n

该文档的其余部分完全没问题。正如我所期望的那样,内容后面甚至没有一些随机填充。

\n\n

是什么导致文件开头出现这种随机垃圾?

\n\n

以下是更多阅读代码:

\n\n
using (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())\n{\n    using (SHA256CryptoServiceProvider sha = new SHA256CryptoServiceProvider())\n    {\n        this.cryptoKey = sha.ComputeHash(Encoding.Unicode.GetBytes(password));\n    }\n    aes.Key = this.cryptoKey;\n    Array.Copy(this.cryptoKey, aes.IV, 16);\n\n    ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);\n\n    using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read))\n    using (CryptoStream cs = new CryptoStream(fs, decryptor, CryptoStreamMode.Read))\n    using (StreamReader sr = new StreamReader(cs))\n    {\n        string data = sr.ReadToEnd();\n        xdoc.LoadXml(data);\n\n        //xdoc.Load(sr);\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这就是加密代码:

\n\n
XmlWriterSettings xws = new XmlWriterSettings();\nxws.Encoding = Encoding.UTF8;\nxws.Indent = true;\nxws.IndentChars = "\\t";\nxws.OmitXmlDeclaration = false;\n\nusing (AesCryptoServiceProvider aes = new AesCryptoServiceProvider())\n{\n    aes.Key = this.cryptoKey;\n    Array.Copy(this.cryptoKey, aes.IV, 16);\n\n    ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);\n\n    using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write))\n    using (CryptoStream cs = new CryptoStream(fs, encryptor, CryptoStreamMode.Write))\n    using (StreamWriter sw = new StreamWriter(cs, Encoding.UTF8))\n    {\n        XmlWriter writer = XmlWriter.Create(sw, xws);\n        xdoc.Save(writer);\n        writer.Close();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Rem*_*anu 4

首先,不要从临时算法生成密钥材料(是的,在密钥派生方面,SHA256 是一种临时算法)。遵循行业标准并使用值得信赖的基于密码的密钥派生功能。当前标准是PBKDF-2,另请参见RFC2898。.Net 管理的加密实现就是该类Rfc2898DeriveBytes

其次,您必须向我们展示加密代码。在我看来,您使用的示例附加了在加密流开头使用的 IV。鉴于IV 不应该从密码中派生,这是完全有道理的。密钥和 IV 应源自密码+随机,并且“随机”必须作为文件的一部分发送。