Hashing is a method of one-way encryption which is ideal for storing passwords in a database, as you may never require a decrypted version. To authenticate some data, simply hash what the user input and compare it with the data stored in the database.
A hash code will always be a small fixed size irrespective of the data length of the source. This makes hashing ideal for comparing files or identifying errors in a data stream (similar to a checksum). A single-bit alteration in any part of the source data will result in a very different hash code.
To hash in C#, call ComputeHash on a HashAlgorithm subclasses like SHA256 or MD5:
byte[] hash;
using (Stream fs = File.OpenRead ("checkme.doc"))
hash = MD5.Create().ComputeHash (fs); // hash is 16 bytes long
The ComputeHash method will also accept a byte array, and so is a convenient method for hashing passwords in C#:
byte[] data = System.Text.Encoding.UTF8.GetBytes ("stRhong%pword");
byte[] hash = SHA256.Create().ComputeHash (data);
Using the GetBytes method on an Encoding object will convert the string to a byte array; and the GetString method will convert it back again. However, the Encoding object is not able to convert an encrypted or hashed byte array to a string since the scrambled data will normally violate text encoding rules. Instead, you can use the below:
◦Convert.ToBase64String
◦Convert.FromBase64String
These will convert between byte arrays and legal strings. MD5 and SHA256 are two HashAlgorithm subtypes which are provided in .NET (and so available for your C# Hashing routines).
Below are listed all the primary algorithms, ordered in ascending security :
MD5(16) > SHA1(20) > SHA256(32) > SHA384(48) > SHA512(64)
Note that shorter algorithms will execute faster. MD5 will be over than 20 times quicker than SHA512 and is a good candidate for calculating file checksums. Hundreds of megabytes per second can be hashed with MD5 with results stored in a Guid – which is exactly 16 bytes long, and since it is a value type it will be more tractable than a byte array. A downside to shorter hashes is that they increase the probability of collision (ie two different files having the same hash).
You should use at least a SHA256 if you are hashing passwords or sensitive data. MD5 and SHA1 are normally considered insecure for this highly sensitive data such as passwords and are typically used only to protect against an accidental corruption, not deliberate data tampering.
SHA384 is not quicker than SHA512, therefore if you are looking for greater security than SHA256, there is little downside to using SHA512.
Longer SHA algorithms are very suited to password hashing, but note that they will require enforcement of a strong password policy to protect against a dictionary attack (where the attacker simply attempts to guess the password by hashing every word/combination in a dictionary). You can protect against this by “stretching” the password hashes— which involves repeatedly rehashing the password to get more computationally intensive byte sequence. After rehashing 100 times, a dictionary attack which could normally take 1 month would take over 8 years. For this exact purpose Rfc2898DeriveBytes and PasswordDerive Bytes classes will perform the rehashing the required number of times.
Another method of avoiding a dictionary attack is to incorporate a “salt” (which is long series of bytes which are obtained using a random number generator then is combined with every password prior to hashing. .NET also includes a 160-bit RIPEMD hashing algorithm, which is slightly more secure than SHA1, however in most circumstances this should be avoided since is has not been efficiently implemented in .NET and is actually slower to execute than even SHA512.