什么时候需要.NET中的SecureString?
我试图弄清.NET的SecureString的用途。从MSDN:
An instance of the System.String class is both immutable and, when no longer needed, cannot be programmatically scheduled for garbage collection; that is, the instance is read-only after it is created and it is not possible to predict when the instance will be deleted from computer memory. Consequently, if a String object contains sensitive information such as a password, credit card number, or personal data, there is a risk the information could be revealed after it is used because your application cannot delete the data from computer memory. A SecureString object is similar to a String object in that it has a text value. However, the value of a SecureString object is automatically encrypted, can be modified until your application marks it as read-only, and can be deleted from computer memory by either your application or the .NET Framework garbage collector. The value of an instance of SecureString is automatically encrypted when the instance is initialized or when the value is modified. Your application can render the instance immutable and prevent further modification by invoking the MakeReadOnly method.
自动加密是最大的收获吗?
我为什么不能说:
SecureString password = new SecureString("password");
代替
SecureString pass = new SecureString(); foreach (char c in "password".ToCharArray()) pass.AppendChar(c);
我缺少SecureString的哪个方面?
解决方案
我猜这是因为该字符串是安全的,即黑客不应该能够读取它。如果使用字符串初始化它,则黑客可以读取原始字符串。
我相信我们必须执行字符添加操作而不是一个平面实例化的原因是因为在后台将" password"传递给SecureString的构造函数会使该" password"字符串在内存中无法达到安全字符串的目的。
通过追加,我们一次只能将一个字符放入内存中,这很可能不会彼此相邻,因此很难重建原始字符串。我在这里可能是错的,但这就是向我解释的方式。
该类的目的是防止安全数据通过内存转储或者类似工具公开。
MS发现,在导致服务器(台式机等)崩溃的某些情况下,运行时环境有时会进行内存转储,以暴露内存中的内容。安全字符串在内存中对其进行加密,以防止攻击者能够检索字符串的内容。
好了,正如描述所指出的那样,该值是以加密方式存储的,这意味着进程的内存转储将不会显示该字符串的值(无需做一些相当认真的工作)。
我们不能仅从常量字符串构造SecureString的原因是,这样我们在内存中将拥有该字符串的未加密版本。将我们限制为分段创建字符串,可以减少一次将整个字符串存储在内存中的风险。
SecureString的一大优点是可以避免由于页面缓存而将数据存储到磁盘的可能性。如果内存中有密码,然后加载了一个大型程序或者数据集,则当程序内存不足时,密码可能会写入交换文件。使用SecureString,至少数据不会以明文形式无限期地驻留在磁盘上。
在极少数情况下,可以在当前版本的Framework中合理使用SecureString。它实际上仅对与非托管API交互有用,我们可以使用Marshal.SecureStringToGlobalAllocUnicode将其封送。
一旦将它转换为System.String或者从System.String转换出来,就无法实现它的目的。
MSDN示例从控制台输入一次生成一个SecureString字符,并将安全字符串传递给非托管API。这相当令人费解且不切实际。
我们可能会期望.NET的未来版本对SecureString的更多支持,这将使其变得更加有用,例如:
- SecureString Console.ReadLineSecure()或者类似方法,以将控制台输入读取到SecureString中,而不包含示例中的所有复杂代码。
- WinForms TextBox替换,将其TextBox.Text属性存储为安全字符串,以便可以安全地输入密码。
- 与安全性相关的API的扩展,以允许将密码作为SecureString传递。
如果没有上述内容,SecureString的价值将是有限的。
当前使用SecureString
的框架的某些部分:
- WPF的
System.Windows.Controls.PasswordBox
控件在内部将密码保留为SecureString(通过PasswordBox :: SecurePassword
公开。 System.Diagnostics.ProcessStartInfo :: Password
属性是SecureString
- " X509Certificate2"的构造函数使用" SecureString"作为密码
主要目的是减少而不是消除攻击面。 " SecureStrings"被"固定"在RAM中,因此垃圾收集器不会移动它或者复制它。它还确保明文不会被写入Swap文件或者核心转储中。加密更像是混淆,不会阻止坚定的黑客,他们将能够找到用于加密和解密的对称密钥。
正如其他人所说,之所以必须一个字符一个字符地创建一个" SecureString",是因为这样做的第一个明显缺陷是:我们大概已经拥有作为纯字符串的秘密值了,那又意味着什么呢?
SecureString
s是解决"鸡与蛋"问题的第一步,因此,即使大多数当前方案要求将它们转换回常规字符串以完全使用它们,它们在框架中的存在现在也意味着对它们的更好支持。至少在将来它们不会成为程序的薄弱环节。
很多很好的答案;这是所讨论内容的简要提要。
Microsoft已实现SecureString类,以通过敏感信息(例如信用卡,密码等)提供更好的安全性。它会自动提供:
- 加密(在内存转储或者页面缓存的情况下)
- 固定在内存中
- 标记为只读的能力(以防止任何进一步的修改)
- 通过不允许传入常量字符串来安全构造
当前,SecureString的使用受到限制,但希望将来会得到更好的采用。
基于此信息,SecureString的构造函数不应仅将字符串分割成char数组,因为拼写出字符串会破坏SecureString的目的。
添加信息:
- .NET安全博客中的一篇文章,与此处介绍的内容大致相同。
- 另一个人回顾了它,并提到了一种可以转储SecureString内容的工具。
编辑:我发现很难选择最好的答案,因为许多信息很多。太糟糕了,没有辅助答案选项。