It's a well known fact that C#
string is pretty insecure, it's not pinned in RAM, the Garbage Collector can move it, copy it, leave multiple traces of it in RAM and the RAM can be swapped and be available as a file to be read, not mentioning several other known facts.
In order to mitigate this Microsoft came up with
SecureString. The thing is: what is the proper way of using it?
I ask this because sooner or later you will have to extract the inner string. And yes,
SecureString does allow us to write one
char at a time and gives us some other minor usages while hiding it's secret, but sometimes we need the whole string at once or something like it. So far all implementations I see use a regular
string at the end, with the extracted and decrypted content from the
SecureString which I think (or hope) it's avoidable in some cases even though it might involve some complicated code to get around a .NET
In my case I use a library for password hashing called BCrypt. It uses a regular
string for calculating the hashes, which I think is far from ideal. I didn't find any libraries that would accept a
SecureString directly, so I don't have much of an option but use it.
Currently I run code such as this:
SecureString password; // This usually comes from a PasswordBox Property IntPtr passwordBSTR = Marshal.SecureStringToBSTR(password); string insecurePassword = Marshal.PtrToStringBSTR(passwordBSTR); Marshal.ZeroFreeBSTR(passwordBSTR); passwordBSTR = default(IntPtr); password.Clear(); // Use the insecurePassword....usually as: bool result = BCrypt.Net.BCrypt.Verify(insecurePassword, user.Password); // This hashes the provided password and compares it with another BCrypt hash. insecureString = string.Empty; // hoping for the GC to act now, fingers crossed. // use result and etc...
This way the password raw
string will be copied multiple times for the
BCrypt method and probably even more times inside it.
This makes some questions arise in my mind:
1 - Are
BSTR strings like
C strings in the sense of memory management? Are they pinned in RAM and I can manipulate them and erase them as I see fit so it will be more secure to use them in C# or interop it with a C++ code so I can eliminate a lot of my .NET
string manipulations (like verifying if the password string is null or white space or has the correct length or has the desired password strength)?
2 - If question's #1 answer is "yes" then should I invest some time to pass the BSTR string to a interop C++ code to calculate it's hash and verify?
3 - Is my later code correct or am I missing something on
Just to be clear: My main intent with this question is to evaluate if I should pass all my password handling code to C++ from my C# (probably using C++/CLI or interop) to achieve a more secure code than what C# has to offer. This scenario really concerns me for password string hashing were multiple strings will be created and copied with the user's secret information scattered all over the RAM.
As an example: I could make a method like:
public string SecureHash(SecureString password)
And this method will extract the
SecureString value and pass it as a
BSTR string (or other extraction option, I honestly don't know the benefits between them) to a C++ hashing method, so we can control all the places our password sits in memory.
I ask this to not have a huge work refactoring my code and in the end discover it was all for nothing because I was using
SecureStrings wrongly all the time and there are already solutions for this, or a false sense of security, as it happens sometimes, since I am not aware of how
BSTR strings are implemented in memory or the other
SecureStrings extraction options (Unicode, ANSI and etc).