How to Secure Memory?

Sometime you might want to protect your data in memory - the greatest example is when dealing with anything related to passwords. It is simply not smart to keep that data around in a plain-text.

In .NET there are multiple methods you can use for this purpose, starting with SecureString, ProtectedMemory, and my favorite ProtectedData.

Each of these has its advantages and disadvantages and definitely each can find its place in a security toolbox. However, I prefer ProtectedData because it doesn't require any Win32 API magic to read (as SecureString), nor it has any limitations on block length (as ProtectedMemory). As long as you are ok dealing with byte arrays, you can use it almost as a transparent storage.

Most of the times I end up having something like this (the most basic form):

private static RandomNumberGenerator Rnd = RandomNumberGenerator.Create();
private byte[] RawDataEntropy = new byte[16];
private byte[] RawData = null;

internal byte[] Data {
get {
if (this.RawData == null) { return new byte[0]; } //return empty array if no value has been set so far
return ProtectedData.Unprotect(this.RawData,
set {
Rnd.GetBytes(this.RawDataEntropy); //new entropy every save
this.RawData = ProtectedData.Protect(value,

On each write we let Windows encrypt the data using a random entropy (in addition to its standard encryption) while on every read we simply decrypt the data and return a copy of it. Care should be taken to delete copies lying around, i.e. when you set the property and encrypt data, you should delete the original. Best practice for delete is to use Array.Clear, e.g.:

Array.Clear(value, 0, value.Length);

I will leave it for reader's exercise why that might be preferred to a simpler value = null.

PS: Note that, as soon as you convert bytes to a string (e.g. to show it to the user), you have signed capitulation as now you have an unencrypted copy of the protected data in memory. Yes, sometime you need to do it, but keep it brief.

Leave a Reply

Your email address will not be published. Required fields are marked *