【问题标题】:How do you cleanup after retrieving SecureString value?检索 SecureString 值后如何清理?
【发布时间】:2013-09-06 02:11:51
【问题描述】:

我正在一个项目中实施 SecureString。在阅读它并看到很多基本上做同样事情的例子之后,我一直认为有些地方是错误的。

以下面的代码为例:

public static string ToUnsecureString(this SecureString secureString)
{
    if(secureString == null)
        throw new ArgumentNullException("secureString");

    IntPtr unmanagedString = IntPtr.Zero;
    try
    {
        unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(secureString);
        return Marshal.PtrToStringUni(unmanagedString);
    }
    finally
    {
        Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
    }
}

保护数据固然很好,但最终它再次被设置为标准字符串的真正意义何在?

我知道您可以将密码存储在char[] 中,然后在创建SecureString 后将其清零,但是在检索字符串时我应该怎么做?我没有看到将其作为char[] 检索的方法,并且不会只调用.ToCharArray() 仍将Marshal.PtrToStringUni(...) 返回的字符串留在内存中吗?

我只是错过了一些非常基本的东西吗?谢谢。

【问题讨论】:

  • 当您不得不再次取出钱时,将钱存入银行有什么意义?关键是它在那里时是安全的。这个问题对我来说很奇怪;问题基本上是“我从它所在的安全盒子中取出了一些东西,现在它没有安全保障,那么为什么我首先要把它放在盒子里?”我不知道;你告诉我。如果你打算把它拿出来,为什么要把它放在一个安全的盒子里?
  • @EricLippert 我了解你来自哪里,我会用你的例子作为我提问的理由(这可能是有缺陷的)。是的,一旦物品从安全盒中取出,它就是不安全的。但是,您始终可以将物品放回盒子中。由于字符串是不可变的,即使在方法返回之后,它们是否也不会在内存中存储很长一段时间?如果我弄错了,请告诉我,我会继续删除这个问题。谢谢
  • 关键是你永远不会把它放到托管字符串中。要么直接在低级代码中使用它,要么将数据复制到一个 mutable 数组,在使用后直接擦除(但由于 GC 在内存中移动对象,即使这样也很棘手)
  • 关于SecureString 的另一个重要点是,它只是为了让字符串远离故障转储、交换文件等。而不是为了保护字符串免受用户或恶意进程的影响。
  • “没有找到将其检索为 char[] 的方法”Marshal.Copy 呢?

标签: c# .net security securestring


【解决方案1】:

你说得对——在托管代码中使用SecureString 的内容非常愚蠢。但是,对于 Windows Credential API 等 P/Invoke API,它只是让您的密码远离窥探。

另一种可能性是调用Marshal.SecureStringToBSTR() 并在非托管代码中进行所有处理,您仍然可以保持一些安全性。

【讨论】:

  • 那么在unsafe 上下文中执行此操作将有助于释放内存中的实际字符串?在 Web 应用程序上执行此操作有什么问题吗?
  • 我说错了。这就是我在半夜回答的结果。然后,当然还有昨天没看到的这个小宝石:stackoverflow.com/a/11459012/136062
  • 优秀。非常感谢那个链接。如果你想更新你的答案,我会接受。它适合我不希望在不可变字符串中包含敏感数据的需求。
猜你喜欢
  • 2018-12-02
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-24
相关资源
最近更新 更多