The Graffiti Beta has expired. Please visit http://Graffiti.com and for an upgrade.

Hashing For Passwords

David Woods

Thursday, January 24 2008         No Comments

As mentioned in "Hashing - The Basics" I felt that a separate post on hashing for passwords was required.

Principal

The principal of storing hashed passwords is fairly simple and can be described in these steps:

  1. When an account is created the plain text password is entered
  2. The password is run through a hashing algorithm
  3. The output of the hash is stored

 

  1. When the user logs in they enter their plain text password again
  2. The password is run through the hashing algorithm
  3. The hash just generated is checked against the stored one. If the two match then the user has entered the same password as the account was created with

Salting

One of the most important techniques with hashing is salting. Salting is the process of injecting random data into a string before it is hashed. There are a few reasons for this.

  1. Collision avoidance. If two users have the same password they will have the same hash in the database. This means if we crack one password then we have easily cracked the other.
  2. Additional complexity. By adding good random data into a string we can no longer brute force a hash. So we could try a brute force and easily get "mypass" as the password or by using salting we would have to brute force mypass#$^q∩gwjoεai←cyuw3b5asdφ♂

One of the things here to note is to add good random data. Math.Random() does not supply strong random numbers. Instead use the RNGCryptoServiceProvider instead.

public static string GenerateSalt(int sizeInBits)
{
    RNGCryptoServiceProvider provider = new RNGCryptoServiceProvider();
    byte[] salt = new byte[size/8];
    provider.GetBytes(salt);
    return Convert.ToBase64String(salt);
}

By adding salting techniques makes the account creating steps a little more involved. The reason for this is when the user logs in we need the original salt data that the hash was created with. Normally we store this along with our data but there are some other techniques.

Here are the steps again with salting involved:

  1. When an account is created the plain text password is entered
  2. A random salt is generated and appended onto the password (i.e. "mypass" + "#$^q∩gwjoεai←cyuw3b5asdφ♂")
  3. The password+salt is run through a hashing algorithm
  4. The output of the hash is stored
  5. The salt used is also stored

 

  1. When the user logs in they enter their plain text password again
  2. The salt is loaded
  3. The plain text password + salt is run through the hashing algorithm
  4. The hash just generated is checked against the stored one. If the two match then the user has entered the same password as the account was created with.

Now it does not always have to be 'password' + 'salt' we could reverse it to be 'salt' + 'password' or even 'salt' + 'password' + 'salt'. As long as the way we create the hash is the same procedure we use to check the hash then the possibilities are endless. In fact as I write this I would say that 'password' + 'salt' is the common pattern that to add more security to your hashes mix the salt in differently (i.e. the 'salt' + 'password' + 'salt')

IMPORTANT: Do not use the same salt for each record. Having random data thrown in to each unique record will make each record harder to crack. I will discuss this idea a bit more in my next post on attacking hashed passwords.

Drawbacks

Hashing passwords does have its drawbacks like anything else:

1. Passwords can not be retrieved for a user. This is because hashes are just a fingerprint of the data; they never actually contain the password inside of them. The way to get around this is to have the ability to reset a users password (i.e. generate a new hash/salt and overwrite it in the database)

2. Creation / Login disparities. I had an issue once where when the account was created the password did not get whitespace trimmed off of it. I created an account with a password of "blah " but the user could not login with "blah" because "blah" and "blah " result in two totally different hashes. This took quite a while to debug.

3. Database/Code truncation. It is easy to spot that a users password exceeds the size of a database column as it would look like this "HelloMyNameIsSi" but a truncated hash would look like "A56FY#SDFH^(EU". These are hard issues to spot and debug sometimes

4. Performance. The performance impact is not that large but it is still higher than a plain text login system. I would never sacrifice security for performance myself and there are usually better places to improve performance of a system.

Call For Videographers

Nolan Zak

Monday, January 21 2008         No Comments

This is a call for any videographers out there. If you have your own video equipment (digital camcorder etc) and feel like helping us out on Saturday, please get in touch. We're hoping you can bring your equipment to the code camp and record some of the sessions.

We want to use the recordings to provide people who attended with recorded content from the day, as well as use it to promote future events. There may even be a chance to have the sessions posted on some Microsoft web sites.

Let me know if you are interested in doing some recordings. You can even just record the sessions you are planning to attend, no need to miss anything you don't want to miss. If you don't have any recording equipment or don't want to record anything, feel free to ignore this message. :)

Hashing - The Basics

David Woods

Saturday, January 19 2008         No Comments

Hashing has been a long used technique to store and validate information. Hashing is the function of applying a translation to a string to generate a unique (and replicable) fingerprint of the data (often referred to as a checksum).

String Hash
Hello World b10a8db164e0754105b7a99be72e3fe5
Hello Worlds 9f0d0cd67d27414d0ae8f5eca41a1a36

As you can see, even a minor change to the string results in a completely different hash. This is why hashes are often used to verify that data has been unmodified. Another great feature of hashes is that they are just a fingerprint of the data. There is no way to reconstitute the original data from a hash*.

Hashing for Verifying the Authenticity of Data

hashing

As you can see in the document the author generates an SHA512 hash of his/her document and places that document on the Internet. The client then downloads the document and runs it through the same algorithm on their own. If the hash we generate matches the authors then the document has been unmodified. If the hashes don't match then the document may have been tampered with and should not be trusted.

Storing the hash right next to the document really defeats the purpose. If an attacker gained access to the document, that attacker could then modify the document, generate a new hash for the modified document and overwrite the original. From a client point of view there is a document and a hash that work out. So it passes the verification. This is why it is really important to store the hash separately from the data you are trying to authenticate. Optimally the hash should be stored with a third party or be given out upon request directly from the author.

Hashing for Passwords

The most common way operating systems store passwords is in a hashed format. I actually don't know of a modern operating system that does not do this. The premise is quite simple. When your account is created your password is hashed and stored on the disk. When you login, you type in your password which then gets hashed. The operating system compares the hash it just generated (based on you entering your password into the login screen) with the hash it has on disk. If the two hashes match then you entered the same password your account was created with and so you are successfully logged in. If properly implemented this is a great way to authenticate users without having to ever store their passwords (I think properly implementing this is a post to itself).

Algorithms

For us in the .NET world there are 5 hashing functions available to us:

Acronym Name Output Size (bit) Recommended
MD5 Message-Digest algorithm 5 128 No (collision can be created in less than one minute on a standard computer)
SHA1 Secure Hash Algorithm 160 No (collisions are possible to create but much harder than MD5)
SHA256 Secure Hash Algorithm 256 Yes
SHA384 Secure Hash Algorithm 384 Yes
SHA512 Secure Hash Algorithm 512 Yes

 

The SHA256-SHA512 are often referred to as SHA2 and are the preferred choice currently. The main reason for this is the lack of collisions which have been created on the MD5, SHA0, and SHA1 protocols. The SHA2 protocols are relatively new but have not been shown to have collisions (yet).

Collisions

A hash collision occurs when two different values produce the same hash. In theory this could mean that two totally different documents could yield the same hash. Worse yet that two separate passwords could yield the same hash. This would reduce the time taken to brute force a system as it would be possible to enter a password that collides against a hashed password in the system thus reducing the number of guesses required to force our way into a system. The use of salting is a great way to help protect against this (more on this later) but I prefer to use a stronger algorithm (and salting) when designing a system.

Code

The code is actually quite simple. All you have to do is convert your input data to a byte array and run it through one of the classes that derives from HashAlgorithm (MD5, SHA1, SHA256Managed, SHA384Managed, or SHA512Managed) and call the ComputeHash method on it. Here is a quick sample using the SHA512 Managed class:

public string CreateHash(string input)
{
       HashAlgorithm sha = new SHA512Managed();
       byte[] inputData = Convert.FromBase64String(input);
       byte[] hashedBytes = sha.ComputeHash(inputData);
       return Convert.ToBase64String(hashedBytes);
}

 

That is the basics of hashing. Next up I will write some posts on properly implementing hashing and salting for password systems.

 

 

*Well besides brute forcing the hash. This is done by throwing data at the hash function until the same hash is generate as the one you are trying to get. If the hashes match then you probably (see collisions) have the original data.

Quick schedule update

Nolan Zak

Sunday, January 13 2008         No Comments

Donabel is coming over from Vancouver for the day, so she requested that her sessions be moved to later in the day. After this update the Sharepoint sessions are after lunch, and the Amazon session gets moved to the first slot of the day.

As always the current schedule can be found here:
http://www.victoriacodecamp.com/SessionSchedule.aspx

Don't forget about the printer-friendly versions of the schedule too. You can print a copy of the schedule that contains all of the sessions and their descriptions here: 
http://www.victoriacodecamp.com/SessionSchedulePrint.aspx

question about 'tracks'

Nolan Zak

Tuesday, January 08 2008         No Comments

Got a great question so I wanted to post an answer to the group:

I have a question about the session schedule and the notion of "Track 1, Track 2, Track 3".  I have not attended a Code Camp before, but I am considering attending this years.  However I have looked at the three Tracks and none of the three have all the sessions that interest me.  I primarily do windows application (client) development, so I am less interested in ASP development.  Do we need to pick one of the three "Tracks" and attend all of the sessions (and only those sessions)?  Or are we free to attend any of the three sessions that are going on at a given time (regardless of the track they are in)?

I just thought it was odd to see Client and Web Application sessions mixed together in the same track.  I would have expected more of a "Client" track, "Web" track and a "hybrid" track if we are required to attend only sessions in the chosen track.



And here's my answer:

That's a really good question. Rather than "Tracks", it's probably more accurate to say "Rooms". Each "Track" is held in a different room. The only restriction to moving from track to track is having to get up and change to a different room. :)

We tried really hard to make sure that sessions with competing content were not held in the same time slot. For example, a web-focused session and a windows forms session are at the same time because it's more likely that people will be interested in one or the other, but not both. Of course that's not true for some people, but we do the best we can. And we're always open to suggestions.



I'll update the FAQ with this answer too.

Registration Is Open

Nolan Zak

Sunday, January 06 2008         No Comments

The registration page on the web site is now open and accepting registrations for the code camp. The official announcement will be tomorrow morning via both web sites and the .NET Dev Association email list.

Code Camp Hotel Discount

Nolan Zak

Thursday, January 03 2008         No Comments

If you're coming from out of town for the Code Camp, this could save you some cash.

We have negotiated an excellent group rate with a great hotel in downtown Victoria. I don't want to post the details publicly though, so if you're coming from out of town and want a nice place to stay at a good price ($99/night) please either leave a comment here with your contact details, or email me (info **at** vicdotnet **dot** org) for more info.

Speaker Update

Nolan Zak

Thursday, January 03 2008         No Comments

Due to personal reasons, Darcy Lussier from Winnipeg is no longer able to make it to the code camp. This causes us both a loss and a gain. It's a loss because we no longer have the Mad Mexican in the house, but it's a gain because we bump Scott Stauffer from the Vancouver SQL Server community into Darcy's slot and add some SQL Server 2008 discussion into the mix.

Scott will be talking about the new development features in SQL Server 2008 as well as some handy tips and tricks he's learned from playing around with the beta releases. As a former SQL junkie myself I'm really looking forward to seeing what's coming down the pipe from the SQL folks this year. Welcome Scott!

What's New in Visual Basic 9?

Beth Massi

Thursday, January 03 2008         1 Comment

This is going to be a GREAT code camp! I did the same sessions at DevTeach in Vancouver in November and we had a lot of fun. Check out my posts here and here.

What can I say about VB 9 -- it's AWESOME! This language has really come a long way. There are so many language enhancements this version that I don't know where to start. I plan on talking about LINQ and as we write a variety of queries I'll show how the new language features tie into them to make them work. I'll also be showing the new XML features that are very specific to Visual Basic  like XML Literals, Embedded Expressions and Axis Properties that make querying, transforming, and creating XML a total breeze. If you're using any language to manipulate and work with XML then you'll want to have a look at VB 9. There's a good set of How-To's on the VB Developer Center under the Video Tutorials page to help you get started.

I'll also be doing a session totally dedicated to XML in VB 9. I'll start with the basics there and then move deeper into the LINQ to XML API and show a bunch of examples using XML Literals and VB's unique, easy-to-use, LINQ syntax. Some of the examples I'll show I've blogged about like the Word Mail Merge example, an Excel import/export example, an RSS Viewer and we'll have some fun mapping customers in Northwind using Virtual Earth.

I'm looking forward to this event. See you there!

Enjoy,
-Beth Massi, Visual Studio Community

 

FAQ listing

Nolan Zak

Thursday, January 03 2008         No Comments

I just finished updating the FAQ page on site (http://victoriacodecamp.com/FAQ.aspx), but the original content was written 3 years ago for the first code camp. Is there anything we're missing?