【发布时间】:2015-11-22 05:38:32
【问题描述】:
出于安全原因,我正在尝试清除 C# 字符串的内存内容。
我知道SecureString 类,但不幸的是我不能在我的应用程序中使用SecureString 而不是String。需要清除的字符串是在运行时动态创建的(例如,我不想清除字符串文字)。
我发现的大多数搜索结果基本上都表明清除 String 的内容是不可能的(因为字符串是不可变的)并且应该使用 SecureString。
因此,我确实在下面提出了自己的解决方案(使用不安全代码)。测试表明解决方案有效,但我仍然不确定解决方案是否有问题?还有更好的吗?
static unsafe bool clearString(string s, bool clearInternedString=false)
{
if (clearInternedString || string.IsInterned(s) == null)
{
fixed (char* c = s)
{
for (int i = 0; i < s.Length; i++)
c[i] = '\0';
}
return true;
}
return false;
}
编辑:由于 GC 上的 cmets 在调用 clearString 之前移动了字符串:那么下面的 sn-p 呢?
string s = new string('\0', len);
fixed (char* c = s)
{
// copy data from secure location to s
c[0] = ...;
c[1] = ...;
...
// do stuff with the string
// clear the string
for (int i = 0; i < s.Length; i++)
c[i] = '\0';
}
【问题讨论】:
-
您在安全方面的尝试是错误的——您试图实现不可能的绝对安全。保护数据是为了让未经授权的人尽可能难以检索数据。如果有人可以直接访问您机器的内存,那么您需要担心更大的问题。使用
SecureString,它会给你最好的结果。 -
请注意,您可以使用
GCHandle.Alloc(s, GCHandleType.Pinned)进行长期固定。完成后不要忘记使用Free()取消固定它。 -
如果您不能使用
SecureString,那么您应该说出原因。存在三种可能性:您可能认为无法使用它是错误的,现在答案可以告诉您原因。或者你可能是对的,但原因为可能的替代方案提供了线索,或者第三,你是对的,但原因无助于解决问题或提供替代方案。但不知道原因,谁也说不清。 -
我强烈推荐使用
SecureString。说真的,您正在尝试(并且失败)重写几乎与SecureString中的封面相同的代码。那么为什么要重新发明轮子呢?尤其是当它如此无聊的时候...... -
人们往往会忘记,为了使用
SecureString,我们必须将其转换为string。只要 GC 需要,string就会一直存在于内存中,所以即使他使用的是SecureString,我也认为这个问题是有效的。
标签: c# string security memory securestring