Common Misunderstandings in C# and .NET – Inadequate Password Hashing

Let’s delve into a common security issue where developers neglect to hash user passwords correctly. It’s essential to grasp the importance of hashing. Imagine a user registers by entering their username and password. During this process, we save the username and password in plain text in our database. If the database gets hacked, the attacker can access Henry’s password and potentially steal his account. How can we address this problem? One solution is to use a hashing algorithm, a one-way function that converts the password into a different string. This transformation is nearly impossible to reverse, so even if a hacker obtains the hash, they can’t retrieve the original password, keeping the account secure.

However, using just a hashing algorithm isn’t enough. Hackers can use rainbow tables, which contain precomputed hashes, to look up hashed passwords and find the corresponding plain text values. To strengthen our hashing process, we can add a concept called “salt.”

Salt is a random value added during the hashing process. By incorporating salt, even if two users have identical passwords, their resulting hashes will be different. This renders rainbow tables ineffective. Additionally, we should make the hashing process intentionally slower to help protect against brute force attacks.

Let’s consider an example:

In this example, we show how to properly hash a password. At line nine, we prompt the user to enter a password via the Console, which could also come from a web application. We read the password and create a new Salt, represented as a 128-bit byte array. A secure Salt is generated using a random number generator that is more secure than the standard system generator.

For demonstration, we print the Salt to the Console after converting it to base 64. Next, we move on to the hashing process. As a precaution, I recommend checking if the username already exists before hashing to reduce the risk of denial-of-service attacks. We utilize a 256-bit subkey with the PBKDF2 algorithm and the HMAC SHA-256 hashing algorithm, passing the Salt and password as parameters. We also specify an iteration count to slow down the process and defend against brute force attacks. Finally, we convert the result to base 64 and store it in the hashed string, which we print to the console for illustration.

Typically, at this point, you would securely save both the Salt and the hashed password in the database.

Source: Nguyen Chi Hieu – Technical Manager