Reputation: 331
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
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