2

I'm building a project from the ground up and I want to do things the Right Way™. I've read online about hashes and that's basically turning a password in 64 letters of mumbo jumbo, correct?

What about salting?

My questions are:

  1. How do I hash a string using C#?
  2. What would the field declaration type be in MSSQL? nvarchar(64)?
  3. What is salting and do I need to save that somewhere in my database?
  4. If I intend to let people use Facebook Connect, do I need to worry about creating a hash/salt?

Code examples are preferred. Thanks!

4 Answers4

1

I will skip question 1 as I'm not a C# person.

Question 3:

Salting is adding a string of random data to the password before hashing. Salts are essential because without them it is possible for an attacker to pre-generate a rainbow table of known password hashes. Salting means that rainbow tables cannot be pre-built, and it means each password must be brute-forced separately.

It is important to generate a new salt for each password.

Salt values are not secret and can be stored alongside the hashed password in your database.

Pseudocode for generating and checking a password are as follows:

generatePassword(String user, String password) {
    String salt = generateRandomSalt();
    String salted = salt + password;
    String hash = hexEncode(hash(salted));
    store(user, hash, salt);
}

checkPassword(String user, String testPassword) {
    String salt = lookupSalt(user);
    String salted = salt + testPassword;
    String testHash = hexEncode(hash(salted));
    return testHash.equals(lookupHash(user));
}

Question 2:

The length of the database field depends on the hash algorithm. SHA1 generates 160-bit output, so that will be 40 characters if hex-encoded. A good rule of thumb is to use a salt that is the same size as the hash output, so you'll have two 40-character columns: one for salt, and one for the hash.

Question 4:

No idea how Facebook Connect works, sorry. I hope the other two answers are helpful.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
  • 2
    If you *really* want The Right Way(TM) then you could also consider iterated hashing. This trades off security against CPU time but makes it extremely difficult for an attacker to brute-force any single password. Without it it is possible to break a single password in as little as a few hours (see http://stackoverflow.com/questions/2772014/is-sha-1-secure-for-password-storage). – Cameron Skinner Dec 09 '10 at 23:50
  • They were tremendously helpful. Thanks for your help. –  Dec 09 '10 at 23:52
  • 2
    Good point about iterated hashing. In C# generating a key using PBKDF2 requires no more code than generating a plain salted hash. See my answer here for details: http://stackoverflow.com/questions/4329909/hashing-passwords-with-md5-or-sha-256-c/4330586#4330586 – LukeH Dec 10 '10 at 00:09
  • To put the iterated hashing into perspective: My machine (2 GHz) can do about 1.2 million SHA1 hashes per second. That's 10^11 candidate passwords per day. There are 10^14 8-character alphanumeric strings so I could break all of those in 1000 days, or 500 if I did the hashing on both cores. So if I have a moderately powerful 4-core machine I guess I could break all of those in – Cameron Skinner Dec 10 '10 at 00:15
1

1) Code

   public static string HashStringSha1(string plainText, string salt)
        {
            using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
            {
                byte[] bb = sha1.ComputeHash(Encoding.UTF8.GetBytes(salt + plainText + plainText));
                return Convert.ToBase64String(bb);
            }
        }

2) Store base64 string in SQLserver varchar

3) Store the salt in a different field with the hash. Salt as plain text.

4) Not sure what you mean. If you use OpenId, you do not need to store passwords.

Aliostad
  • 80,612
  • 21
  • 160
  • 208
0

Hash & salt are used to keep your users password safe. MD5 hash is the most popular algorithm used. Hash functions are irreversible -> you cannot get the password from the hash, but somebody somewhere thought - hey! let's generate a a table that contains example passwords and their hashes then sort that and do simple lookup to check the password. This is why salt was introduced - salt is added to the user password and then hashed. Salt is randomly generated thus should be kept in the db for each hash.

For the details of implementation I suggest you look at live examples like nopCommerce which is open source e-commerce solution. http://www.nopcommerce.com

(this one is very useful because it has a custom membership provider implemented which utilizes the ideas of salt & hash)

kubal5003
  • 7,186
  • 8
  • 52
  • 90
0

How do I hash a string using C#?

Take a look here: http://support.microsoft.com/kb/307020

What would the field declaration type be in MSSQL? nvarchar(64)?

It is binary data. You might want to format it as string, but thats "extra work"

What is salting and do I need to save that somewhere in my database?

You should use a unique salt per entry. The salt is there to make it impossible to know if 2 times the same password was used. usually a slat is constructed from 2 components... A "shared secret" (Needs to be resonably complex, so it can defeat lookup lists) and a unique part (for example a ID value of the user in the DB or something else.... Just make sure that "shared" + "Unique" + Password is unique

If I intend to let people use Facebook Connect, do I need to worry about creating a hash/salt?

If you can use a 3rd party API, then you dont have to care about hashing salting. As long as you dont save the passwords, there is no need to hash. Hashing is a one way function, so there is no "good" way (Hint: Rainbow tables) to reconstruct the original password. If you let facebook handle the authentication, you wont have to worry about all that base plumbing, since you dont store the passwords.

Hashing is used if you want some information so secure, that even someone that steals your DB cannot access it. BTW: That includes yourself... There is no way to recreate the original password...

Heiko Hatzfeld
  • 3,197
  • 18
  • 15
  • The salt should be a newly generated random string. Don't bother including the user ID, it doesn't add any security and just makes your code more complex. – Cameron Skinner Dec 10 '10 at 00:22
  • If you add the user ID, you can use a shared secret, instead of a randomly generated one for each user. This will allow you to skip saving the salt itself to the record. The main goal of a salt is to make your password string unique before hashing it. I also like that the potential attacker does not gain access to all information if he gets the database... – Heiko Hatzfeld Dec 10 '10 at 06:53