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:
- How do I hash a string using C#?
- What would the field declaration type be in MSSQL? nvarchar(64)?
- What is salting and do I need to save that somewhere in my database?
- If I intend to let people use Facebook Connect, do I need to worry about creating a hash/salt?
Code examples are preferred. Thanks!
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.
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.
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)
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...