views:

164

answers:

4

I had an idea about hashed passwords and salt values. Since I'm rather new to hashing and encryption, I thought I'd post this to you. Would it be more secure to generate a unique salt for each user account, then store the salt and hashed values in the database? Or, keep a single salt value securely stored and re-use that each time I hashed a password?

For example, A user would use the password:

"secret"

My code would generate a salt value of:

"d1d0e3d4b3d1ed1598a4e77bb614750a2a175e"

Then hash the result to get:

"e8187dcbe8e2eabd4675f3a345fe21c98affb
 5544a9278461535cb67265b6fe09a11dbef572
 ce3a4a8f2275839927625cf0bc7bc46fc45d51
 12d7c0713bb4a3"

The hashed result and salt would then be stored in the database in the users profile when their account was created. Then, each time the user logged on, a new salt would be generated, the password and salt rehashed and stored in the database.

Any thoughts? Like I said, this is a sanity check on an idea I had.

+1  A: 

As Adam already mentioned, hashing and storing the password each time a user logs in serves no real purpose.

Rather than rolling your own, you might want to look into using BCrypt.NET, a .NET implementation of a proven password hashing algorithm.

Usage is very simple:

// When setting password
string hashedPassword = BCrypt.HashPassword(password, BCrypt.GenerateSalt());

// Upon login
bool validPassword = BCrypt.CheckPassword(password, hashedPassword);

It allows you to vary the computational costs of calculating a password hash if you want to, making it more difficult for someone to do a dictionary attack on a database they might have obtained for example. This is done by adding a parameter to the GenerateSalt method call.

The details of the BCrypt algorithm can be found here.

Thorarin
Is that salt automatically persisted or does the caller need to store it?
Adam
@Adam: It only does hashing and checking. You're free to store the hashed value anywhere you like, but salt strength, the salt and hash are packed into a single string. This differs from your existing (?) solution where they are two separate values.
Thorarin
@Thorarin so are you saying the salt is appended to the hashed value? Most solutions I see append the salt to the password and hash the lot.
Adam
@Adam: I've added a link that explains the algorithm in detail.
Thorarin
@Thorarin cheers :-)
Adam
A: 

The real purpose of a salt is to prevent against precomputation attacks, as the salt itself is NOT supposed to be secret (i.e. it is fine to have it accessible from the outside world). It is therefore not intended to provide security against brute forcing since it's (almost) as easy to hash(Salt+Password) as it is hash(Password).

If you believe someone will actually build a precomputed table of your one single salt to a database of passwords, then look up the salted password hashes they found in your database with said table, then you should use a unique salt for each password. Otherwise, don't worry about it.

bowenl2
The article you cited says: "In some protocols, the salt is transmitted as cleartext with the encrypted data, " -- doesn't that contradict it not being public?
bowenl2
@Adam: The use of salt is to protect the password hash against pre-computed rainbow tables, not to be a secondary password. For public salt, you have to compute each possible password with the salt, which is a lot more work than getting a table from somewhere else and doing a simple search. Since this only applies if the attacker has gotten the password hashes, which should be secret, it seems pointless to assume that the salt will be kept secret.
David Thornley
+3  A: 

Storing a unique salt per user is a good idea in my opinion. Re-generating the salt/hash combination every time the user logs in is a bit pointless unless you've got CPU cycles to burn. I'd recommend using something like the Rfc2898DeriveBytes class to generate a secure salt/hash combo:

Simple example of generating a hash from a password:

string password = GetPasswordFromInput();

using (var deriveBytes = new Rfc2898DeriveBytes(password, 32))  // 32-byte salt
{
    byte[] salt = deriveBytes.Salt;
    byte[] hash = deriveBytes.GetBytes(32);  // 32-byte hash
    SaveToDatabase(salt, hash);
}

And the corresponding checking of a password:

string password = GetPasswordFromInput();
byte[] salt = GetSaltFromDatabase();
byte[] hash = GetHashFromDatabase();

using (var deriveBytes = new Rfc2898DeriveBytes(password, salt))
{
    if (deriveBytes.GetBytes(32).SequenceEqual(hash))
        Console.WriteLine("Password matches");
    else
        throw new Exception("Bad password");
}
LukeH
Minor quibble: Having CPU cycles to burn doesn't change the pointlessness. :)
Craig Stuntz
Very cool stuff.
Andy Evans
+3  A: 
  • Each user should have their own unique salt.
  • There's no point updating the salt each time a user logs in, this serves no real purpose with regards to security.
  • The salt should be randomly generated and not linked to the password in any way.

The purpose of a salt is to protect against pre-computation attacks (such as rainbow tables). So if two users have the same password, they won't have the same final hash. If the salt is system wide and not per user, then this wouldn't be the case and an attacker only need to pre-compute all of the passwords for your system once. If each user has their own salt, then a pre-computation attack would need to be done on each user individually, making the attack infeasible.

Using a salted hash does not protect against brute force dictionary attacks. You would need to use other methods to protect against those.

Rich Adams