long time lurker here finally having a question that I'm not seeing. I am writing a c# console application in dotnet core and trying to allow a user to input a password, and am concerned about security, particularly memory dumping.
Following: Password masking console application my understanding is that a password stored as a string variable could be exposed through a memory dump (reference).
SecureString would normally be the way to go here but doesn't seem to be supported in dotnet core.
I've tried to modify the code to use a char array, because my limited understanding is that it is not immutable so it will not all be stored in a single piece of memory. Honestly though security is not my forte, so my question is if this code below properly protects me from exposing the password through a memory dump?
Console.WriteLine("Enter pass");
char[] passwordArray = new char[256];
int whileIndex = 0;
while (true)
{
ConsoleKeyInfo key = Console.ReadKey(true);
if (key.Key == ConsoleKey.Enter)
{
break;
}
else if (key.Key == ConsoleKey.Backspace)
{
if (whileIndex != 0) //so it doesn't explode if someone holds backspace
{
whileIndex--;
}
}
else
{
passwordArray[whileIndex] = key.KeyChar;
whileIndex++;
}
}
//Truncate array to length of password
var endIndex = Array.IndexOf(passwordArray,'\0');
char[] shortenedPasswordArray = new char[endIndex];
Array.Copy(passwordArray, shortenedPasswordArray, endIndex);
//Authentication code here
//Wipe the characters when done
foreach(var passChar in passwordArray)
{
passwordArray[passChar] = '\0';
}
foreach (var passChar in shortenedPasswordArray)
{
shortenedPasswordArray[passChar] = '\0';
}
I would store the user's input after it has been processed by a secure password hashing algorithm. Have the same algorithm accessible when the user needs to authenticate again, and use the result to verify the user.
Some comments: 1) First and foremost remember that security is not solved in one application. For somebody with full access to the machine there is (almost) nothing you can do to keep a password truly secure.
(Fun exercise: How would you authenticate a password without keeping the password in memory at all?)
2) SecureString only gives you more control over the lifespan of a password in memory by letting you determine when it goes away. A normal string may last a very long time in memory, even until the program exits, since it doesn't go away until garbage collection. SecureString lets you explictly wipe it, but it still exists in memory until then.
3) Using your own char array is a good idea, but I might have used a List because it allows a variable length, or maybe even a LinkedList because it spreads the characters out in memory. Shrug. Refer back to #1 and consider what kind of attacks you're protecting the password from.