是有史以来SecureString的实际在C#应用程序? [英] Is SecureString ever practical in a C# application?

查看:989
本文介绍了是有史以来SecureString的实际在C#应用程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

随时纠正我,如果我的假设是错在这里,但让我解释一下为什么我问。

Feel free to correct me if my assumptions are wrong here, but let me explain why I'm asking.

从MSDN,两者一 SecureString的

这应该保密重新presents文本。文本是加密的隐私被使用时,以及从计算机存储器中删除不再需要时

Represents text that should be kept confidential. The text is encrypted for privacy when being used, and deleted from computer memory when no longer needed.

我得到这个,它使完整意义上存储在 SecureString的超过 System.String ,因为您可以控制​​如何以及何时实际上是存储在内存中,因为 System.String

I get this, it makes complete sense to store a password or other private information in a SecureString over a System.String, because you can control how and when it is actually stored in memory, because a System.String:

是不可变的,当不再需要,不能以编程方式安排垃圾回收;即,该实例是只读创建后,它不可能predict当实例将从计算机存储器中删除。因此,如果一个String对象包含敏感信息,如密码,信用卡号码或个人数据,存在使用后会因为你的应用程序不能从计算机内存中删除数据中的信息可以透露的风险。

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.

然而,在一个GUI应用程序(例如,SSH客户端)的情况下, SecureString的必须从一个的<建成code> System.String 。所有文本控件的用一个字符串作为其基础数据类型

However, in the case of a GUI application (for example, an ssh client), the SecureString has to be built from a System.String. All of the text controls use a string as its underlying data type.

所以,这意味着每次用户presses的关键,旧的字符串,在那里被丢弃,一个新的字符串是建立在重新present什么文本框中的值,甚至如果使用密码掩模。 我们无法控制的时候或任何这些值是从内存丢弃

So, this means that every time the user presses a key, the old string that was there is discarded, and a new string is built to represent what the value inside the text box is, even if using a password mask. And we can't control when or if any of those values are discarded from memory.

现在是时候登录到服务器。你猜怎么了?的您需要通过身份验证的连接的传递一个字符串。因此,让我们转换 SecureString的 System.String ....现在我们对堆字符串没有办法迫使它通过垃圾收集(或写0到缓冲区中)。

Now it's time to log in to the server. Guess what? You need to pass a string over the connection for authentication. So let's convert our SecureString into a System.String.... and now we have a string on the heap with no way to force it to go through garbage collection (or write 0's to its buffer).

我的观点是:不管你做什么,沿线某处,即 SecureString的终止的的到被转换成 System.String ,这意味着它将至少存在于堆在某些点(没有垃圾收集的任何保证)。

My point is: no matter what you do, somewhere along the line, that SecureString is going to be converted into a System.String, meaning it will at least exist on the heap at some point (without any guarantee of garbage collection).

我的观点是不可以:是否有规避发送一个字符串ssh连接,或具有控制存储逃避义务的字符串(创建一个自定义的控制)的方法。对于这个问题,你可以取代SSH连接和登录表,报名表,金表,食物 - 你 - 会 - 饲料 - 您 - 小狗,但并非您的子女组成等等。

My point is not: whether there are ways of circumventing sending a string to an ssh connection, or circumventing having a control store a string (make a custom control). For this question, you can replace "ssh connection" with "login form", "registration form", "payment form", "foods-you-would-feed-your-puppy-but-not-your-children form", etc.


  • 那么,在什么时候使用 SecureString的居然成了
    实用?

  • 是以往任何时候都值得额外的开发时间,以彻底根除
    使用 System.String 对象?

  • 是整点 SecureString的简单地减少时间量 System.String 在堆上(降低其移动到物理交换文件的风险)?

  • 如果攻击者已经有一堆检查手段,那么他们极有可能是(A)已经阅读击键,或(B)的手段已经的身体有机的...所以,将使用 SecureString的 prevent他们得到的数据反正?

  • 这只是安全通过隐藏?

  • So, at what point does using a SecureString actually become practical?
  • Is it ever worth the extra development time to completely eradicate the use of a System.String object?
  • Is the whole point of SecureString to simply reduce the amount of time a System.String is on the heap (reducing its risk of moving to a physical swap file)?
  • If an attacker already has the means for a heap inspection, then they most likely either (A) already have the means to read keystrokes, or (B) already physically have the machine... So would using a SecureString prevent them from getting to the data anyways?
  • Is this just "security through obscurity"?

如果我躺在太厚的问题,对不起,只是好奇心得到了我的好。随意回答任何或所有的问题(或者说我的假设是完全错误的)。 :)

Sorry if I'm laying the questions on too thick, curiosity just got the better of me. Feel free to answer any or all of my questions (or tell me that my assumptions are completely wrong). :)

推荐答案

SecureString的的其实很实用。

你知道有多少次我看到这样的场景(答案是:很多):

Do you know how many times I've seen such scenarios(answer is: many!):


  • 密码会出现在日志文件中意外。

  • 密码被显示在某个地方 - 一旦GUI的确显示应用程序时正在运行的命令行,然后在命令行组成的密码。 哎呀

  • 使用内存分析器来分析你的同事的软件。同事在内存中看到您的密码。听起来不真实?不尽然。

  • 我曾经使用的可以捕获局部变量的价值,在例外情况下,令人惊讶的有用展鹏软件。不过,我可以想像,它会记录的字符串密码偶然。

  • 系统崩溃转储包含字符串密码。

  • A password appears in a log file accidentally.
  • A password is being shown at somewhere - once a GUI did show a command line of application that was being run, and the command line consisted of password. Oops.
  • Using memory profiler to profile software with your colleague. Colleague sees your password in memory. Sounds unreal? Not at all.
  • I once used RedGate software that could capture the "value" of local variables in case of exceptions, amazingly useful. Though, I can imagine that it will log "string passwords" accidentally.
  • A crash dump that includes string password.

你知道如何避免这些问题? SecureString的。它通常可以确保你不要让愚蠢的错误如此。它是如何避免呢?通过确保密码在非托管内存加密,真正的价值可以当你90%的把握,你在做什么,只访问。

Do you know how to avoid all these problems? SecureString. It generally makes sure you don't make silly mistakes as such. How does it avoid it? By making sure that password is encrypted in unmanaged memory and the real value can be only accessed when you are 90% sure what you're doing.

在这个意义上, SecureString的容易的工作pretty:

In the sense, SecureString works pretty easily:

1)一切都被加密

2)用户呼叫 AppendChar

3)解密非托管内存的一切,并添加字符

3) Decrypt everything in UNMANAGED MEMORY and add the character

4)在非托管内存重新加密的一切。

4) Encrypt everything again in UNMANAGED MEMORY.

如果用户有权访问你的电脑?将病毒能够获得所有的 SecureStrings ?是。所有你需要做的是自己钩到 RtlEncryptMemory 内存被解密的时候,你会得到未加密的内存地址的位置,并读出来。瞧!事实上,你可以做一个病毒会不断扫描 SecureString的的使用,并记录所有活动吧。我并不是说这将是一件容易的事,但它可以做到的。正如你所看到的, SecureString的的强盛是完全消失,一旦出现在你的系统中的用户/病毒。

What if user has access to your computer? Would a virus be able to get access to all the SecureStrings? Yes. All you need to do is hook yourself into RtlEncryptMemory when the memory is being decrypted, you will get the location of the unencrypted memory address, and read it out. Voila! In fact, you could make a virus that will constantly scan for usage of SecureString and log all the activities with it. I am not saying it will be easy task, but it can be done. As you can see, the "powerfulness" of SecureString is completely gone once there's a user/virus in your system.

您在您的文章几点。当然,如果你使用一些持有字符串密码在内部,使用的UI控件的实际 SecureString的是没有多大用处的。不过,尽管如此,它可以防止一些愚蠢,我上面列出。

You have few points in your post. Sure, if you use some of the UI controls that hold "string password" internally, using actual SecureString is not that useful. Though, still, it can protect against some stupidity I've listed above.

此外,正如其他人所指出的,WPF支持PasswordBox它使用 SecureString的内部。

Also, as others have noted, WPF supports PasswordBox which uses SecureString internally.

底线是;如果你有敏感数据(密码,信用卡卡,..),使用 SecureString的。这是C#框架是继什么。例如,的NetworkCredential 类存储密码 SecureString的。如果你看看<一个href=\"http://referencesource.microsoft.com/#mscorlib/system/security/securestring.cs#77d68ea938f47705#references\">this,你可以看到在〜80不同的用途在.NET框架 SecureString的

The bottom line is; if you have sensitive data(passwords, credit-cards, ..), use SecureString. This is what C# Framework is following. For example, NetworkCredential class stores password as SecureString. If you look this, you can see over ~80 different usages in .NET framework of SecureString.

有很多情况下,你必须 SecureString的转换为字符串,因为有些API希望它。

There are many cases when you have to convert SecureString to string, because some API expects it.

通常的问题可以是:


  1. 的API是通用的。它不知道,有一个敏感的数据。

  2. 的API知道它在处理敏感数据,并使用串 - 这只是糟糕的设计

您提出好一点:当 SecureString的转换为会发生什么字符串?这只能发生,因为第一点。如API不知道它的敏感数据。我个人没有看到,正在发生的事情。获取串出SecureString的是并非如此简单。

You raised good point: what happens when SecureString is converted to string? This can only happen because of the first point. Eg the API does not know that it's sensitive data. I have personally not seen that being happening. Getting string out of SecureString is not that simple.

这是一个简单的原因并不简单;它从来就没有打算让用户转换SecureString的字符串,如你所说:GC会踢如果你看到自己这样做,你需要退一步,问问自己:为什么我即使这样,还是我真的需要这一点,为什么呢?

It's not simple for a simple reason; it was never intended to let the user convert SecureString to string, as you stated: GC will kick in. If you see yourself doing that, you need to step back and ask yourself: Why am I even doing this, or do I really need this, why?

还有,我看到一个有趣的情况。也就是说,WINAPI功能LogonUser的需要LPTSTR作为密码,这意味着你需要调用 SecureStringToGlobalAllocUni code 。这基本上让你生活在非托管内存未加密的口令。你需要尽快就大功告成了摆脱这一点。

There's one interesting case I saw. Namely, WinApi function LogonUser takes LPTSTR as a password, which means you need to call SecureStringToGlobalAllocUnicode. That basically gives you unencrypted password that lives in unmanaged memory. You need to get rid of that as soon as you're done.

您可以随时扩展方法延长 SecureString的类,如 ToEncryptedString(__ SERVER__PUBLIC_KEY),这给 SecureString的的你字符串实例正在使用服务器的公钥加密。那么只有服务器可以将其解密。问题解决了,GC将永远不会看到的原始的字符串,因为你永远不暴露其托管内存。这究竟是什么正在<一做href=\"http://referencesource.microsoft.com/#System.Management.Automation/System/Management/Automation/Internal/PSRemotingCryptoHelper.cs\"><$c$c>PSRemotingCryptoHelper EncryptSecureStringCore(SecureString的SecureString的))。

You can always extend the SecureString class with an extension method, such as ToEncryptedString(__SERVER__PUBLIC_KEY), which gives you a string instance of SecureString that is encrypted using server's public key. Only server can then decrypt it. Problem solved, GC will never see the "original" string, as you never expose it in managed memory. This is exactly what is being done in PSRemotingCryptoHelper (EncryptSecureStringCore(SecureString secureString)).

和的东西非常近有关:单SecureString的根本不加密。实施已被注释掉,因为..wait它.. <一个href=\"https://github.com/mono/mono/blob/master/mcs/class/corlib/System.Security/SecureString.cs#L259\">\"It某种原因导致NUnit测试断裂,这使我的最后一点:

And as something very almost-related: Mono SecureString does not encrypt at all. The implementation has been commented out because ..wait for it.. "It somehow causes nunit test breakage", which brings to my last point:

SecureString的不到处支持。如果平台/体系结构不支持 SecureString的,你会得到异常。还有的在文档中支持平台的列表。

SecureString is not supported in everywhere. If the platform/architecture does not support SecureString, you'll get exception. There's a list of platforms that are supported in the documentation.

我最长的计算器后,谁可以指望我重复了多少遍 SecureString的将获得+1: - )

My longest StackOverflow post and anyone who can count how many times I repeated SecureString will get +1 :-).

这篇关于是有史以来SecureString的实际在C#应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆