1

I want to hash "user + password".

[EDIT: prehashing "user" would be an improvement, so my question is also for hashing "hash(user) + password". If cross-site same user is a problem then the hashing changed to hashing "hash(serviceName + user) + password"]

From what I read about salted hash, using "user + password" as input to hash function will help us avoid problem with reverse hash table hacking. The same thing can be said about rainbow table.

Any reason why this is not as good as salted hashing?

5

The short answer is that when it comes to security, and especially when it comes to cryptography, don't roll your own. Use vetted schemes that meet the approval of the security community in general. Your home-grown method is practically guaranteed to have flaws that you haven't thought of.

For a longer answer, read Thomas Pornin's excellent treatise on how to securely hash passwords. Most of what I'll write here is contained in that answer.

For password hashing, there are three generally-approved hashing functions: PBKDF2, bcrypt and scrypt. I won't compare them in this answer; none of these is a wrong choice. Several threads on Security Stack Exchange compare them, in particular Do any security experts recommend bcrypt for password storage? and Are there more modern password hashing methods than bcrypt and scrypt?.

Now, getting to the technical answer to your question, there are two things wrong with using e.g. SHA-256(username + password) as the password hash. The first thing is that user names are not unique. This has several implications:

  • In particular, this makes it obvious when a user has picked the same password on different sites, which can help for some targeted attacks.
  • Using a weak, predictable “salt” also facilitates non-targeted attacks that focus on the most common user names, e.g. a rainbow table with the 1000 most common user names and the 1,000,000 most common passwords has the same size as a rainbow table with the 1,000,000,000 most common passwords for unsalted hashes, and still catches quite a few weak passwords. A truly unique salt makes precomputed table useless.

The salt technically doesn't have to be random, but it needs to be unique, and using a random string is the easiest way of meeting this requirement.

For more details about salts, see Why are salted hashes more secure? and Convincing my manager to use salts. A pepper may optionally be combined with the salt — it's a good defense against some common attacks (database dump by SQL injection).

A second problem with your approach is that something like SHA-2(salt+password) is not good either. A hash function must be slow — legitimate servers only compute one authentication value, whereas attackers must make a lot of failed attempts, so slowness penalizes the attacker more. General-purpose hash functions like SHA-1 and SHA-2 are designed to be fast, they are no good for password hashing. You can turn them into a good password hash function by repeating them many times — but don't roll your own, because the devil is in the details: PBKDF2 is based on this principle.

  • I haven't mentioned any use of SHA1 or SHA2. That detail can be easily changed. How do you know what I use to come to that second problem? For the 'same user' problem on different sites, I would use the hashing of not just "user + password" but "serviceName + user + password". It would solve the two problems you mentioned. Note that for problem 2, one can prehash the 'user' or the 'service + user' part, so the second problem is not even a problem. But your answer is the best answer to my question. Many thanks. – InformedA Aug 20 '14 at 4:15
  • 2
    @randomA The second problem is very much a problem! The problem is not, as you seem to have read, that hashing is too slow, but that it is too fast. Hashing must be slow by construction, so that brute force attacks take a long time. If part of the computation can be done in advance, that is a bad thing. – Gilles Aug 20 '14 at 9:02
7

A salted hash has several advantages over the approach you mention.

  • Salt adds uniqueness. Since it is randomly generated each time a password is created or changed, it guarantees that two identical passwords have different hashes. Using the username would sort of achieve this goal, but the salt is more effective since it changes with the password while a username normally does not change. It is stronger over time.
  • Salt introduces more entropy. The number of bytes in a salt may be more or less than a username, but introduce more entropy. A salt is completely random in all eight bits per byte. A username is at best an email address with 52 letters (upper and lower case), 10 numbers, and a few punctuation. Let's say 64 characters, so 6 bits per byte (and typically less).
  • Assuming the username is known, the same password would hash to the same predictable value in multiple password records. Salt is random and not tied to the login, so the same username and password combination would still result in different hashed passwords when using random salt.

Salt can be arbitrary length and contain a lot of entropy, making the hashed password more secure.

For more information, I recommend you visit the information security stack exchange site.

  • 6
    The conclusion is correct, but the details aren't quite right. The function of the salt is not entropy, but uniqueness — enough entropy does achieve uniqueness, which is why generating a random salt (the usual method) is a fine choice. The attacker knows the salt if they know the hash, that's not an issue. The third point is important and is why the salt needs to be unique and so can't be derived from password and username alone. – Gilles Aug 19 '14 at 8:16
  • @Gilles That is what I get for answering late at night after the caffeine is gone. I still stand by the entropy being a factor, but you are correct, uniqueness is the most important factor. – user22815 Aug 19 '14 at 14:30
  • For your first point of uniqueness, my thought is that the uniqueness is a combination of "serviceName + userName". If you don't worry about multiple services/servers then only userName is taken into account. Therefore, "serviceName + userName" would give you the same uniqueness that you want a salt to fulfill. – InformedA Aug 20 '14 at 4:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.