当我需要一个SecureString。净?
-
02-07-2019 - |
题
我想神交目的。净的SecureString.从MSDN:
一个实例系统。串类两个不可改变的,当不再需要时,不可编程预定于垃圾收集;就是说,实例是只读之后创建的和不可预测的实例时将被删除计算机存储器中。因此,如果一串的对象包含敏感信息,例如密码、信用卡号码,或个人数据,是有风险的信息可能揭示后,这是因为你的申请不能删除的数据的计算机存储器中。
SecureString对象类似于一串的目的在于,它有一个文本价值。然而,值SecureString目的是自动的加密,可以修改,直到你应用标记它为只读,并且可以从中删除计算机存储器中通过应用程序。净框架垃圾的收集器。
值的一个实例SecureString是自动加密的当时的实例是初始化或当值为修改。你的应用程序可以呈现不可改变的实例,并防止进一步的修改通过调用MakeReadOnly方法。
是的自动加密的大结局?
为什么我不能只是说:
SecureString password = new SecureString("password");
而不是的
SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
pass.AppendChar(c);
什么方面的SecureString我的失踪?
解决方案
一些零部件的框架,目前使用 SecureString
:
- WPF的
System.Windows.Controls.PasswordBox
控制保持密码作为一个SecureString内部(作为一份经过PasswordBox::SecurePassword
) - 的
System.Diagnostics.ProcessStartInfo::Password
是一个酒店SecureString
- 本构造
X509Certificate2
需要一个SecureString
对于密码
主要目的是减少攻击表面,而不是消除它。 SecureStrings
是"固定"在RAM这样的垃圾收集器不移动或使副本。它还确保普通的文本不会得到写入交换文件或核垃圾场。加密的是更像混淆,并且不会停止的一个判定黑客,但是,谁能够找到的 对称的关键 用来加密和解密。
正如其他人所说的那样,你的原因必须创建一个 SecureString
逐字符的是因为第一个明显的缺陷的做否则:你大概有秘密的价值为普通的字符串了,所以有什么意义呢?
SecureString
s是第一个步骤,在解决一个鸡和蛋的问题,因此,即使虽然大多数当前的情况下,需要转换他们回到经常串做出的任何使用他们,他们的存在,在该框架现在意味着更好地支持他们的未来--至少到一个点,在那里你的程序中没有薄弱环节。
其他提示
许多伟大的答复;这里有一个简单的概要已经讨论过。
微软已经实施的SecureString类努力提供更好的安全敏感的信息(如信用卡的密码,等等)。它自动提供:
- 加密(在的情况下转储存 或页面缓存)
- 钉住在存储器
- 能力标记为只读(以防止任何进一步的修改)
- 安全建构,通过不允许一个不断串通过
目前,SecureString是有限的使用,但期望通过更好的未来。
基于这一信息,所构造的SecureString不应该只是采取一串和切的最char列为具有串阐明了失败的目的SecureString.
额外信息:
编辑:我发现很难挑选最好的回答,因为没有好的信息在很多;太糟糕了,没有协助的答案选项。
简短的回答
为什么我不能只是说:
SecureString password = new SecureString("password");
因为现在你有 password
在存储器;有没有办法把它擦-这是完全点的 SecureString.
只要回答
的原因 SecureString 存在是因为你不能使用 ZeroMemory 擦敏感的数据,当你完成了它。它的存在是为了解决一个问题,该问题存在 因 的CLR。
在一个正常的 本机的 应用程序,你会打电话 SecureZeroMemory
:
填补了一个框存储器零。
注意到:SecureZeroMemory是完全相同 ZeroMemory
, 除了编译器不会优化了。
问题是你 不能 呼叫 ZeroMemory
或 SecureZeroMemory
内。网。和中。净串不可改变;你甚至不能 复盖 内容串喜欢,你可以在其他语言:
//Wipe out the password
for (int i=0; i<password.Length; i++)
password[i] = \0;
所以你可以做什么?我们怎么提供的能力。净擦拭一个密码,或信用卡号码从记忆时我们用它做什么?
只有这样,它可以做到的就是地方的串在一些 本机的 存储块,你在哪里 可以 然后打电话 ZeroMemory
.本机存储器的对象,例如:
- 一个例如:
- 一个。
- CoTaskMem非托管存储器
SecureString给失去能力回来
中。网、串不可抹去时你与他们做:
- 他们是不可改变;你不能复盖他们的内容
- 你不能
Dispose
他们 - 他们清理受垃圾收集器
SecureString存在作为一种方式来绕过字符串的安全,并能够保证他们清理的时候你需要。
你问的问题:
为什么我不能只是说:
SecureString password = new SecureString("password");
因为现在你有 password
在存储器;有没有办法消灭它.它就卡在那里直到CLR发生决定重新使用的存储器。你已经把我们回到我们开始;一个运行的应用程序使用密码,我们不能摆脱的,并在一个转储存(或过程的监测)可以看到的密码。
SecureString使用的数据保护API储存的串密存储器;这样的串不会存在swapfiles,崩溃的垃圾场,或者甚至在地方变量的窗口,与一个同事找你应该。
我怎么读密码?
然后是一个问题:我怎么交互串?你绝对 不不 希望的方法,如:
String connectionString = secureConnectionString.ToString()
因为现在你回来你开始的-一个密码你无法摆脱。你想要的 力 开发人员来处理敏感的串正确使它 可以 被消灭,从存储器。
这就是为什么。净提供了三个方便的辅助功能到马绍尔SecureString成一个不受管存储器:
- SecureStringToBSTR (释放与 ZeroFreeCoTaskMemUnicode)
- SecureStringToCoTaskMemUnicode (释放与 ZeroFreeCoTaskMemUnicode)
- SecureStringToGlobalAllocUnicode (释放与 ZeroFreeGlobalAllocUnicode)
你转换的串成一个不受管存blob,处理它,然后擦一遍。
一些Api接受 SecureStrings.例如在ADO.net 4.5的 和.凭证 需要设置 SqlCredential:
SqlCredential cred = new SqlCredential(userid, password); //password is SecureString
SqlConnection conn = new SqlConnection(connectionString);
conn.Credential = cred;
conn.Open();
你也可以改变密码内的一连串:
SqlConnection.ChangePassword(connectionString, cred, newPassword);
并且有很多地方内。净在那里他们继续接受普通串的兼容性的目的,然后迅速转身,把它变成一个SecureString.
如何把文本进SecureString?
这仍然留下的问题:
我如何获得一个密码进入SecureString在首位?
这是一个挑战,但有一点是让你思考安全。
有时候功能已经提供给你。例如,WPF 东西 控制可以回报你的输入密码 SecureString 直接:
东西.SecurePassword酒店
获得密码的目前持有的 东西 作为一个 SecureString.
这是有益的,因为到处都是你用来传递一个原串,你现在有类型的系统的抱怨,SecureString是不符合串。你想要去尽可能长的时间之前具有转换你的SecureString回到正常串。
转换SecureString是容易的:
- SecureStringToBSTR
- PtrToStringBSTR
为:
private static string CreateString(SecureString secureString)
{
IntPtr intPtr = IntPtr.Zero;
if (secureString == null || secureString.Length == 0)
{
return string.Empty;
}
string result;
try
{
intPtr = Marshal.SecureStringToBSTR(secureString);
result = Marshal.PtrToStringBSTR(intPtr);
}
finally
{
if (intPtr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(intPtr);
}
}
return result;
}
他们只是真的不想你这样做。
但是我怎么得到一串成一SecureString?那么你需要做的是停止具有一个密码 字符串 在第一位。你需要它 的东西 人。即使一个 Char[]
阵列可能会有帮助。
这时候你可以添加的每一个字 和 擦明,当你完成的工作:
for (int i=0; i < PasswordArray.Length; i++)
{
password.AppendChar(PasswordArray[i]);
PasswordArray[i] = (Char)0;
}
你需要你的密码保存在 一些 记忆你能擦去。载入SecureString从那里。
tl博士: SecureString 存在提供相当于 ZeroMemory.
一些人们看不到这点 擦拭的用户密码,从存储器在设备被锁定, 或者擦 擦键从存储器之后,他们'authenticated.那些人不使用SecureString.
有非常少数的情况下,你可以明智地使用SecureString在目前版本的框架。它真的仅是有用的互动与非托管Api-你可元帅它利用元帅。SecureStringToGlobalAllocUnicode.
只要你把它从一个系统。String,你已经打败了其目的。
MSDN 样本 产生的SecureString一个角色的时间从控制台输入和通过安全串的非托管API。这是相当令人费解和不现实的。
你们可能预期的未来版本。网有更多的支持SecureString,这将使它更加有用,例如:
SecureString控制台。ReadLineSecure()或类似读控制台投入SecureString没有令人费解的代码样本。
它文本替换,储存其文本框。文本的财产作为安全串因此,可以将密码输入安全。
扩展与安全相关的Api允许的密码可作为传递SecureString.
没有上述,SecureString会的价值有限。
我相信你必须做一个字符追加而不是一个平面实例的原因是因为在后台传递“密码”而不是对于SecureString的构造函数,将“password”设置为“password”。内存中的字符串会破坏安全字符串的目的。
通过附加你只是将一个角色一次放入记忆中,这种记忆可能不会彼此相邻,从而使重建原始字符串变得更加困难。我可能在这里错了,但这就是我向他解释的原因。
该类的目的是防止通过内存转储或类似工具公开安全数据。
SecureString的一大好处是,它可以避免由于页面缓存而将数据存储到磁盘的可能性。如果您在内存中有密码然后加载大型程序或数据集,则当您的程序被分页内存不足时,您的密码可能会被写入交换文件。使用SecureString,至少数据不会无限期地以明文形式存在于您的磁盘上。
我想这是因为字符串是安全的,即黑客不应该阅读它。如果用字符串初始化它,黑客可以读取原始字符串。
好吧,正如描述所述,该值是加密存储的,意味着您的进程的内存转储不会显示字符串的值(没有一些相当严肃的工作)。
您不能仅仅从常量字符串构造SecureString的原因是因为那时将在内存中具有未加密的字符串版本。限制您分段创建字符串可以降低将整个字符串同时存储在内存中的风险。
我会停止使用SecureString。看起来PG家伙正在放弃对它的支持。可能甚至将来拉它 - https://github.com / dotnet / apireviews / tree / master / 2015-07-14-securestring 。
我们应该在.NET Core中的所有平台上从SecureString中删除加密 - 我们应该废弃SecureString - 我们可能不应该在.NET Core中公开SecureString
另一个用例是当您使用支付应用程序(POS)时,您只是无法使用不可变数据结构来存储敏感数据,因为您是谨慎的开发人员。例如:如果我将敏感的卡片数据或授权元数据存储到不可变的字符串中,那么这些数据在被丢弃后将在内存中可用大量时间的情况总是如此。我不能简单地覆盖它。这种敏感数据保存在内存中的另一个巨大优势是加密。