sglogowski
sglogowski

Reputation: 331

converting Byte array to SecureString

What is best way to create SecureString(unicode encoded) from byte array? I want to store my decrypted DEK key in memory, the decryption process is made by Azure.KeyVault(api), that produce byte array as a result.

var keyBytes = client.DecryptAsync(url, keyName, keyVersion, algorithm, encryptedKeyBytes).GetAwaiter().GetResult().Result;

I have created something like that but I am not proud from that implementations.

var secureKey = new SecureString();
var secureKeyCharArray = Encoding.Unicode.GetChars(keyBytes);

for (int i = 0; i < keyBytes.Length; i++)
{
    keyBytes[i] = 0;
}

for (int i = 0; i < secureKeyCharArray.Length; i++)
{
    secureKey.AppendChar(secureKeyCharArray[i]);
    secureKeyCharArray[i] = (char)0;
}

secureKey.MakeReadOnly();

After rewriting DEK key to SecureString variable I am cleaning both array: secureKeyCharArray and keyBytes but i dont know that it is enough.

Do you know some better solutions for that case? Maybe some nuget packages? Or maybe my whole idea is wrong?

Thanks for any suggestion.

=== Edited ===============================================================

But if we focus on storing secure data in memeory, do you know any better solution than SecureString? Work with this type is a little bit dificult, for example to read key from that vartiable I am using something like that:

IntPtr unmanagedString = IntPtr.Zero;
try
{
    unmanagedString = Marshal.SecureStringToGlobalAllocUnicode(securePassword);
    return Marshal.PtrToStringUni(unmanagedString);
}
finally
{
    Marshal.ZeroFreeGlobalAllocUnicode(unmanagedString);
}

I dont know that it is ok for production purpose to use Marshal classes.

Upvotes: 4

Views: 2727

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1064324

The most obvious problem is:

.GetAwaiter().GetResult().Result;

You should almost never do that; await would be far preferable:

var keyBytes = await client.DecryptAsync(url, keyName, keyVersion,
                                         algorithm, encryptedKeyBytes);

Using .GetAwaiter().GetResult().Result; on an incomplete awaitable operation can cause hard deadlocks. More generally, you should only try to access the result if you know (either by checking IsCompleted, or because you've awaited) that it is complete.


As for the rest: it really depends what your aim is here; and note that yes SecureString is more secure than string, but it isn't actually secure in the strong sense - a malicious user can still reverse it. It is mostly an inconvenience and something that makes it hard for memory scanners to find the data. Other than that, what you have looks OK? Note that if you want to avoid the AppendChar loop you could use fixed in an unsafe block and make use of the constructor that takes a char* and int, but that's just a performance tweak. You'd still need to erase the source array manually, of course. If you're going that route, and the password isn't large, you could actually stackalloc a block to decode into, rather than having secureKeyCharArray as an array. You would still need to manually wipe the stackalloc area when you're done.

Upvotes: 2

Related Questions