如何在加密和解密期间避免额外的内存使用?
所以我有一个基本的加密类。 请注意,这是一个简化的实现来说明问题。
现在我想这两个方法都有一个额外的字节数组和字符串实例。
Encrypt
xmlString
和bytes
和
decryptedBytes
中的Decrypt
和Decrypt
那么如何重新设计此类中的流的使用以最小化内存使用?
class Crypto { Rijndael rijndael; public Crypto() { rijndael = Rijndael.Create(); rijndael.Key = Encoding.ASCII.GetBytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); ; rijndael.IV = Encoding.ASCII.GetBytes("bbbbbbbbbbbbbbbb"); ; rijndael.Padding = PaddingMode.PKCS7; } public byte[] Encrypt(object obj) { var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; var ns = new XmlSerializerNamespaces(); ns.Add("", ""); var sb = new StringBuilder(); var xmlSerializer = new XmlSerializer(obj.GetType()); using (var xmlWriter = XmlWriter.Create(sb, settings)) { xmlSerializer.Serialize(xmlWriter, obj, ns); xmlWriter.Flush(); } var xmlString = sb.ToString(); var bytes = Encoding.UTF8.GetBytes(xmlString); using (var encryptor = rijndael.CreateEncryptor()) using (var stream = new MemoryStream()) using (var crypto = new CryptoStream(stream, encryptor, CryptoStreamMode.Write)) { crypto.Write(bytes, 0, bytes.Length); crypto.FlushFinalBlock(); stream.Position = 0; var encrypted = new byte[stream.Length]; stream.Read(encrypted, 0, encrypted.Length); return encrypted; } } public T Decrypt(byte[] encryptedValue) { byte[] decryptedBytes; using (var decryptor = rijndael.CreateDecryptor()) using (var stream = new MemoryStream()) using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Write)) { crypto.Write(encryptedValue, 0, encryptedValue.Length); crypto.FlushFinalBlock(); stream.Position = 0; decryptedBytes = new Byte[stream.Length]; stream.Read(decryptedBytes, 0, decryptedBytes.Length); } var ser = new XmlSerializer(typeof(T)); var decryptedString = Encoding.UTF8.GetString(decryptedBytes); using (var stringReader = new StringReader(decryptedString)) using (var xmlReader = new XmlTextReader(stringReader)) { return (T)ser.Deserialize(xmlReader); } } }
这是一个unit testing
[TestFixture] public class Tests { [Test] public void Run() { var before = new MyClassForSerialize() { Property = "Sdf" }; var dataEncryptor = new Crypto(); var encrypted = dataEncryptor.Encrypt(before); var after = dataEncryptor.Decrypt(encrypted); Assert.AreEqual(before.Property, after.Property); } } public class MyClassForSerialize { public string Property { get; set; } }
===编辑===
基于Damien_The_Unbeliever的anser,我尝试了这个。 哪个unit testing失败了
public byte[] Encrypt(object obj) { var settings = new XmlWriterSettings { OmitXmlDeclaration = true }; var ns = new XmlSerializerNamespaces(); ns.Add("", ""); var xmlSerializer = new XmlSerializer(obj.GetType()); using (var encryptor = rijndael.CreateEncryptor()) using (var stream = new MemoryStream()) using (var crypto = new CryptoStream(stream, encryptor, CryptoStreamMode.Write)) { using (var xmlWriter = XmlWriter.Create(crypto, settings)) { xmlSerializer.Serialize(xmlWriter, obj, ns); xmlWriter.Flush(); } crypto.FlushFinalBlock(); stream.Position = 0; return stream.ToArray(); } }
您可以直接在CryptoStream
之上构建XmlWriter
(将crypto
传递给XmlWriter.Create
),而不是使用单独的缓冲区。 (同上解密)
MemoryStream
有一个ToArray
方法,因此您不必手动分配,重新定位和读取它。
除此之外,它看起来像一个合理的实施 – 是否有需要修复的具体问题?
根据您的编辑,如果我将解密更改为:
public T Decrypt(byte[] encryptedValue) { using (var decryptor = rijndael.CreateDecryptor()) using (var stream = new MemoryStream(encryptedValue)) using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read)) using (var xmlReader = XmlReader.Create(crypto)) { var ser = new XmlSerializer(typeof(T)); return (T)ser.Deserialize(xmlReader); } }
然后它似乎对我有用。
新版本包含XML BOM,而旧版本则不包括。 XmlReader 应该应付,我想,但似乎没有。 在Encrypt
尝试以下设置:
var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = new UTF8Encoding(false) };
现在它适用于旧的Decrypt
function。
完整解决方案
加密
public byte[] Encrypt(object obj) { var settings = new XmlWriterSettings { OmitXmlDeclaration = true, Encoding = new UTF8Encoding(false) }; var ns = new XmlSerializerNamespaces(); ns.Add("", ""); var xmlSerializer = new XmlSerializer(obj.GetType()); using (var encryptor = rijndael.CreateEncryptor()) using (var stream = new MemoryStream()) using (var crypto = new CryptoStream(stream, encryptor, CryptoStreamMode.Write)) { using (var xmlWriter = XmlWriter.Create(crypto, settings)) { xmlSerializer.Serialize(xmlWriter, obj, ns); xmlWriter.Flush(); } crypto.FlushFinalBlock(); return stream.ToArray(); } }
解码
上述就是C#学习教程:如何在加密和解密期间避免额外的内存使用?分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public T Decrypt(byte[] encryptedValue) { using (var decryptor = rijndael.CreateDecryptor()) using (var stream = new MemoryStream(encryptedValue)) using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read)) { var ser = new XmlSerializer(typeof(T)); return (T)ser.Deserialize(crypto); } }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/983929.html