views:

305

answers:

4

What are the advantages / disadvantages of those 3 methods to create a salt?

$salt = md5($password);

$salt = sha1(md5($password));

$salt = generate_random_number();

Computing hash:

$hash = sha1($salt + $password);
+10  A: 

Salts

To answer this question it's important to know for what salts are.

Salts are designed against attacks with pre-calculated tables. For example rainbow tables. Rainbow tables are huge tables with all possible password variations up to a certain length. (Using a clever memory/time tradeoff.)

If the attacker only wants to crack a single password, they don't offer an advantage.

The statement above is not true if

  • The database doesn't use salts. Then a common rainbow table can be used.
  • The salt is too short. If the salt is too short, it has the same effect as just having a longer password.
  • It's a common salt like salt. There are for sure already some rainbow tables with that salt included.

Attackers using rainbow tables usually want to crack as many accounts as possible.

Which of your methods is most secure?

All of your methods except the third are insecure. This is because using any of the other methods allows the attacker to calculate a rainbow-table for your whole database.

Because the salt is dependent on the password. Don't make it dependent on the username either, this would still allow an attacker to create a rainbow table for the 100 most common usernames.

Keep in mind

  • Use only a cryptographically secure random generator to calculate your salts.
  • Don't use MD5. It's already considered broken, use at least SHA1.
Georg
That's not what a rainbow table is. A rainbow table is not precomputed hashes of a dictionary, it's slightly more complicated. It's a precomputed hash of particular values which is used iteratively to hone in on the plaintext.
blowdart
@blowdart: In the end they _are_ huge dictionaries of all passwords, using a clever storage/time tradeoff.
Georg
Not of all passwords no, they're tables of bits of half completed hash computation which allows part of the password to be guessed. The effect is that it needs lots of lookups to hone in, but it doesn't need a huge dictionary of all words.
blowdart
@blowdart: Impossible. Cryptographic hash functions are designed to make sure guessing half of the password isn't possible. Rainbow tables use hash chains. The longer a hash chain is the more computation time it needs to crack a password, but the less space is needed. That is because only the first and last part of that chain are stored. http://en.wikipedia.org/wiki/Rainbow_tables
Georg
Which proves the point it's a chain of hashes for parts of a hash, not a simple lookup table :) "store only the first and last password in each chain" - the intervening hashes are dropped out.
blowdart
The answer is essentially correct, though if we are nitpicking it might have been better to say that salts are designed to prevent attacks based on precomputed tables, or which rainbow tables are a particular type.
GregS
Ah yes, Greg hits it on the head :)
blowdart
I wouldn't use SHA1 either. Though still safer than MD5 it is looking increasingly shaky. You can even get 'pen testing' tools like this http://sourceforge.net/projects/ssha-attack/
zebrabox
@zebrabox: That's true. I just wasn't sure if there are handy functions in PHP for SHA2 hashes. Therefore I decided to write _at least SHA1_.
Georg
+3  A: 

Well strictly speaking you only have one salting method, where you calculate the hash. The first three lines are different ways of generating a salt.

So a salt is there to stop precomputed lookup tables from discovering passwords. It should be a fixed value stored someone that is, preferably, unique to the plain text being hashed.

The most secure would be to use a cryptographically secure random number generator to produce a salt which is then stored along side the password.

If you created a salt which was an MD5 of the password then it would have to stored alongside the hashed and salted password value, which means you have an unsalted hash which is vulnerable to precomputed lookup tables, unless you plan to calculate it every time which is a small performance hit. By taking a SHA hash of an MD5 hash you're reducing the possibility of the plain text values, as there's a finite number of MD5 hash values as they are fixed length. This would mean that a rainbow table lookup might have a greater chance of success than a truly random salt.

So use the random salt please.

blowdart
Of that particular weakness of having the salt depend on the password I haven't thought, interesting.
Georg
+4  A: 

The first two methods are worthless. The whole point of salting is that the same password does not always result in the same encrypted/hashed string.

If you make the "salt" dependent on just the password, the same password will always result in the same hash. So basically the result is the same as if you'd use a slightly different hash function without any salt.

With the third method two users with the same password will usually get a different salt and the hashed version of the password will look different for both users. It will be hard to tell by the hashes that they both have the same password.

sth
A: 

A useful way to think of rainbow tables is that they can be built for any one-way (or "trapdoor") function that only has one input. That is, if you use the same function, F, for all your passwords: hash = F(password). F could be MD5 or SHA1 or whatever.

Now lets look at salts. You use a salted function G, hash = G(salt, password). If all passwords in your database use the same salt, you can construct a function G, where G(password) = F("your salt", password), so there is a single input function, and thus you can build a rainbow table.

What if the salt depends on the password? Say the salt = I(password), we can build J(password) = G(I(password), password), a single input function, so rainbow tables can be built.

So, each password needs to have its own salt. This means that in the time it would take an attacker to crack all of your passwords, they can only crack one.

ZoFreX