Fra*_*ghi 5 c# encryption securestring
用例是在 c# 中保护内存编程中的字符串。Microsoft 本身不鼓励使用 SecureString 类 ( https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netframework-4.7.2 )。
我想知道它是否可以作为一个有效的替代方案:
有什么建议吗?
tl;dr:SecureString是一个好且正确的想法。微软不再推荐它的原因是.NET Core不能拥有它,因为Linux不支持加密。
您需要SecureString有两个原因。
第一个与 HeartBleed 攻击类似,也是SecureZeroMemory存在的原因,也是 Windows在将内存页面提供给您之前始终将其归零的原因:以避免泄漏信息。
奖励阅读
终端服务将未加密的用户密码保存在 RAM 中。
第二个,也是 .NET 中存在 SecureString 的原因,是因为您无法调用SecureZeroMemory。.NET 中的字符串是不可变的,您无法控制它们的生命周期。
因此,要解决这个问题,有两个要素:
当它是一个数组时,意味着你可以擦除其中的内容。这意味着你可以做道德上相当于ZeroMemory
处理完敏感信用卡号、比特币私钥、密码、英特尔蓝光主密钥后的操作:您可以擦除它们
这解决了完全无法擦除C#字符串的问题
CryptProtectData
SecureString 的另一个不相关的优点是原始字符串不会出现在内存转储、虚拟机 RAM 快照、Web 服务器日志、调试器监视窗口中。或者在HeartBleed 攻击的情况下,不会出现在分发给其他网站用户的未初始化数据中。
这是SecureString的两个核心元素。
两者都可以复制。.NET Core 没有它们的原因并不是因为 SecureString 是一个坏主意,或者是一个浪费的想法,或者是一个不完整的想法,或者“没有兑现它的承诺”。相反,这是因为 Linux 没有相当于CryptProtectData
. 由于 .NET Core 必须是跨平台的,因此它们必须满足最低的共同点。所以他们举手说把它拿走。
但 SecureString 作为一个概念同样有效:
任何持相反观点的人都是彻头彻尾的谎言。
您想使用 SecureString
CryptProtectData
存在CryptProtectMemory
存在这是否意味着信用卡号在某个时刻以明文形式存在于内存中:
不,原因是它的用途非常有限,并且在大多数情况下,该字符串要么保留在内存中,要么重新出现。原始字符串保留在内存中,直到被GCd。由于 SecureString 在 Win32 API(或 Linux)中没有对应项,因此一旦应用程序尝试对其执行任何操作,原始字符串就会重新出现。即使在 SDK 中,也只有 NetworkCredentials 正确使用了它,而 SecureString 不是 Windows 概念,因此一旦您使用 Windows API,它就会被转换回来。
但我们必须认识到的是:
这些都是很好的纵深防御措施。
任何不同的说法都是错误的。
我不会说它“被微软劝阻”——这过于简单化了。此页面中给出了实际原因(https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md)并且论点似乎是“不值得努力使用它在 .NET Core 中”,并不是说它总体上不安全。
我认为这SecureString
是安全的……但仅适用于 Windows 上的 .NET Framework。我链接到的页面来自跨平台的 .NET Core 项目 - 因此不鼓励或禁止SecureString
在 .NET Core 中使用是有意义的- 但如果您的项目面向 .NET Framework(Windows 独有)或者针对.NET核心的窗口-那么你的罚款。报价如下(强调我的):
除 .NET Framework 外,数组的内容未加密。
顺便说一句,SecureString
如果您仅SecureString
使用其Append
方法直接将机密直接读入,则可以安全地使用以避免内存中的明文。这在从控制台读取密码(伪代码)时最有用:
Console.WriteLine( "Enter your password" );
SecureString password = new SecureString();
while( Char c = Console.ReadKey() != '[Enter'] ) {
password.Append( c );
}
Run Code Online (Sandbox Code Playgroud)
...但是,如果您之后需要访问字符串的明文版本,那么它就不那么安全了(尽管明文字符串有望被 GC 作为第 0 代对象收集)。
关于你的提议:
- 将字符串转换为字节数组并立即将字符串设置为 null(并最终调用垃圾收集器)
- 使用类 ProtectedMemory 加密字节数组。
这正是 SecureString 的工作方式,但它仍然存在相同的问题:加密内容的明文副本仍然存在于内存中一小段时间——这就是问题所在。
因此,您要问的基本问题是“既然 Microsoft 不鼓励 SecureString 用户,我可以推出自己的吗?”。
好吧,除了您的实现可能不如 Microsoft 原始版本安全之外,它至少也会遇到相同的问题,因为它们不是与具体实现有关,而是与概念有关。
如果你想使用这个概念,你也可以使用 SecureString。解决方案是不要在内存中使用加密凭据的概念,无论是 Microsoft 的类还是您自己的自制程序。
归档时间: |
|
查看次数: |
5184 次 |
最近记录: |