Saving Passwords...

Published 17 January 05 11:57 PM

As a general principle one should never store even an encrypted version of the user's password. You should instead store a hash of the password. When authenticating a user you hash the the password they provide and compare that hash with the one in the database. The benefit here is that even if someone gets a copy of the hashes they can't figure out the passwords.

The second step to keep in mind is that you shouldn't hash just the password, you need to 'salt' it first. If you don't, your hashes are much more easily subject to pre-computed dictionary attacks. Salting means appending a few random bytes. Of course, you now need to know those random bytes when you go to authenticate, so they need to be stored with the password hash.

Here's an example of code to do this:

using System;
using System.Security.Cryptography;
using System.Text;

class PasswordHash {          static int Main(string[] args)          {                  if (args.Length < 1) {                           Console.WriteLine("usage: hash [salt]");                           return 1;                  }                  byte[] password = Encoding.Unicode.GetBytes(args[0]);
                 byte[] salt;                  if (args.Length > 1) {                           salt = Convert.FromBase64String(args[1]);                  } else {                           salt = new byte[6];                           RandomNumberGenerator.Create().GetBytes(salt);                  }
                 byte[] data = new byte[password.Length + salt.Length];                  password.CopyTo(data, 0);                  salt.CopyTo(data, password.Length);
                 byte[] hash = SHA1.Create().ComputeHash(data);                  string result = Convert.ToBase64String(hash) +                           Convert.ToBase64String(salt);
                 Console.WriteLine(result);                  return 0;          } }


If you run it repeatedly against the same password you will get completely different results. For example:
 

D:\src\hash>hash foo
bvjyITcIWEujYvdT1pTQQ1o9Ae0=CnUnZs3R
D:\src\hash>hash foo
2UZUb6qfbx5V9Hc6+aVYUNY9SFQ=LKpLGvwv
D:\src\hash>hash foo
zHYLVghX24quUa8Fia3N6reGztA=sweTFm0v


However if you pass in the same salt then you get the same result. The salt is the part after the equals sign in that base64 encoded blob, so looking at the second run above the salt would be LKpLGvwv and sure enough:
 

D:\src\hash>hash foo LKpLGvwv
2UZUb6qfbx5V9Hc6+aVYUNY9SFQ=LKpLGvwv

 

by fahad
Filed under:
Anonymous comments are disabled