Oct 04 2006

Storing passwords in your ASP.NET application - part 1

Posted by admin under ASP.NET articles

This guide will show you how to store your user passwords in an ASP.NET - or Windows Forms - application. Or rather - it will show you the secret is to NOT store the actual password. I'll explain later, don't worry. 

There is always a risk of someone getting their hands of sensitive information - and user accounts and passwords sure counts as sensitive data, don't you think? Let's investigate what we can do to make it harder for an intruder to get their hands of such things.

Textfile or database?

If I encrypt the passwords will storing them in a textfile be enough?

Well, I can't say where to put your bars, but storing them in a database sure gives you another layer of protection. In a web solution, if someone gained access to your webserver and there was a textfile called accounts.xml it would be dead easy to just copy the file to another box and start cracking it. If the information is stored in a database - maybe on another server, you would get a little more security. However - please note that often the connection strings are stored in clear text in a web.config file - and it would then be easy to just look into that file to gain access to the correct database and server - still - a database storing solution would take a little more time to crack - and the fact is that no security solution is possible to protect you 100% - what you can do is add levels making it harder for an intruder - and therefore you might get time to act.

So, a database it is - fine. Now - lets say I have a database table looking like this:

CREATE TABLE [dbo].[user_cleartext] (
 [loginid] [varchar] (50) NOT NULL ,
 [pwd] [varchar] (50) NOT NULL
) ON [PRIMARY]
GO

And I store passwords in this table. How can we make that harder to crack? Now "all" for the hacker is access to the SQL Server  - and writing a simple select * from user_cleartext would show all password for all users.

Encrypting and decrypting passwords

So lets add some encryption. By using the something like the DESCryptoServiceProvider we are able to encrypt the passwords before storing it - and by using the same key
we can decrypt it - which is needed for login verification.

But hold on - this means that if the hacker gained access to the database, he would still "just" need to crack the key being used - and probably that key will be somewhere (hardcoded) inside your application maybe. And moreover - if the hacker cracks the key - ALL passwords will be available to him.

Hashing passwords

Now lets look into a solution where the crypted data can't be decrypted back - SHA1. That algoritm is instead just able to compute hashes from data - and the idea is to save the hashed value in the database. So in the login function we can hash the password the user just entered - if it matches with what was saved in the database we know the user has entered the
same (correct) value. This technique does not involve any keys at all.

Hashing passwords and salt

Now - the last problem. The SHA1 algoritm (being mathematic) will of course produce the same hash value each and every time for the same password. That's the whole idea. But it would open for dictionary testing - if someone gains access over a database of 200000
passwords and finds the same (hashed) password in say 100 rows - even my initial guess would be to start trying to hash common words like "secret" etc and see if it produces the same value.

So the last thing we do is add a random element to our hashing algoritm. It's called using a SALT. For each user account we generate a random string (salt). We append the salt to the password before hashing and stores the (unique per user) salt in the database along with loginid and hashed password. In short - we are adding a random element to the users selected password - since users often aren't too "clever" in selecting password, we can add some cleverness to it. 

Next, when verifying the attempt to login, we retrieve the salt value for the user from the database - modify the entered password the same way as when creating the account (appending salt) - and computes the hash on the resulted string.

And it will give unique values in the column hashpwd  for each user regardless of whether they have the same password or not.

Please note that using a non decryptable password storing algorithm means just that. If a user calls you and say - "hey, I have forgotten my password - can you tell me what it is" - you just can't.

Instead the method is to offer a way (either through your interface or by provided by system admin) to reset a password - i.e create a new password for a specific user.

This method with salt and storing just the computed hash value - not the actual password - is implemented in ASP.NET 2.0 membership provider system - but this article shows you how to use it in your ASP NET1.1 (or Windows forms) applications as well.

 Please now read Part 2 - which explains the downloadable application.  

ASPCode.net recommends