5

Consider the following two methods:

hashedPassword = hash(trulyRandomSalt + password)

Where hashedPassword and the trulyRandomSalt are stored in the database.

hashedPassword = hash(applicationConstantPepper + uniqueUserName + password)

Where the hashedPassword and uniqueUserName are stored in the database and the applicationConstantPepper is stored in the application config. Here, the uniqueUserName acts as a salt which are usually email addresses.

I have read this question which has a lot of great information but doesn't address an application constant pepper value and how that will improve using usernames as a salt.

I have always used method one with a 32 bit cryptographically random salt. However, I've just seen method two used in another application. The first issue I have with method two is that it ties the username to the hash so that the username can never change without regenerating the hash.

What are the security issues with method two? Which would be the best method to use?

Community
  • 1
  • 1
Jason Eades
  • 1,547
  • 5
  • 16
  • 31

4 Answers4

1

Consider the following two methods:

The first method is terrible because it allows attackers who get your hashes to use something like oclHashcat to make, typically, trillions or quadrillions of guesses per month, and the second is horrific because those same attackers can not only make the same, typically, trillions or quadrillions of guesses per month, if they get ahold of the applicationConstantPepper and usernames before they get ahold of your passwords, they can precompute guesses while they work on getting your passwords.

Please read How to securely hash passwords?, in which Thomas Pornin states "For peppering to be really applicable, you need to be in a special setup where there is something more than a PC with disks; you need a HSM." Please read the entire article for context, but the gist of it is:

  • Do use PBKDF2 (also known as RFC2898 and PKCS#5v2), BCrypt, or SCrypt.
  • Do not use a single pass of a hash algorithm, regardless of how good your seasonings are.
  • Do use an 8-16 byte cryptographically random salt.
  • Use as high an iteration count/work factor as your machine can handle at peak load without causing users to complain.
  • For PBKDF2 in particular, do not request or use more output bytes than the native size of the hash function.
    • SHA-1 20 bytes
    • SHA-224 28 bytes
    • SHA-256 32 bytes
    • SHA-384 48 bytes
    • SHA-512 64 bytes
  • If you're on a 64-bit system, consider using PBKDF2-HMAC-SHA-384 or PBKDF2-HMAC-SHA-512, which will reduce the margin of superiority an attacker with 2014-vintage GPU's will have over you.

If you like the pepper concept anyway, please read Password Hashing add salt + pepper or is salt enough?, again, Thomas Porrin's answer in particular.

Community
  • 1
  • 1
Anti-weakpasswords
  • 2,604
  • 20
  • 25
  • Thomas Porin misses a couple of subtle points (or he knows them but he's painting with too a broad brush). – jww Mar 25 '14 at 02:52
  • What points in particular, and why not suggest them in a comment or edit on that answer, so they can be included in such a popular question and answer? – Anti-weakpasswords Mar 25 '14 at 03:02
  • "...and why not suggest them in a comment or edit on that answer" - Its not a battle I'm interested in fighting. – jww Mar 25 '14 at 03:04
  • @noloader, could you provide a reference and/or quote or two here, if they specifically pertain to my answer or the original question? – Anti-weakpasswords Mar 25 '14 at 03:06
  • I believe salts (and peppers) are considered public parameters. There's no need to store them in an HSM. However, storing a key to an HMAC would be appropriate. HMACs have provable security properties (like a PRF and PRP notion of security); and unkeyed hashes are not equivalent to them. Like I said, there were some subtle points that were not quite right. – jww Mar 25 '14 at 03:24
  • Thanks for pointing me in the right direction. I will look into PBKDF2, BCrypt, and SCrypt. – Jason Eades Mar 25 '14 at 04:12
1

Consider the following two methods...

Neither are particularly good....


What are the security issues with method two?

John Steven of OWASP provides one of the better write ups related to password hashing and storage. He takes you through the various threats and explains why things are done in certain ways. See


Which would be the best method to use?

hashedPassword = hash(applicationConstantPepper + uniqueUserName + password) does not provide semantic security. That is, using the constant pepper and the username, the adversary could tell if an oracle answered with a random answer or the real answer.

hashedPassword = hash(trulyRandomSalt + password) is probably equivalent to or mildly better than the other proposed method. The per-user random salt has a lot of desirable properties. But it can be improved upon, too.


Finally, why reinvent the wheel? Go to Openwall's Portable PHP password hashing (phpass) and use it. Its written by the author of John the Ripper. Solar Designer keeps up with the state of the art in password cracking, so the library is probably very useful in practice.

jww
  • 97,681
  • 90
  • 411
  • 885
  • You say neither of these inputs are very good. What would make for a better input to the hashing function? – Rick Oct 17 '16 at 17:23
  • @Rick - You probably want to forgo the hash all together and use a keyed hash. The keyed hash is a HMAC. You also probably want to iterate over the input rather than using one iteration. The application specific pepper is probably good. In the bigger picture, this question is not a good fit for Stack Overflow. Security goals need to be stated, and analysis needs to be performed. Asking fellow programmers what they do is leading to useless answers void of context and analysis. You should probably read John Stevens' material. – jww Oct 17 '16 at 19:33
  • Thanks, I see your point that the security context really needs to be defined to get useful answers. For password hashing I would think that once you have a unique salt, length extension attacks don't have any use, so the difference between an iterated hash and a keyed hash would be negligible. Do you know of another advantage of HMACs over iterated hashes besides protection against length extension attacks? – Rick Oct 18 '16 at 12:17
1

In addition to Anti-weakpasswords answer, i would like to point out, that both (salt and pepper) have its purposes. If you apply both, then use a random salt and store it in the database (not a derrived one), afterwards encrypt the password-hash with the server-side key (pepper).

I wrote a tutorial in which the pros and cons with the pepper are explained more indepth. Using a server-side key is an advantage, even if the key cannot be protected entirely.

martinstoeckli
  • 23,430
  • 6
  • 56
  • 87
0

Both methods are approximately equal and are fine as long as you're using a good hash (see other answers)

Using a username has the issue that the username can be re-used. This can be a huge problem if you don't include an application specific prefix as the username is probably used many places so there might already be a decent rainbow table for that username.

The "pepper" helps alleviate this issue by requiring the rainbow table to be specific to your application. Now it only becomes an issue if a user changes their password frequently, as now the attacker could get all the old passwords by generating one rainbow table, instead of getting only one password per search. In my opinion this is a nearly negligible downside, as

  1. most people don't change their passwords frequently
  2. the attacker would still have to access the hash for each password they want to crack, so for a one time database breach there would be no difference.
  3. Anyone who changes their passwords very frequently is likely not reusing the same passwords elsewhere so the additional passwords acquired would be less useful.

Overall, from an attacker's standpoint there's not much gain from a target using usernames as salt if combined with pepper to make them unique.

Rick
  • 1,240
  • 14
  • 21