In modern application development, it is a cardinal sin to ever store a user's password in plain text. Stored in plain text, a user's password is available to anyone from hackers sniffing network traffic to internal, disgruntled employees. Once these bad folks have clear text passwords they can easily get into associated accounts.
Modern applications today need to use cryptographically secure hashed passwords. Let's take a look at the abstract definition of how this works, then we'll look at the very few lines of AVR for .NET code required to implement it (thanks to the .NET Framework).
How password hashing works
There are many hashing algorithms. We first consider SHA-256 hashing. This algorithm returns a 64-character hash of the input. This online SHA-256 hash generator shows that when you hash 'apple' you get the value:
The password is never stored for later comparison. The hashed password is stored. Hashes aren't encryption; a hashed value cannot be decoded back to its original value. In password hashing, a password is hashed twice. Once when it is stored and then again when the password is validated. Upon sign in, the user provides her
apple password and its hash is compared to the stored hash. If they match, the user is authenticated.
One way for a hacker to defeat simple hashing like above is with a dictionary attack. Imagine that a large security breach surfaced many user IDs and passwords. Armed with a long list of words (including typical passwords like
qwerty) the hacker compares the hashed value of each word against the pirated hashes. When a match is found, the hacker just got in. If your faith in mankind keeps you from thinking anyone could be this evil, download word lists for this purpose here.)
One interesting aspect of hashing is that while any one algorithm creates a fix-length hash (SHA-256 creates a 64 character hash), the input length is, for all intents and purposes, unlimited. The value below is the SHA-256 hash of the lyrics to Neil Young's Keep on Rocking in the Free World. Crazy, huh?
A pinch of salt
The need to minimize the success of dictionary attacks lead to the concept of adding a salt value to the password to help defeat dictionary attacks . A salt value is a random value added to the password before it is hashed. (Why do they call it a salt?.) For example, let's say we appended
adDl[!4&T to the word
apple before hashing it. As validation time, we also append that value before hashing it. It's unlikely the hacker's word list has any words that start with
adDl[!4&T in it, but a big enough list could.
A better algorithm
The need for highly secure passwords lead to the development of better hashing techniques over the last several years. These algorithms are considered cryptographically secure because they meet standards that make them much harder to guess. It is very strongly recommended now that you use an algorithm using either the PBKDF2 and or bcrypt algorithm to hash passwords. Unlike SHA-based (and other) algorithm these newer algorithms do not repeat hash values for an input. This online brcrypt hasher generator created the two different hashes for the world
Using the algorithm's validation feature shows that both match the word
Although SHA-256 hashing isn't up to snuff for modern password management, there are many places where using it is still appropriate. Git, the open-source source control utility, uses SHA-based hashes as content identifiers to track source changes. Git is currently in the process of moving from the very old SHA-1 standard to SHA-256.
Password hashing with AVR for .NET
Given that quick intro into password hashing, let's turn our attention to password hashing with AVR for .NET.
FormsAuthentication class in the Microsoft
System.Web.Security namespace has a method named
HashPasswordForStoringInConfigFile that creates hashed passwords. However, that method has since been marked obsolete and it is highly recommended that you not use it. It is not PBKDF2-compliant and does not generate a cryptographically secure password.
If you are using
HashPasswordForStoringInConfigFileconsider swapping it out soon for the method discussed below. Doing so requires all users to change their passwords.
Microsoft's current recommendation solution for created hashed passwords is to use its Membership framework. However, that framework is SQL Server-specific and to use it with another other database or data store you need to subclass it and implement its methods. This isn't a trivial task.
However, there is a poorly documented escape hatch. Microsoft has a class library (a DLL) named
System.Web.Helpers.Crypto available on Nuget that offers a class with the PBKDF2-compliant cryptographically secure methods we need. These methods also automatically generate a random salt value. AVR doesn't work well with some Nuget packages so here is the best way to get the DLL you need:
Go to this Nuget link and click the "Download package" link. This puts a file named "system.web.helpers.crypto.3.2.3.nupkg" on your system.
A Nuget file is really a zipped file. Use an unzip utility to unzip it (you may need to rename it with a
.zipextension). After unzipping, a file named
Set a reference that file in your AVR project and then you're ready to use the code below.
This four-minute video shows the process above in action.
Just a dash of code
Creating a cryptographically secure hashed password with AVR for .NET requires just one line of code with the library we downloaded from Nuget:
HashedPassword = System.Web.Helpers.Crypto.HashPassword(Password)
The value returned from the
HashPassword method is a 68-character string. This is the value that needs to be stored in the user's row in your authentication row. While its length is 68 characters, consider making your password column much longer (maybe 255 characters) so that in the future if the algorithm gets updated you won't need to change your database.
Authenticating the hashed password also requires just line line of code. The chunk of code below assumes you've read the user's authentication row with the user id and put the hashed password in the
If System.Web.Helpers.Crypto.VerifyHashedPassword(HashedPassword, Password)) // User authenticated Else // User not authenticated EndIf
If you're rolled your own password mechanism, or if you're using the deprecated
HashPasswordForStoringInConfigFile method, consider moving to the secure methods provided by Microsoft with its crypto library.
Remember, too, that no matter how you are storing passwords, Networked applications, especially Internet applications, should always use HTTPS/TSL (SSL). Otherwise user passwords are passed as clear text and can be intercepted.