Software Development

Protect sensitive data with hashing in .NET

The .NET Framework includes everything necessary to protect your sensitive data, with one of the more popular techniques being hashing. Hashing provides a simple method of scrambling data values that may be easily stored in a database and re-created using the original hash algorithm.

Due to the increasing number of security threats, cryptography is a must for most application development projects. Cryptography basically takes meaningful data and transforms it into data stripped of meaning.

The .NET Framework includes everything necessary to protect your sensitive data, with one of the more popular techniques being hashing.

Reworking data

Data can be as small as a database connection string and as large as a DataSet containing thousands of database records. For this reason, there are numerous approaches to protecting your data. The most basic process is called hashing.

Hash values are a cryptographically secure way to refer to basic text values. A secure hash algorithm is designed so that it's computationally infeasible to construct identical hash values accidentally or maliciously.

The .NET Framework supports the following hash algorithms:

  • MD5 is an algorithm that takes as input a message of arbitrary length and produces as output a digested or encrypted version of the input that uses 128-bits.
  • SHA1 is the Secure Hash Algorithm (SHA) that uses 196 bits to encrypt the data.
  • SHA256 is the SHA that uses 256 bits to encrypt the data.
  • SHA384 is the SHA that uses 384 bits to encrypt the data.
  • SHA512 is the SHA that uses 512 bits to encrypt the data.

The supported algorithms range from 128 to 512 bits. The more bits utilized results in more security; however, conversely, more bits also degrade performance.

With this information, you may decide that SHA512 is best because it uses the most bits. The ultimate decision depends upon the particular situation.

Cryptography and .NET

The .NET Framework provides hashing functionality through the System.Security.Cryptography namespace. It provides access to various classes for utilizing the various hashing algorithms. Here is a sampling of these classes:

  • CryptographicException throws an exception when an error occurs during a cryptographic operation.
  • MD5CryptoServiceProvider computes the MD5 hash for the input data using the implementation provided by the cryptographic service provider (CSP).
  • SHA1CryptoServiceProvider computes the SHA1 hash for the input data using the implementation provided by the CSP.
  • SHA256Managed computes the SHA256 hash for the input data.
  • SHA512Managed computes the SHA512 hash for the input data.

You can refer to the Microsoft documentation for more details on the System.Security.Cryptography namespace. Now let's take a closer look at using these classes to implement hashing.

A hashing example

The hashing process is simple. First, a crypto service object is created. Then, a byte array is passed to the crypto service object's ComputeHash method. This returns an array of bytes that contained the encrypted version of the data. At this point, you must convert the byte array to a string value if it must be stored or displayed. The following example shows these steps:

string test = "Builder.com";
byte[] result = new byte[test.Length];
try  {
SHA1 sha = new SHA1CryptoServiceProvider();
result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(test));
Console.WriteLine(Convert.ToBase64String(result));
} catch (CryptographicException ce) {
Console.WriteLine("Error: " + ce.Message);
}

The code utilizes the SHA1 algorithm to encode the string. The result is written to the standard output. Notice that the encoded result is contained in a byte array, so it must be converted to a string to properly display. Also, the cryptography-related code is enclosed in a try/catch block to catch unexpected problems.

A common application of hashing is storing simple data such as passwords or, possibly, connection strings. Storing a password is simple. The encoded value is stored (in its string form). The next time the user logs on, her password is hashed using the same algorithm, and the result is compared to the stored value.

Enhance the hash with salt

One of the caveats of hashing is that identical input values produce identical encoded values. That is, two users with the same password will have the same encoded string stored for their password. If a hacker views the data, they may notice trends and possibly crack the values.

Adding salt values to the hashing algorithm solves this problem. A salt is random bytes added to the input value before the algorithm is applied. A salt value may be a random value generated by the system or an arbitrary value like an employee number.

The RNGCryptoServiceProvider class implements a cryptographic, random-number generator using the implementation provided by the cryptographic service provider. It may be easily used to add salt to the previous code sample:

string test = "Builder.com";
byte[] salt = new byte[8];
string intermediate = null;
try {
SHA1 sha = new SHA1CryptoServiceProvider();
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(salt);
intermediate = Convert.ToBase64String(salt) + test;
byte[] result = new byte[intermediate.Length];
result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(intermediate));
Console.WriteLine(Convert.ToBase64String(result));
} catch (CryptographicException ce) {
Console.WriteLine("Error: " + ce.Message);
}

Here's the same code in VB.NET:

Dim test As String = "Builder.com"
Dim result As Byte()
Dim salt(8) As Byte
Dim intermediate As String
Try
Dim sha As SHA1
sha = New SHA1CryptoServiceProvider
Dim rng As RNGCryptoServiceProvider
rng = New RNGCryptoServiceProvider
rng.GetBytes(salt)
intermediate = Convert.ToBase64String(salt) + test
result = sha.ComputeHash(System.Text.Encoding.UTF8.GetBytes(intermediate))
Console.WriteLine(Convert.ToBase64String(result))
Catch ce As CryptographicException
Console.WriteLine(ce.Message)
End Try

The code varies from the first example when it adds the salt value to the beginning of the value to encode. Once the two strings are concatenated, the hash process begins. This allows unique salt values to be applied to individual users—attempting to thwart hack attempts. It does combat a dictionary attack, which is when the attacker tries to decrypt an encrypted message by comparing the encrypted value with previously computed encrypted values for the most likely keys.

One approach to cryptography

Protecting sensitive data is imperative in today's world, where everyone seems to be connected to the Internet. Hashing is just one approach that provides a simple method of scrambling data values that may be easily stored in a database and re-created using the original hash algorithm.

TechRepublic's free .NET newsletter, delivered each Wednesday, contains useful tips and coding examples on topics such as Web services, ASP.NET, ADO.NET, and Visual Studio .NET. Automatically sign up today!

About

Tony Patton has worn many hats over his 15+ years in the IT industry while witnessing many technologies come and go. He currently focuses on .NET and Web Development while trying to grasp the many facets of supporting such technologies in a productio...

1 comments
abdullah.adam
abdullah.adam

Excellent article and quite helpful. Thank you. However, you better store that salt somewhere otherwise you won't be able to verify your data against the hash! Maybe this needs a follow up article on verifying against a hash with a salt.

Editor's Picks