When would I need a SecureString in .NET?
Some parts of the framework that currently use SecureString
:
- WPF's
System.Windows.Controls.PasswordBox
control keeps the password as a SecureString internally (exposed as a copy throughPasswordBox::SecurePassword
) - The
System.Diagnostics.ProcessStartInfo::Password
property is aSecureString
- The constructor for
X509Certificate2
takes aSecureString
for the password
The main purpose is to reduce the attack surface, rather than eliminate it. SecureStrings
are "pinned" in RAM so the Garbage Collector won't move it around or make copies of it. It also makes sure the plain text won't get written to the Swap file or in core dumps. The encryption is more like obfuscation and won't stop a determined hacker, though, who would be able to find the symmetric key used to encrypt and decrypt it.
As others have said, the reason you have to create a SecureString
character-by-character is because of the first obvious flaw of doing otherwise: you presumably have the secret value as a plain string already, so what's the point?
SecureString
s are the first step in solving a Chicken-and-Egg problem, so even though most current scenarios require converting them back into regular strings to make any use of them at all, their existence in the framework now means better support for them in the future - at least to a point where your program doesn't have to be the weak link.
Edit: Don't use SecureString
Current guidance now says the class should not be used. The details can be found at this link: https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md
From the article:
DE0001: SecureString shouldn't be used
Motivation
- The purpose of
SecureString
is to avoid having secrets stored in the process memory as plain text. - However, even on Windows,
SecureString
doesn't exist as an OS concept.- It just makes the window getting the plain text shorter; it doesn't fully prevent it as .NET still has to convert the string to a plain text representation.
- The benefit is that the plain text representation doesn't hang around
as an instance of
System.String
-- the lifetime of the native buffer is shorter.
- The contents of the array is unencrypted except on .NET Framework.
- In .NET Framework, the contents of the internal char array is encrypted. .NET doesn't support encryption in all environments, either due to missing APIs or key management issues.
Recommendation
Don't use SecureString
for new code. When porting code to .NET Core, consider
that the contents of the array are not encrypted in memory.
The general approach of dealing with credentials is to avoid them and instead rely on other means to authenticate, such as certificates or Windows authentication.
End Edit : Original Summary below
Lots of great answers; here’s a quick synopsis of what has been discussed.
Microsoft has implemented the SecureString class in an effort to provide better security with sensitive information (like credit cards, passwords, etc.). It automatically provides:
- encryption (in case of memory dumps or page caching)
- pinning in memory
- ability to mark as read-only (to prevent any further modifications)
- safe construction by NOT allowing a constant string to be passed in
Currently, SecureString is limited in use but expect better adoption in the future.
Based on this information, the constructor of the SecureString should not just take a string and slice it up to char array as having the string spelled out defeats the purpose of SecureString.
Additional info:
- A post from the .NET Security blog talking about much the same as covered here.
- And another one revisiting it and mentioning a tool that CAN dump the contents of the SecureString.
Edit: I found it tough to pick the best answer as there's good information in many; too bad there is no assisted answer options.