gpt4 book ai didi

c# - 如何避免在加密和解密过程中使用额外的内存?

转载 作者:太空狗 更新时间:2023-10-29 17:56:25 25 4
gpt4 key购买 nike

所以我有一个基本的加密类。请注意,这是一个简化的实现来说明问题。

在我看来,这两种方法都有一个额外的字节数组和字符串实例。

xmlStringEncrypt 中的 bytes

decryptedStringDecrypt 中的decryptedBytes

那么我怎样才能在这个类中重新使用流来最小化内存使用量呢?

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<T>(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);

}
}

}

这是一个单元测试

[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<MyClassForSerialize>(encrypted);
Assert.AreEqual(before.Property, after.Property);
}
}
public class MyClassForSerialize
{
public string Property { get; set; }
}

===编辑===

基于 Damien_The_Unbeliever 的回答,我尝试了这个。哪个没有通过单元测试

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<T>(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 函数一起使用。

完整解决方案

加密

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();
}
}

解密

public T Decrypt<T>(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);
}
}

关于c# - 如何避免在加密和解密过程中使用额外的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13947803/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com