Ok, I have an application written in C#. We have data in an SQL Server. Among that data we have user accounts, which will give access to the application.
I've read around, and I know that you should salt and hash and possibly hash a bunch of times, etc. But, where do I do what? What do I send to and from the SQL Server? Exactly what do I store in the database? Do I hash it in SQL? (possibly a hash function there, like in mysql?) Do I hash and do the fancy stuff in my code? Do I send the hash to the server and compare, or do I get the hash from the server and compare in my application? What about the salt? Where do I make it? Where do I store it? How do I get it?
In other words, could someone give me a nice and clear walkthrough of a login scenario (and possibly a user add/reset password scenario). What goes where, what should be used where, etc.
Hope someone can clear these things up for me =)
I agree with Joel Coehoorn completely, the best choice is to trust someone else's tried and true implementation. If, however, you're determined to roll your own security implementation, then my advice is the following:
- Store the hash and salt in the database.
- Generate the hash and the salt in your own code. That way you're not tying yourself to a specific database.
- Never send the password over the wire as plaintext. I would recommend fetching the hash and the salt from the database and comparing it to the ones you calculated from the username and password supplied by the party that wishes to be authenticated.
For C# + SQL Server, you can just use the MembershipProvider model, which will take care of all this for you.
And IMO, the most important part of getting all this stuff right is not doing it yourself. Rather, rely on the mechanism provided by your platform. It's just so easy to get it wrong in a subtle way that appears to work. Then you deploy, and you don't even know anything is wrong until after you are hacked.
If you are using ASP.NET, using the built in membership stuff is a cakewalk to implement I would recommend going that way.
However, as a general question, I would implement the hashing in your local code, then only send the hash values out to the database. For salts there is a number of ways to do it, you can create a random salt, or you can salt the value using the records id, or something else. Again, I would do it in the C# code. There is a helpful method in the framework for doing it.
I did this myself a number of years ago before the Membership Provider model was available.
We used the functions built-into ASP.NET to handle the hashing of the password; it's the static method HashPasswordForStoringInConfigFile in the FormsAuthentication namespace. You give it a password and an encryption choice and it returns the hashed password.
Our flow was:
- Get the hashed password from the database for hte entered user name.
- Hash the entered password.
- Do they match? If so, continue, else logon failed.
When changing the password, we sent the hash to the database for storing; we did not send the unencrypted password.
And, I believe, it is what the MembershipProvider is doing under the covers today.
To reiterate too, the most important piece when doing forms authentication regardless of how you are doing it, is to work over a secure (HTTPS) connection.