14

我一直在使用 C# 为自己编写一个小程序,我可以用它来存储我的密码,然后检索它们以进行查看/编辑。

虽然密码以加密格式存储到磁盘中,但当它们被读入内存以在表单上显示/编辑时,它们是未加密的。

我了解到,在内存中有未加密的密码是一个相当大的安全问题,所以我遇到了这SecureString门课。

有没有比使用SecureString类更安全的方法,还是SecureString名副其实?

4

4 回答 4

16

SecureString将其文本加密保存在内存中,您可以在不需要时立即将其丢弃。问题是,当您想以几乎任何其他方式显示或使用它时,您必须将其转换为普通字符串,这是不安全的。

此外,我不会过分依赖它——系统无需任何解密密钥即可对其进行解密,这意味着坚定的黑客很可能也能做到这一点。当黑客控制您的计算机时,您无法确定任何事情,他可能能够访问任何未使用具有良好密钥的良好算法加密的任何内容。

于 2011-06-26T12:26:30.190 回答
14

SecureString 以某种方式保护字符串的内存实例,但是您应该注意一些重大缺点。

  • 可以在没有解密密钥的情况下检索 SecureString(正如 svick 指出的那样),因此任何熟练到足以检索您可以放心假设的这块内存的黑客都可以轻松地执行这个小操作来检索纯文本字符串。考虑简单性SecureStringToBSTR(input);
  • SecureString 需要以逐个字符的方式填充,因为没有 .Text 属性 Get 或 Set 访问器可供使用。在包括 MSDN 在内的博客上,您经常会看到如下代码:

    public static SecureString StringToSecureString(string input)
    {
        SecureString output = new SecureString();
        int l = input.Length;
        char[] s = input.ToCharArray(0, l);
        foreach (char c in s)
        {
            output.AppendChar(c);
        }
        return output;
    }
    

这段代码的一个重要问题是,开发人员一开始就允许input字符串存在于内存中。用于从用户那里收集此密码的 PasswordBox 的用户控件或 WinForm TextBox 永远不应在一次操作中收集整个密码,因为

  • 黑客可以直接访问内存,直接从栈上的控件中取回密码,或者在该方法的实例化上注入代码取回密码
  • 如果上次蓝屏时您的最后一个内存转储仍然驻留在您的计算机上,并且此控件中填充了您的纯文本密码,那么该密码位于一个整洁的小文件中,准备好让您的黑客在他/她的闲暇。

而是考虑使用 KeyPress 从用户那里检索每个字符的选项,否则,我相信 WPF 的 PasswordBox 默认由 SecureString 支持(其他人可能会确认这一点)。

最后,还有更简单的方法可以从 Key Loggers 等用户那里收集密码。我的建议是考虑你的用户人口统计、暴露风险,并确定像 SecureString 这样微不足道的东西是否真的会削减它。

于 2012-01-02T22:43:29.567 回答
1

SecureString 正是它的名字所说的,你猜到了:它保存了也在内存中加密的字符串,所以是的,这是正确的方法。
这里

表示应保密的文本。文本在使用时被加密以保护隐私,并在不再需要时从计算机内存中删除。这个类不能被继承。

于 2011-06-26T12:12:38.963 回答
-3

你们让这种方式太复杂了。没有人问这是否是解决问题的最佳方法。他们只是想看看一些工作代码。天哪。在本例中,passwordPre 是使用您的专有解密算法从资源(例如配置文件)中解密的字符串。

    string passwordPre = DecryptProprietary(objectReferringToPassword);
    char[] passwordChars = passwordPre.ToCharArray();        
    System.Security.SecureString securePassword = new System.Security.SecureString(); // in production, this should probably be a global variable
    foreach (char c in passwordChars)
        securePassword.AppendChar(c);

    string decryptedPassword = new System.Net.NetworkCredential(string.Empty, securePassword).Password; // this is how to convert it to a string for quick usage to access the protected resource

因此,您可以快速使用解密的密码来访问您需要的任何资源,然后通过退出该方法来处理它。

于 2016-06-09T13:34:56.487 回答