14.2 Calculate the Hash Code of a Password


Problem

You need to store a user's password securely so that you can use it to authenticate the user in the future.

Solution

Do not store the user's plaintext password; storing plaintext passwords is a major security risk and one that most users would not appreciate given that many of them will use the same password to access multiple systems. Instead, create and store a cryptographic hash code of the password using a hashing algorithm class derived from the System.Security.Cryptography.HashAlgorithm class. On future authentication attempts, generate the hash of the provided password and compare it to the stored hash code.

Discussion

Hashing algorithms are one-way cryptographic functions that take plaintext of variable length and generate a fixed- size numeric value. They are one-way because it's nearly impossible to derive the original plaintext from the hash code. Hashing algorithms are deterministic; applying the same hashing algorithm to a specific piece of plaintext always generates the same hash code. This makes hash codes useful for determining if two blocks of plaintext (passwords in this case) are the same. The design of hashing algorithms ensures that ” although not impossible ”the chance of two different pieces of plaintext generating the same hash code is extremely small. In addition, there is no correlation between the similarity of two pieces of plaintext and their hash codes; minor differences in the plaintext cause significant differences in the resulting hash codes.

When using passwords to authenticate a user, you aren't concerned with the content of the password that the user enters. You need only to know that the entered password matches the password that you have recorded for that user in your accounts database. The nature of hashing algorithms makes them ideal for storing passwords securely. When the user provides a new password, you must create the hash code of the password and store it, and then discard the clear text password. Each time the user tries to authenticate with your application, calculate the hash code of the password he or she provides and compare it with the hash code you have stored.

Note  

People regularly ask how to obtain a password from a hash code. The simple answer is that you can't. The whole purpose of a hash code is to act as a token that you can freely store without creating security holes. If a user forgets a password, you can't derive it from the stored hash code; you must either reset the account to some default value, or generate a new password for the user.

Generating hash codes is quick and simple in the .NET Framework. The abstract class HashAlgorithm provides a base from which all concrete hashing algorithm implementations should derive. The .NET Framework class library includes the six hashing algorithm implementations listed in Table 14.1; each implementation class is a member of the System.Security.Cryptography namespace. The classes with names ending in CryptoServiceProvider wrap functionality provided by the native Win32 CryptoAPI, whereas those with names ending in Managed are fully implemented in managed code.

Table 14.1: Hashing Algorithm Implementations

Algorithm Name

Class Name

Hash Code Size (in Bits)

MD5

MD5CryptoServiceProvider

128

SHA or SHA1

SHA1CryptoServiceProvider

160

SHA1Managed

SHA1Managed

160

SHA256 or SHA-256

SHA256Managed

256

SHA384 or SHA-384

SHA384Managed

384

SHA512 or SHA-512

SHA512Managed

512

Although you can create instances of the hashing algorithm classes directly, the HashAlgorithm base class is a factory for the concrete implementation classes that derive from it. Calling the static method HashAlgorithm.Create and passing the algorithm name as an argument will return an object of the specified type. Using the factory approach allows you to write generic code that can work with any hashing algorithm implementation.

Once you have a HashAlgorithm object, its ComputeHash method accepts a byte array argument containing plaintext and returns a new byte array containing the generated hash code. Table 14.1 shows the size of hash code (in bits) generated by each hashing algorithm class.

The HashPasswordExample class shown here demonstrates the creation of a hash code from a string, such as a password. The application expects two command-line arguments: the name of the hashing algorithm to use and the string from which to generate the hash. Because the HashAlgorithm.ComputeHash method requires a byte array, you must first byte encode the input string using the class System.Text.Encoding , which provides mechanisms for converting strings to and from various character encoding formats.

 using System; using System.Text; using System.Security.Cryptography; public class HashPasswordExample {          public static void Main(string[] args) {         // Create a HashAlgorithm of the type specified by the first         // command line argument.         using (HashAlgorithm hashAlg = HashAlgorithm.Create(args[0])) {             // Convert the password string, provided as the second command             // line argument, to an array of bytes.             byte[] pwordData = Encoding.Default.GetBytes(args[1]);                  // Generate the hash code of the password.             byte[] hash = hashAlg.ComputeHash(pwordData);                  // Display the hash code of the password to the console.             Console.WriteLine(BitConverter.ToString(hash));         }     } } 

Running the command HashPasswordExample SHA1 ThisIsMyPassword will display the following hash code to the console:

 80-36-31-2F-EA-D9-93-45-79-34-C9-FD-21-EE-8D-05-16-DC-A1-E2 



C# Programmer[ap]s Cookbook
C# Programmer[ap]s Cookbook
ISBN: 735619301
EAN: N/A
Year: 2006
Pages: 266

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net