converting Byte array to SecureString - c#

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.

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.

Related

Looping as an expression

I come across things where this would be useful rather often, and if it exists I want to know about it. I'm not really sure how to explain it to search for it, but it's basically a one line loop statement- similar to a lambada. This isn't the best example (it's a simple solution without this), but it's what was on my mind when I decided to finally ask this question. But this is the kind of thing I'm talking about.
(The following is what I'm thinking of looks like. I'm asking if something similar exists)
In my current situation, I am converting a string into a byte array to write to a stream. I want to be able to do this to create the byte array:
byte[] data = String ==> (int i; Convert.ToByte(String[i]))
Where i is the number in the string based on it's length, and the next line is the output for item.
You should read about LINQ.
Your code can be written as:
var String = "some string";
byte[] data = String.Select(x => Convert.ToByte(x)).ToArray();
or even with method group:
byte[] data = String.Select(Convert.ToByte).ToArray();

Simple ASP.NET password hashing class troubles

I am attempting to apply some security to a project I'm completing for college. This security is somewhat glancing so I'm tempted to give up, save passwords as plaintext or converted to base64, and do something more user-obvious.
Before I give up, I'm asking SO. This is my first attempt at asking anything here so please be gentle.
I decided that implementing this MSDN code wouldn't be too hard.
http://msdn.microsoft.com/en-us/library/aa545602%28v=cs.70%29.aspx
Turns out, it really is. I'm getting the error
System.FormatException: Input string was not in a correct format.
For code
binarySaltValue[0] = byte.Parse( salt.Substring( 0, 2 ), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat );
I'm going to be honest, I don't fully understand this code.
What is SaltValueSize supposed to be? The provided code doesn't supply it, neither do any References. Also it's capitalised, so is it an object? Or a field in some object somewhere?
The variable "hash" is not defined anywhere, so I just filled it with new MD5CryptoServiceProvider(). Is this a mistake?
If I'm reading it right, the string "salt" is supposed to hold binary, but it doesn't at runtime, it has garbled text, meanwhile the line everything crashed at is trying to parse binary from "salt"? Why?
If anyone can fix this or supply an idiot-proof asynchronous hashing class I'd appreciate it.
( apologies for my random user name, I have no idea how that happened )
Here's a basic method (no salt) to at least get you started. It just "hashes" the string coming in.
private string GetHashedString(string _PW)
{
string _HashedPW = "";
SHA512 sha = new SHA512CryptoServiceProvider();
byte[] result;
StringBuilder strBuilder = new StringBuilder();
sha.ComputeHash(ASCIIEncoding.ASCII.GetBytes(_PW));
result = sha.Hash;
for (int i = 0; i < result.Length; i++)
{
strBuilder.Append(result[i].ToString("x2"));
}
_HashedPW = strBuilder.ToString();
return _HashedPW;
}

in C#, what is the proper way to handle sensitive data such as a password?

This app displays a form with a textbox where the user is supposed to enter a password used to decrypt a document.
I have code that looks like this:
string password = passwordTextBox.Text;
...
DecryptDocument(password);
But I was told that, technically speaking, this is a security flaw, because the data that represents the password might remain in memory even after the application is closed.
I tried to use the System.Security.SecureString class but now I'm dealing with pointers to CoTaskMem which seems to make the problem worse:
SecureString password = new SecureString();
foreach(char i in passwordTextBox.Text.ToCharArray())
password.AppendChar(i);
IntPtr ptr = Marshal.SecureStringToCoTaskMemAnsi(password);
int length = password.Length;
byte[] bytes = new byte[length];
Marshal.Copy(ptr, bytes, 0, length);
DecryptDocument(Encoding.Default.GetString(bytes));
Marshal.FreeCoTaskMem(ptr);
As you can see, it doesn't look like I'm making the application safer, since sooner or later I will have to take the input (passwordTextBox.Text) and convert it into a string that I can pass to the DecryptDocument() function.
Is there a way to solve this problem or should I just deal with this security vulnerability?
If you really want to use SecureString, it needs to be used end-to-end, preferably only ever interacting one character at a time. Whenever the string is decrypted to a character array, you'll want to explicitly clear out the memory when you're done using it. Consequences of this:
You should use a secure TextBox control that operates with SecureString directly. See here for one good example.
You should modify DecryptDocument to take a SecureString directly.
You'll want to implement the decryption so that it spends as little time with decrypted characters as possible. Some of the crypto architecture in .NET actually supports SecureString directly. Failing that, your best bet is to use the unmanaged buffer and explicitly clear it out when you're done with it.

Rfc2898DeriveBytes + PBKDF2 + SecureString is it possible to use a secure string instead of a string?

I've a function GetPassword, that returns a SecureString type.
When I pass this secure string to Rfc2898DeriveBytes to generate a key, Visual Studio shows an error. My limited knowledge tells me that it is because Rfc2898DeriveBytes accepts only a string and not a secure string. Is there a workaround to this?
//read the password from terminal
Console.Write("Insert password");
securePwd = myCryptography.GetPassword();
//dont know why the salt is initialized like this
byte[] salt = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xF1, 0xF0, 0xEE, 0x21, 0x22, 0x45 };
try
{ //PBKDF2 standard
Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(securePwd, salt, iterationsPwd);
I found it interesting that the Rfc2898DeriveBytes class does not support a SecureString overload for passing the password used in deriving the key.
WPF allows for handling passwords as SecureString objects with the PasswordBox control. It seemed like such a waste that the added security that this control offers was lost due to the fact we could not pass in a SecureString to the constructor. However, erickson brought up the excellent point of using the byte[] instead of the string overload as it is relatively easier to properly manage the contents of a byte[] in memory than a string.
Using erickson's suggestion as inspiration I came up with the following wrapper which should allow for using the value of the password protected by SecureString with minimal exposure of the plaintext value in memory.
private byte[] DeriveKey(SecureString password, byte[] salt, int iterations, int keyByteLength)
{
IntPtr ptr = Marshal.SecureStringToBSTR(password);
byte[] passwordByteArray = null;
try
{
int length = Marshal.ReadInt32(ptr, -4);
passwordByteArray = new byte[length];
GCHandle handle = GCHandle.Alloc(passwordByteArray, GCHandleType.Pinned);
try
{
for (int i = 0; i < length; i++)
{
passwordByteArray[i] = Marshal.ReadByte(ptr, i);
}
using (var rfc2898 = new Rfc2898DeriveBytes(passwordByteArray, salt, iterations))
{
return rfc2898.GetBytes(keyByteLength);
}
}
finally
{
Array.Clear(passwordByteArray, 0, passwordByteArray.Length);
handle.Free();
}
}
finally
{
Marshal.ZeroFreeBSTR(ptr);
}
}
This approach leverages the fact that BSTR is a pointer pointing to the first character of the data string with a four byte length prefix.
Important points:
By wrapping Rfc2898DeriveBytes in a using statement it ensures that it is disposed in a deterministic manner. This is important as it has a internal HMACSHA1 object which is a KeyedHashAlgorithm and needs to have the copy of the key (password) it possesses to be zeroed out in the call to Dispose. See Reference Source for full details.
As soon as we are done with the BSTR we zero it out and free it via ZeroFreeBSTR.
Lastly, we zero out (clear) of our copy of the password.
Update: Added pinning of the byte[]. As discussed in the comments of this answer, if the byte[] is not pinned then the garbage collector could relocate the object during collection and we would be left with no way to zero out the original copy.
This should keep the plaintext password in memory for the shortest amount of time and not weaken the gains of using SecureString too much. Although, if the attacker has access to RAM you probably have bigger problems. Another point is that we can only only manage our own copies of the password, the API we are using could very well mismanage (not zero out/clear) their copies. To the best of my knowledge this is not the case with Rfc2898DeriveBytes, although their copy of the byte[] key (password) is not pinned and therefore traces of the array may hang around if it was moved in the heap before being zeroed out. The message here is that code can look secure, but problems may lie underneath.
If anyone finds any serious holes in this implementation, please let me know.
Apparently, you can violate the protection afforded by SecureString and expose its internal state via the Marshal.SecureStringToBSTR() function.
Rather than creating a String out of the result, copy the content to a Byte[] to pass to Rfc2898DeriveBytes. Creating a String would prevent you from destroying the password information, allowing it to hang out in the heap indefinitely, or get paged to disk, which in turn increases the chances that an attacker can find it. Instead, you should destroy the password as soon as you are finished using it, by filling the array with zeros. For the same reason, you should also assign a zero to each element of the BSTR as you copy it to the Byte[].
Salt should be randomly selected for each hashed password, not a fixed, predictable value, otherwise a pre-computed dictionary attack is possible. You should iterate many tens of thousands of times in order to prevent brute force attacks.
After doing some research and looking at previous answers on stackoverflow mentioning SecureString, that answer is almost certainly: "No". Only the creators of the API can accept SecureString and handle it correctly internally. And they can only do that with help of the platform.
If you - as a user - could retrieve the plain text String, you would have negated most of the advantages of using SecureString in the first place. It would even be a bit dangerous as you would create secure looking code, that would not actually be secure at all (edit: at least not when it comes to protecting in-memory data).
public static string GetSecureString(SecureString str) {
System.Net.NetworkCredential cred = new System.Net.NetworkCredential(null, str);
return cred.Password;
}

How to decode (shifting and xoring) a massive byte array in a fast way?

How to decode (shifting and xoring) a massive byte array in a fast way?
I need it for a file viewer application that opens the archive file and decodes the files inside and display them to the user. The files are encrypted with a byte shifting and xoring system. It is impossible for me to change the algorithm. Currently, I just read all the bytes and then run the Decode function on them.
The decode function that I currently use:
byte[] DecodeVOQ(byte[] EncodedBytes)
{
for (int i = 0; i < EncodedBytes.Length; i++)
{
EncodedBytes[i] ^= (byte)194;
EncodedBytes[i] = (byte)((EncodedBytes[i] << 4) | (EncodedBytes[i] >> 4));
}
return EncodedBytes;
}
Edit: I found out that the real performance problem is with displaying the text. Reading + Decoding is pretty fast.
One possible optimization would be to precompute the output for any input byte. So you'd have:
private static byte[] DecodedBytes = PrecomputeDecodedBytes();
public static byte[] DecodeVOQ(byte[] data)
{
for (int i = 0; i < data.Length; i++)
{
data[i] = DecodedBytes[data[i]];
}
return data;
}
It's quite possible that that will be slower than your existing bitshifting algorithm though. EDIT: I've just tried comparing this with the original bitshift but using a temporary local variable: they're about the same.
Have you benchmarked the current performance? Is it definitely too slow? In particular, loading the file from just about any storage medium will be much much slower than the cost of decoding. I've just tried this on my laptop - for 200MB of data, it takes about half a second. (EDIT: With Marcelo's answer, it takes under half a second.) Is that really too slow?
Would you be happy to use more than one processor? It's an embarrassingly parallelizable routine, after all. If you're using .NET 4, the TPL may well make this pretty simple.
I should emphasize again though that this isn't "encryption" - it's a mild form of obfuscation, in the same way that the base-64 encoding of a username/password for basic HTTP authentication is.
I'm thinking a table driven approach would be faster, right? Since it's just bytes, and no byte depends on an adjacent byte, there are only 256 possible choices, so just lookup each one
You might speed things up by using a temporary:
byte b = EncodedBytes[i] ^ (byte)194;
EncodedBytes[i] = (byte)((b << 4) | (b >> 4));
You might speed things up further by using unsafe and raw pointers, thus avoiding checked accesses (though I don't know if that's a consideration with current JIT optimisers).
One approach to consider is to decode the data just as it's being displayed. That is, only decode a portion at a time. But I suspect you are just dumping the data to an edit control or something, which would not really make that an option. How are you displaying the data?
Other than that, I'm not sure how you'd speed it up too much.
Without .NET you'd be able to decode that 4 bytes in a time, but here, actually, the only one thing you can do is to precompute translation table.
That's not xor, that's shift and or...
In assembly, that would be a single "rotate byte by 4" instruction.
BTW can't you decode it on demand? Decode the file in blocks, as you stream the file.

Categories

Resources