I have the following code with private static members.
All of these classes say that they are thread safe in the MSDN library for “public static” members.
My question is whether these members will be thread safe when used as private static instead of “public static” as stated in the MSDN library.
public static class passwordManager
{
private static System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
private static System.Text.Encoding enc = System.Text.Encoding.ASCII;
public static string produceSalt(int size)
{
byte[] by = new byte[size];
lock (rand)
{
rand.GetBytes(by);
}
return enc.GetString(by, 0, by.Length);
}
public static string encryptPassword(string password, string salt){
return enc.GetString(shaM.ComputeHash(enc.GetBytes(password + salt)));
}
public static bool isCorrectPassword(string inputPassword, string DBsalt, string DBpassword)
{
return encryptPassword(inputPassword, DBsalt) == DBpassword;
}
This might be entirely dependent on whether the methods I am using themselves use shared variables instead of all method instance variables… some peace of mind would be helpful but I would rather not have to lock everything here if it isn’t necessary.
The only reason I locked the random number generator is to limit the possibility of getting the same salt however the chances of this being called by two threads at the same time is very low in my situation.
Thanks,
Mike
This should now be thread safe. I was trying to save on object instantiation overhead but I guess there is a trade off between this and lock waiting. On a high load system lock waiting would likely greatly overpower instantiation overhead and memory usage.
public static class passwordManager
{
private static System.Security.Cryptography.RandomNumberGenerator rand = new System.Security.Cryptography.RNGCryptoServiceProvider();
public static byte[] produceSalt(int size)
{
byte[] by = new byte[size];
lock (rand)
{
rand.GetBytes(by);
}
return by;
}
public static byte[] encryptPassword(string password, byte[] salt){
System.Security.Cryptography.SHA256 shaM = new System.Security.Cryptography.SHA256Managed();
System.Text.Encoding enc = new System.Text.UTF8Encoding();
return shaM.ComputeHash(concatArrays(enc.GetBytes(password), salt));
}
public static bool isCorrectPassword(string inputPassword, byte[] DBsalt, byte[] DBpassword)
{
return compare(encryptPassword(inputPassword, DBsalt), DBpassword);
}
}
Your code is not thread-safe.
Consider the
System.Text.Encodingvariableenc. You are callingGetStringwhich is an instance member. The documentation says that only public static members are thread-safe so by inferenceGetStringis not thread-safe because it is not a public static member.1This code may fail due to the following reasons:
Encoding.GetString.Encoding.GetStringis called from a public static method in yourpasswordManagerclass.The reason why public static methods are almost always designed to be thread-safe is because it would be awkward for the caller to always synchronize access to it. You cannot limit multithreaded access to static members like you can with instance members. Consider an ASP.NET application, for example. Web page requests are frequently handled concurrently on separate threads. Do you want to use a
lockeverytime you call a static method? Of course not. This is a ridiculous burden to place on a developer.Update:
Your new code is now thread-safe. You will have to do some benchmark tests to see which way is faster: using a
lockor instantiating new instances on every call like you have now. I would not be surprised if thelockwere faster.1The same could be said for
shaM.ComputeHashandenc.GetBytes.