Salting the Password in C#

dotnetlogo
Hashed passwords provide much better security than storing passwords in the database as simple text. They are, however, potentially vulnerable to a dictionary attack. In a dictionary attack, the attacker attempts to guess passwords by using software to iteratively hash all words in a large dictionary and compare the generated hashes to the stored hash values.

You can help prevent dictionary attacks by requiring the end users to define passwords that are not common words and that contain some numbers or other nonalphanumeric characters.

In addition, you can add a random set of bytes at the beginning or end of the password before hashing it. This random set of bytes is called a salt. You then store this salt value in the table along with the password.

There are many ways to generate a salt value. One way is to generate a globally unique ID, or GUID, as follows.

public static String ComputeSalt()
{
System.Guid GuidValue = System.Guid.NewGuid();
return GuidValue.ToString();
}

This code can also be included in your utility component so it can be reused.

By using both the hash and the salt, you can minimize the possibility of an unauthorized user accessing your application.

Hashing the Password in C#

dotnetlogo

Every application uses username and password to provide security to the systems. The way an application handles the storage of password defines the level of security provided by the application.

The password should not be stored in the database as a string. Rather, it should be converted to an unrecognizable value that is unique for any defined password. This value is called a hash. Hashing algorithms are defined so that any string that is hashed to a unique value will always be hashed to that unique value.

When an end user defines a password, the password should be hashed to a unique value, and that unique value should be stored in the database. When the end user logs in with the password, the password can be hashed again using the same algorithm. The resulting value can be compared with the hashed value stored in the database to validate the login.

Hashed values cannot be “unhashed,” so there is no way to get the original password back from the hashed value. This provides an additional level of security, because if someone obtains hashed passwords from the database, they cannot be converted back to the original passwords. A side effect of this is that if an end user forgets the password, a new password would need to be assigned.

The System.Security.Cryptography library in the .NET Framework provides a set of classes that assist with hashing. Two primary hashing schemes are provided in this library:

  • MD5: The Message Digest 5 (MD5) hash digest uses an MD5 algorithm to hash a value, such as an end user password. This algorithm provides better performance than SHA1.
  • SHA1: The Secure Hash Algorithm-1 (SHA1) hash digest uses a SHA1 algorithm to hash a value, such as an end user password. This algorithm provides better security than MD5.

A password such as “password” will have a hash that looks something like W6ph5Mm5Pz8GgiULbPgzG37mj9g=.

The following code uses the SHA1 algorithm to hash a password:

using System.Security.Cryptography;
public static String ComputeHash(string textToHash)
{
SHA1CryptoServiceProvider SHA1 = new SHA1CryptoServiceProvider();
byte[] byteValue = System.Text.Encoding.UTF8.GetBytes(textToHash);
byte[] byteHash = SHA1.ComputeHash(byteValue);
SHA1.Clear();
return Convert.ToBase64String(byteHash);
}

You can put this code in a utility component and reuse it in every application that needs to store a password or other secure information.

But hashing a password does not protect the application from a dictionary attack. For further security, salt the password as well.

Obsolescing Your Code in C#

dotnetlogo
One feature of refactoring that is available in .NET now is the ability to obsolete your properties or methods. Say you have a method (or other member) in your application that is no longer needed or whose signature needs to be changed. You could delete or change the method, and then find and modify all of the code that uses the method. But a better approach is to mark the method as obsolete, basically declaring it to be deprecated. By marking a method as obsolete, instead of deleting or changing it, you avoid needing to modify any of the code that uses the method.

Code that uses the obsolete method will get a warning or a syntax error (depending on how you obsolete the method) the next time that code is compiled. This allows you to define a logical obsolescence path for your code. For example, when building components for a team of developers, your standards may require that you obsolete a method for six months with a warning and another six months with a syntax error, before the method is actually removed from the code.

To mark a routine as obsolete, use the ObsoleteAttribute.

[ObsoleteAttribute(“This method is obsolete. Please use Retrieve(iID) instead”,
false)]
public DataSet Retrieve(string sProduct)
{
// Code here performs the retrieve
}

The first parameter of the ObsoleteAttribute is the message text that the developer will see wherever the obsolete method is used. This message text will appear in the Task List window in Visual Studio.

The second parameter of the ObsoleteAttribute is whether the obsolete member usage is considered to be an error. Set the parameter to False to specify that the developer using the method will get a warning message in the Task List window, or to True to generate a syntax error if the method is used.