问题
The use case is to protect strings in memory programming in c#. The use of the class SecureString (https://docs.microsoft.com/en-us/dotnet/api/system.security.securestring?view=netframework-4.7.2) is discouraged by Microsoft itself.
I was wondering if it could be a valid alternative to:
- transform the string in a byte array and immediately set the string to null (and eventually call the garbage collector),
- encrypt the byte array with the class ProtectedMemory.
Any suggestion?
回答1:
There is no alternative to the SecureString
class. The 'alternative' Microsoft encourages is found here:
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.
So, if you really need the credentials and there is no other way: on .NET Framework, use SecureString
. For .NET Core there is no alternative at the moment.
回答2:
I wouldn't say it's "discouraged by Microsoft" - that's an oversimplification. The actual reasons are given in this page ( https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md ) and the argument seems to be "it isn't worth the effort to use it in .NET Core", and not that it isn't secure overall.
I contend that SecureString
is secure... but only for the .NET Framework on Windows. The page I linked to is from the .NET Core project which is cross-platform - so it makes sense to discourage or disallow the use of SecureString
in .NET Core - but if your project is targeting .NET Framework (which is exclusive to Windows) or is targeting .NET Core for Windows - then you're fine. The quote is below (emphasis mine):
The contents of the array is unencrypted except on .NET Framework.
BTW, SecureString
can be used securely to avoid cleartext in memory if you only read secrets directly into the SecureString
directly by using its Append
method. This is most useful when reading passwords from the console (pseudocode):
Console.WriteLine( "Enter your password" );
SecureString password = new SecureString();
while( Char c = Console.ReadKey() != '[Enter'] ) {
password.Append( c );
}
...however if you need access to the cleartext version of the string afterwards then it's less secure (though the cleartext string would hopefully be collected by GC as a Generation 0 object).
Regarding your proposal:
- transform the string in a byte array and immediately set the string to null (and eventually call the garbage collector)
- encrypt the byte array with the class ProtectedMemory.
This is exactly how SecureString works already, and it still suffers from the same problems: the cleartext copy of the encrypted contents still exists in memory for a short period of time - that's the problem.
回答3:
So the basic question you are asking is "since Microsoft discourages the user of SecureString, can I roll my own?".
Well, apart from the fact that your implementation will likely be less secure than Microsoft's original version, it will also at least share the same problems, because they are not with the specific implementation, but with the concept.
If you want to use the concept, you could as well use SecureString. The solution is to not use the concept of encrypted credentials in memory, neither with Microsoft's classes, nor with your own homebrew.
来源:https://stackoverflow.com/questions/55590869/how-to-protect-strings-without-securestring