C# 正在内存系统中燃烧。字符串

C# 正在内存系统中燃烧。字符串,c#,.net,string,securestring,C#,.net,String,Securestring,我试图从内存中删除正常字符串的任何痕迹,为此,我从正常字符串的引用中创建了SecureString的实例。像这样: public static unsafe void Burn(this string input) { fixed (char* c = input) { var secure = new SecureString(c, input.Length); secure.Dispose(); } } 问题是,即使在调用dispos

我试图从内存中删除正常字符串的任何痕迹,为此,我从正常字符串的引用中创建了
SecureString
的实例。像这样:

public static unsafe void Burn(this string input)
{
    fixed (char* c = input)
    {
        var secure = new SecureString(c, input.Length);
        secure.Dispose();
    }
}
问题是,即使在调用dispose方法之后,
input
的内容也不会更改。据我所知,
SecureString
实例应该引用
输入
地址,因此在调用
Dispose()
时从内存中清除if。我缺少什么?

它似乎不适合您的代码使用。文档不清楚,但是它使用短语
从系统的子数组初始化SecureString类的新实例。Char对象
告诉我它可能在复制数据,而不是对现有字符串进行加密。这是有意义的,因为
SecureString
的文档特别提到
String
不能以确定的方式销毁

测试这一理论的一个好方法是比较
输入
安全
的地址,看看它们在初始化后是否仍然指向内存中的同一位置。

它似乎不适合您的代码使用。文档不清楚,但是它使用短语
从系统的子数组初始化SecureString类的新实例。Char对象
告诉我它可能在复制数据,而不是对现有字符串进行加密。这是有意义的,因为
SecureString
的文档特别提到
String
不能以确定的方式销毁

测试这一理论的一个好方法是比较
输入
安全
的地址,看看它们在初始化后是否仍然指向内存中的同一位置。

这并不是真正的答案,因为无法确定字符串是否仍在内存中的某个位置浮动,但我想我会发布这个,因为它确实修改了调用它的原始字符串


通过测试您的示例代码,我得出了这个结论。不保证它不会泄漏内存,但它会“烧掉”调用字符串。不过,您的字符串可能仍在其他地方的内存中浮动

这并不是真正的答案,因为无法确定字符串是否仍在内存中的某个位置浮动,但我想我会发布此消息,因为它确实修改了调用它的原始字符串



通过测试您的示例代码,我得出了这个结论。不保证它不会泄漏内存,但它会“烧掉”调用字符串。不过,您的字符串可能仍在其他地方的内存中浮动

string
对象是共享的。谁知道代码引用的是
输入
字符串是什么?安全决策可以基于此

因此,字符串在.NET中必须始终是不可变的。您不能(以文档化的方式)删除其内容

input
甚至可能引用字符串文字!如果更改其内容,则不相关代码中的文字可能会更改其值。您可以编写
“x”
,并在运行时获取
“\0”
。这太可怕了


此外,GC可以移动对象。你的秘密数据可能已经泄露到了整个堆中。构建应用程序时,不需要销毁数据,或者只将其存储在固定/非托管缓冲区中。

string
对象是共享的。谁知道代码引用的是
输入
字符串是什么?安全决策可以基于此

因此,字符串在.NET中必须始终是不可变的。您不能(以文档化的方式)删除其内容

input
甚至可能引用字符串文字!如果更改其内容,则不相关代码中的文字可能会更改其值。您可以编写
“x”
,并在运行时获取
“\0”
。这太可怕了


此外,GC可以移动对象。你的秘密数据可能已经泄露到了整个堆中。构建应用程序时,不需要销毁数据,或者只将其存储在固定/非托管缓冲区中。

它仍然存在,因为
input
仍然存在。您已经处理了
SecureString
,但没有处理原始传入的
input
字符串。我认为如果你真的想处理
字符串
,你必须从
安全字符串
开始。而且,如果你这样做是为了摆脱密码的
字符串
实例,那你就错了即使您成功地执行了您想要的操作(即使用指针并重写字符串的内容),也不能保证它只是字符串的副本(即GC可能移动了对象10次,并在内存中留下了所有的跟踪)。另外,不要忘了源代码中的字符串是内部的,所以要小心清理这些字符串(不太可能是您想要做的,但请记住)。它仍然存在,因为
input
仍然存在。您已经处理了
SecureString
,但没有处理原始传入的
input
字符串。我认为如果你真的想处理
字符串
,你必须从
安全字符串
开始。而且,如果你这样做是为了摆脱密码的
字符串
实例,那你就错了即使您成功地执行了您想要的操作(即使用指针并重写字符串的内容),也不能保证它只是字符串的副本(即GC可能移动了对象10次,并在内存中留下了所有的跟踪)。另外,别忘了源代码中的字符串是被截取的,所以要小心清理它们(不太可能是你想要做的,但要记住)。是的,检查两个变量的内存地址是我尝试的第一件事,事实上它们并不指向同一个位置。
安全
不可能有
public static class StringTest
{
    public static unsafe void Burn(this string input)
    {
        fixed (char* c = input)
        {
            Marshal.Copy(new string('\0', input.Length).ToCharArray(), 0, new IntPtr(c), input.Length);
        }
    }
}