I have a C# application which initializes some variables with sensitive data. They are not password, but we consider them sensitive though. The variable values I want to protect are all of string type.
What I am trying to do is to find a mechanism (I know there is not 100% mechanism) that allows me to protect in-memory variable values or at least to make it a little bit more difficult to the attackers to read them. So I can protect sensitive data in-memory of my application and make it more "unreadable" by any other application that can trace, dump or read my application at runtime.
I see that exist the Microsoft Data Protection API (DPAPI), which has a class called ProtectedMemory which offers two methods protect and unprotect, here is an example.
Anyway it looks like MS stopped use ProtectedMemory as some guy is saying here since it is not useful.
Other people here instead suggest to hash them with a good function (e.g. SHA1/2) and store the digest.
I would like to use private properties (as it is only used within my class) instead of a simple variable which its set property encrypts it into memory and the get property, decrypts it. As below:
public static MyClass
{
private string MyVariable
{
get
{
return Encoding.UTF8.GetString(ProtectedMemory.Unprotect(_myVariable, MemoryProtectionScope.SameLogon));
}
set
{
_myVariable = Encoding.UTF8.GetBytes(value);
ProtectedMemory.Protect(_myVariable, MemoryProtectionScope.SameLogon);
}
}
private byte[] _myVariable;
}
And the same for the rest of my string variables.
I wanted to do the same as this guy in his post but some people there say moving the protected memory from a private backing field to a property is not going to help (i am not sure what he is referring to, if using a property is not being protected¿?). Could you also confirm me if using a private property for my variables is going to be protected in memory or not?
So how can I do this? could somebody provide a simple code snippet? The encryption/decryption process should be relatively fast.
I do not want to use any third-party, only OS help and .NET Framework.
.NET offers
SecureStringfor this ostensible purpose. But it comes with a huge caveat that all but destroys its utility:Very few .NET APIs support it. This means that you would need to convert between
SecureStringandstringmany times in the lifecycle of your application. Every time this is done is an opportunity for the secret value to leak into unencrypted RAM. You have to be extremely meticulous therefore in wiping plaintext copies of the string when they're no longer needed by usingunsafecode. Plus, you don't know how many copies of your secret will be created when passing thatstringto other APIs. Take JSON serialization for example - if you need to put yourSecureString's unencrypted value in a JSON stream, that value could easily exist somewhere else in RAM, possibly many times over, after JSON serialization is finished. Same goes for HTTP headers and other places where secrets are commonly exchanged.With all that said, if you want to take the plunge, you'll need to be aware of how to convert from a
SecureStringto a normalstringfor the 99.99% of .NET APIs that don't support it:and how to convert a normal
stringto aSecureString:And finally, you need a way to zero-out the bytes of a plaintext
stringwhen you're done with it:And you have to be EXTREMELY careful with that last one; due to the way .NET caches strings, this could have more consequences than you'd expect. You should never use this except on plaintext strings converted from
SecureStringusing theToInsecureStringabove, since you know those will exist in their own buffer.Is all this worth it? Honestly probably not. It's almost always a losing battle to try to keep secrets protected in-RAM. But if you want to try it, or just need to check a box on an audit form, then go for it.