C# 如何避免解密后内存中数据的未加密副本?
我正在尝试编写一些函数,这些函数允许对数据块进行加密/解密。出于兼容性原因,它需要对称加密,可以保存在一台机器上,然后在另一台机器上读取,这样就排除了使用ProtectedData的可能性,因为它的范围不会比本地机器更广。太糟糕了,仅仅添加这个选项就可以节省很多麻烦 我已经做了很多网络搜索,到目前为止,我还没有遇到任何好的例子,真正尝试从磁盘上的加密值到内存中的SecureString进行干净的转换,其间没有任何痕迹。我真的很想看看如果?这是可以做到的 我有一个加密功能,它似乎工作得相当好。您给它一个SecureString,它返回一个常规字符串,其中包含SecureString内容的加密副本。如果在调用函数后保存内存转储,则无法在转储中的任何位置找到未加密数据的任何副本。这很好 然而,我没有解密对手那么幸运。虽然我可以成功地解密数据并将其返回到SecureString中,但在解密完成时,我在内存转储中得到了解密值的多个副本。当然,将副本分散在明文中会抵消使用内存加密的全部意义。这很糟糕 有人能就如何使这段代码干净,以便在代码完成后不会在内存中留下未加密值的副本提出建议吗 这是我的密码:C# 如何避免解密后内存中数据的未加密副本?,c#,encryption,persistence,securestring,C#,Encryption,Persistence,Securestring,我正在尝试编写一些函数,这些函数允许对数据块进行加密/解密。出于兼容性原因,它需要对称加密,可以保存在一台机器上,然后在另一台机器上读取,这样就排除了使用ProtectedData的可能性,因为它的范围不会比本地机器更广。太糟糕了,仅仅添加这个选项就可以节省很多麻烦 我已经做了很多网络搜索,到目前为止,我还没有遇到任何好的例子,真正尝试从磁盘上的加密值到内存中的SecureString进行干净的转换,其间没有任何痕迹。我真的很想看看如果?这是可以做到的 我有一个加密功能,它似乎工作得相当好。您给
public SecureString Decrypt(string base64EncryptedText)
{
using (SymmetricAlgorithm sa = GetAlgorithm())
{
ICryptoTransform transform = sa.CreateDecryptor();
var result = new SecureString();
using (var memstream = new MemoryStream())
{
using (var cs = new CryptoStream(memstream, transform, CryptoStreamMode.Write))
{
byte[] base64EncryptedTextByteArray = Convert.FromBase64String(base64EncryptedText);
cs.Write(base64EncryptedTextByteArray, 0, base64EncryptedTextByteArray.Length);
cs.FlushFinalBlock(); // If you don't do this, results are inconsistent from the ToArray method.
byte[] decodedBytes = memstream.ToArray();
// Clear the contents of the memory stream back to nulls
memstream.Seek(0, 0);
for (int i = 0; i < memstream.Length; i++)
{ memstream.WriteByte(0); }
char[] decodedChars = Encoding.UTF8.GetChars(decodedBytes);
// Null out the bytes we copied from the memory stream
for (int i = 0; i < decodedBytes.Length; i++)
{ decodedBytes[i] = 0; }
// Put the characters back in to the SecureString for safe keeping and null out the array as we go...
for (int i = 0; i < decodedChars.Length; i++)
{
result.AppendChar(decodedChars[i]);
decodedChars[i] = '\0';
}
}
}
return result;
}
}
private SymmetricAlgorithm GetAlgorithm()
{
string password = "DummyPassword";
string salt = "salty";
DeriveBytes rgb = new Rfc2898DeriveBytes(password, Encoding.Unicode.GetBytes(salt));
SymmetricAlgorithm sa = new RijndaelManaged();
sa.Key = rgb.GetBytes(sa.KeySize >> 3);
sa.IV = rgb.GetBytes(sa.BlockSize >> 3);
return sa;
}
另一件事,我还没有探索这么多,如果垃圾收集器在这一切中间运行会发生什么…如果发生这种情况,所有的赌注都被关闭了,所以在这些函数的开始运行GC来减少它在中间发生的可能性会是个好主意吗?
谢谢。
如果你想绝对确定明文和/或键永远不会在内存中暴露,那么你必须考虑使用硬件加密模块HSMS。不幸的是,这很昂贵。是的,但我做这件事和做其他事情一样多。可以在本机.NET代码中完成吗?很明显,MS正在考虑引入SecureString和所有现在接受它们的方法的问题。看起来他们在加密流中留下了一些洞。unsafe public string Encrypt(SecureString textToEncrypt)
{
using (SymmetricAlgorithm sa = GetAlgorithm())
{
ICryptoTransform ict = sa.CreateEncryptor();
using (MemoryStream memStream = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(memStream, ict, CryptoStreamMode.Write))
{
IntPtr unmanagedBytes = Marshal.SecureStringToGlobalAllocAnsi(textToEncrypt);
try
{
byte* bytePointer = (byte*)unmanagedBytes.ToPointer();
byte[] singleByte = new byte[1];
while (*bytePointer != 0) // This is a null terminated value, so copy until we get a null
{
singleByte[0] = *bytePointer;
cs.Write(singleByte, 0, 1);
singleByte[0] = 0;
bytePointer++;
}
}
finally
{
Marshal.ZeroFreeGlobalAllocAnsi(unmanagedBytes);
}
}
string base64EncryptedText = Convert.ToBase64String(memStream.ToArray());
return base64EncryptedText;
}
}
}