C#从内存中安全删除变量

时间:2016-09-12 10:12:00

标签: c# security memory

我正在制作与安全相关的计划,我想确保我以正确的方式做这件事。当有人使用密码登录时,密钥会被解密并存储在变量中。当他们注销时,我希望内存中的数据被完全删除,而不仅仅是标记为已删除。我目前正在做以下事情:

public void Logout()
{
    RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider();
    for (var i = 0; i < 3; i++)
    {
        byte[] data = new byte[(int) Math.Round((double) (_phraseHash.Count()))];
        rngCsp.GetBytes(data);
        int randomNum = BitConverter.ToInt32(data, 0);
        _phraseHash = randomNum.ToString();
    }
    LoggedIn = false;
    _phraseHash = null;
}

我想知道的是,这是否足以从系统中完全删除密钥(_phraseHash)。

这还有必要吗?我实际上并不太了解内存中的数据是如何被删除的,我只是假设它有点类似于硬盘驱动器的工作方式,其中字节被标记为删除并在其他需要空间时重写。

2 个答案:

答案 0 :(得分:9)

我想你可能对SecureString

感兴趣
  

System.String类的实例都是不可变的,当不再需要时,无法以编程方式安排进行垃圾回收;也就是说,实例在创建后是只读的,并且无法预测何时将从计算机内存中删除实例。因为System.String实例是不可变的,所以看起来修改现有实例的操作实际上会创建一个操作的副本。因此,如果String对象包含敏感信息(如密码,信用卡号或个人数据),则使用该信息后可能会显示该信息,因为您的应用程序无法从计算机内存中删除数据。

     

SecureString对象类似于String对象,因为它具有   文字价值。但是,SecureString对象的值是固定的   内存,可以使用提供的保护机制,如加密   通过底层操作系统,可以修改直到你的   application将其标记为只读,可以从计算机中删除   您的应用程序调用Dispose方法或通过   .NET Framework垃圾收集器。

答案 1 :(得分:0)

有关安全字符串的MS文档-> https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?redirectedfrom=MSDN&view=netframework-4.8#HowSecure

以下内容应告诉您,如果安全是您最关心的问题,则不应将SecureString用于存储密码。

即使SecureString实现能够利用以下优势 加密,分配给SecureString实例的纯文本可能 在不同的时间暴露:

因为Windows在Windows上不提供安全的字符串实现 在操作系统级别,.NET Framework仍必须转换 将字符串值安全地保存为其纯文本表示形式以便使用 它。

每当通过以下方法修改安全字符串的值时, AppendChar或RemoveAt,必须将其解密(即转换回 修改为纯文本),然后再次加密。

如果在互操作调用中使用了安全字符串,则必须对其进行转换 转换为ANSI字符串,Unicode字符串或二进制字符串(BSTR)。对于 有关更多信息,请参见SecureString和互操作部分。

SecureString实例的值为的时间间隔 与String类相比,所暴露的只是缩短了。

存储与使用情况更笼统地说,SecureString类定义了一个 应当保护或保留的字符串值的存储机制 机密。但是,在.NET Framework本身之外,没有任何用途 机制支持SecureString。这意味着安全字符串 必须转换为可用形式(通常是明文形式) 可以被其目标识别,并且解密和转换 必须出现在用户空间中。

总体而言,SecureString比String更安全,因为它限制了 敏感字符串数据的公开。但是,那些字符串可能仍然是 暴露于有权访问原始内存的任何进程或操作中, 例如在主机上运行的恶意进程, 转储或用户可见的交换文件。 代替使用SecureString来 保护密码,建议的替代方法是使用不透明 处理存储在流程之外的凭据。