5

Context: A website is hosted on multiple dedicated servers. There are frontend webservers, backend DB servers and other servers between them. The DB holds user's accounts passwords. All connections are secure and the registration/login pages can not be bruteforced (out of the question's range).

Threat model: A hacker manages to get a copy of the DB and wants to crack the passwords. The hacker has very powerful hardware power at his disposal (CPU/GPU/RAM/ASIC) and only needs to crack one single password to be considered as the winner (protecting a maximum of users is not enough, all users must be protected).

Question: Which of the cases below would be considered the most secure against the hacker efforts?

  1. Traditional iterations based hashing with salt (scrypt/bcrypt)
  2. Handmade multi-peppered hashing with very long secrets held at each "stage" (webserver/middle/DB).
    • Webserver operation: Hash1 = SHA512 (password + secret1)
    • Middle operation: Hash2 = SHA512 (hash1 + secret2)
    • DB operation: Hash3 = SHA512 (hash2 + secret3)
    • DB storage: Hash3 with salt

My opinion is that case 2 is by far the more resistant because iterations will not protect poor (low entropy) passwords such as "123456" for more than a few hours/days at best. As long as the secrets are very long and at least one of them remain unknown then I think the increased entropy will secure everyone for decades.

I do not see such scheme rolled out on production very often though, in general the consensus is "iterations+salt or get shamed", so maybe I am missing something.

Of course the implementation would need to be secure (handmade vs more standart scrypt) and the secrets must remain unknown. Moreover if a secret is revealed and must be changed, the update process would be a pain. On the other hand, login process would be more hardware friendly (no iterations).

Edit (based on Matthews comment): My question is not about the benefit of a pepper in an iterations based method. It is the security difference between iterations based vs secrets based methods.

Edit 2: I made more searches and managed to find a similar question after all, my bad (maybe the results improved based on my activity on current question though). It has a nice answer (by Thomas Pornin) similar to here.

10
  • There are loads of questions asking very similar things around. The key problem is that if you're trying to protect against weak passwords, an attacker won't bother trying to crack the passwords. They'll get a botnet and try weak passwords against the usernames, using your normal system. They've got the usernames - they're in the DB...
    – Matthew
    Commented Feb 2, 2017 at 15:56
  • I agree about the number of questions on this topic but I think mine is quite specific and has not been covered by any other. Moreover, while your mention of "botnet attacking the normal system" could be valid on a normal context, I asked to keep login process abuse as off-topic here.
    – HashDoe
    Commented Feb 2, 2017 at 16:08
  • 2
    Why not do both? Use a slow hash algorithm and many peppers? The pepper is not a replacement to the "slowness" of the algorithm, it is a complement.
    – Anders
    Commented Feb 2, 2017 at 17:03
  • 2
    Say an attacker manages to get a db dump. That means there is at least one security vulnerability (whether that is a bug in your application or a disgruntled employee who deliberately exposes your data). Can you guarantee that there are no vulnerabilities that may expose the pepper? Worst-case scenario, vulnerabilities in your application expose the database and your secret peppers. At that point, your only defence is a salt and a slow hashing algorithm.
    – knbk
    Commented Feb 2, 2017 at 19:29
  • 1
    The attacker getting a dump of the db is also quite unlikely, but it does happen. The point is that you want to defend against those scenario's anyway, you don't want to assume that they just don't happen.
    – knbk
    Commented Feb 2, 2017 at 20:25

2 Answers 2

4

Assume that your system is fully compromised. An attacker has all of your peppers, all required salts, and knowledge of how you're combining them. This is the equivalent situation for an attacker who gets a table of bcrypted passwords.

At this point, for your scheme, breaking passwords is fast. SHA-512 can be calculated at millions of hashes per second. For the current general advice, bcrypt, breaking passwords is still slow. By tuning it, standard hardware could be restricted to 100s per second, with specialist hardware still only giving 10,000s per second.

Now, if you can be absolutely sure that no one can steal your pepper data, that's fine. However, if you do lose them, your passwords are almost instantly vulnerable - fast hashing lets an attacker try common passwords easily. On the other hand, the iterations don't have that issue.

The iterations are also easy to implement - one, usually built in, function. That's very little effort for developers, which makes it easy to implement correctly. On the other hand, your scheme requires hashing code in multiple places, on different servers. You need to make sure that the intermediate hashes aren't exposed at any point. You need to ensure that the code at each layer is correct. You might need to run extra software on some systems (does the DBMS natively support the hashing method?). There are lots of moving parts. It's a lot easier to make a mistake somewhere.

In short, iterations retain security in the event of complete compromise, and are easier to develop. In an ideal world, multilayer pepper would help against the failure mode where the database is compromised, and no other systems are. It would be suitable for adding to a system with high security requirements, in addition to using slow (high iteration) hashing, but not instead, unless you have complete confidence that the peppers can never be compromised.

1
  • Thanks, this is a nicely written summary of what most people seem to be thinking. Key management is hard and can totaly fail, yet it can offer superior security in some cases... it's sad that it is not used more often.
    – HashDoe
    Commented Feb 2, 2017 at 22:38
4

A message authentication code with a secret key that's unavailable to the attacker will indeed resist many attacks that resource-intensive password hashing won't. There's no question there. You don't even need the excessively complex three-tier key architecture; just one 128-bit secret key would be plenty.

(Side note: I highlight "message authentication code" because that's the cryptographic construct that's appropriate for your proposal. Your "SHA512(password + secret)" betrays that you don't seem to know what construct is appropriate for what you've proposed; HMAC-SHA512(key, password) would be the better choice.)

But here's the big, difficult topic that your question completely sidesteps: how do you protect those secret keys? You say this:

Of course the implementation would need to be secure (handmade vs more standard scrypt) and the secrets must remain unknown.

...but those two are precisely where laypersons who attempt to implement your proposal will fail, again and again! You already have questionable crypto in your proposal (handrolled keyed hash instead of HMAC, three layers of MAC computation when just one would do), and you say nothing about how you'll make sure your secret keys don't get disclosed—which is the point on which the security of the scheme hinges!

Moreover if a secret is revealed and must be changed, the update process would be a pain.

This can be solved with a hash-then-encrypt approach, like Dropbox has adopted (with bcrypt, however). The equivalent in your no-iterations approach would be something like encrypt(key, hash(password)), or (scarcely) better encrypt(key, hmac(salt, password)), which would allow you to later rekey the encrypted hashes.

I do not see such scheme rolled out on production very often though, in general the consensus is "iterations+salt or get shamed", so maybe I am missing something.

Insecure storage of long-term secret keys is really, really common, and nearly everybody who suggests using a pepper haven't really thought the key management problem through. This is what makes key-less schemes like resource-intensive password hashing so valuable and such a strong recommendation; if we can avoid or reduce the reliance on secret keys, that is generally a plus. Basically, key management is hard, so the fewer long-term cryptographic keys we need to store and defend the better, and the more we can mitigate the consequences of failure the better as well.

Secret keys should therefore only be considered for password hashing after:

  1. You've adopted resource-intensive password hashing, which serves at least as a fallback line of defense if the keys are disclosed.
  2. You have a well-thought out and well-engineered system for protecting and managing your systems' secret keys—ideally one where the keys are stored in just one secure key management system whose only purpose is to store long-term secret keys and never to leak them to any external system. A KMS shouldn't disclose the keys not even to its clients, who instead must resort to asking the KMS to perform cryptographic operations on their behalf. Some examples:
8
  • Your answer's last part seems to be the conclusion everyone else share : "secret keys are much more secure but key management is hard". I do not agree with your first part though, HMAC will not provide any added security over hash (unless you expect SHA512 to have collisions on a field a short as a password). Hacking 3 layers of service, each on dedicated hardware with different running applications and access rights is probably much more difficult than hacking a single one too, for obvious reasons.
    – HashDoe
    Commented Feb 2, 2017 at 22:30
  • The idea that hacking three different layers is harder is wishful thinking. You highlight the ways in which they're different, but they will likely also share just as many commonalities—e.g., they'll all be running the OS, receiving the same patches, same third-party monitoring software, etc. Even the custom software that differs between them will often be written by the same team who may well introduce the same security flaws into all layers. And in any case, if the solution worked the fact that it would require three layers of dedicated hardware is a big disadvantage! Commented Feb 3, 2017 at 0:13
  • Also, the fact that you're talking about "collisions" when discussing HMAC vs. SHA-512 does not reassure me that you understand the issue here: what are the necessary properties for your scheme to be secure, and what functions or construction supply those properties? What you want here is a message authentication code, because (a) it's a secret keyed function, and (b) it provides existential unforgeability under adaptive chosen message attack. HMAC is a very secure MAC; hash(msg + key) might not be. Commented Feb 3, 2017 at 0:21
  • 1
    To clarify that last comment, in this context, "existential unforgeability under adaptive chosen message attack" means that even an attacker who can submit passwords of their choice for you to hash, observe the results, and adapt their attack based on what they learn from these results, still cannot feasibly forge any message + hash pair that they haven't tried already. HMAC provably has this property, and HMAC-SHA512 likely has it. sha512(password + key) doesn't. Commented Feb 3, 2017 at 0:25
  • 1
    "Message authentication code" is just a name, what matters is what it promises, not what it's called. A MAC promises that an attacker who doesn't know the key, even if they can learn lots of (message, tag) pairs, even if these pairs are of their choice, can't forge even a single other one. Applied to your context this means that an attacker who doesn't know the key, even if they can learn lots of (password, hash) pairs, can't learn any other one, much less one for a password or hash of their choice. This is exactly what you want and HMAC provides it. Commented Feb 3, 2017 at 1:24

Not the answer you're looking for? Browse other questions tagged .