views:

145

answers:

5

How can I easily salt a password from a Textbox.Text?

Are there some built in wizardry in the .NET framework?

+2  A: 

Here's a nice article and another one (which is more adapted to ASP.NET applications).

Darin Dimitrov
The second article is better, since it allows for an arbitrary salt size. The first one recommends a 4-byte salt; definitely way to small. Salts should be long. I'm not criticizing you, just placing this here for posterity. :)
Randolpho
A: 

There is no wizardry, a salt is simply some random text appended to a password to defeat dictionary attacks - make up your own jibberish.

Adam
A: 

Have a look at the hmac functions like hmacdm5, hmacsha1 or hmacsha256.
Look at the System.Security.Cryptography namespace, too.

tanascius
@downvoter: I'd like to hear about the problem ... thx
tanascius
Me too. :S Why would this be downvoted?
Sergio Tapia
Possibly because its not got much to do with salts directly? Not sure...
Adam
+5  A: 

We had a great discussion a while ago about best practices when salting a password, you might find some great ideas there:

Salting Your Password: Best Practices?

I've found that one of the easiest, while still being fairly secure, is to use a GUID as your salt. It's random and sufficiently long. It works best if you include the string formatting of the GUID (the '{' and '-' characters), but you don't have to.

Remember that the salt has to be unique per item salted and that to be most secure, you should use a cryptographically secure random number generator. Remember also that you have to store your salt along with the password, or you won't be able to check the plaintext version against the hashed version! You can store the salt un-encrypted if you like; I typically put it in a field on the same table as the password. The purpose of the salt isn't to remain hidden, it's to make rainbow tables difficult (hopefully impossible) to compute in a timely manner.

Here's a quick snippet that will work in C#:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] buffer = new byte[1024];

rng.GetBytes(buffer);
string salt = BitConverter.ToString(buffer);
var saltedPassword = password + salt;

or...

var salt = Guid.NewGuid().ToString();
var saltedPassword = password + salt;
Randolpho
If you generate random salts, remember to keep hold of them as you need them to decrypt on the way out.
Adam
@Adam: good point. I originally had a sentence to that effect but have apparently edited it out. I'll put it back in.
Randolpho
No worries, +1 for a good explanation :)
Adam
+3  A: 

I suppose you are asking for a username along with the password?

In some systems username is used as a salt. (And I think it is OK to do that.) Otherwise you'll need to have your salt stored somewhere and retrieve it before hashing (in case of random-created salt) or have an algorithm which will return the same salt for the same user (and it is not better that just using a plain username).

Personally use the following code:

byte[] GetSaltedPasswordHash(string username, string password)
{
    byte[] pwdBytes = Encoding.UTF8.GetBytes(password);
    // byte[] salt = BitConverter.GetBytes(userId);
    byte[] salt = Encoding.UTF8.GetBytes(username);
    byte[] saltedPassword = new byte[pwdBytes.Length + salt.Length];

    Buffer.BlockCopy(pwdBytes, 0, saltedPassword, 0, pwdBytes.Length);
    Buffer.BlockCopy(salt, 0, saltedPassword, pwdBytes.Length, salt.Length);

    SHA1 sha = SHA1.Create();

    return sha.ComputeHash(saltedPassword);
}
Regent