I found this presentation how Facebook stores customer passwords and how they do authentication.

This slide shows how they hash passwords:

enter image description here

Is it a good idea to do such operations with a raw password? Isn't it "security-by-obscurity"? Does it make sense to do such operations with PBKDF2 as we're going to use?

  • 1
    Why do you think it's security through obscurity? They are implementing hashing & salting. It's the industry best practice for password storage. MD5 and SHA1 are cryptographically weak (given modern computing), but this is also from 2014, so I'm not sure if they are still using those algorithms (I'd be surprised). – HashHazard Mar 16 '18 at 17:34
  • I'm asking if something like it makes sense now in 2018. We're going to use PBKDF2 HMAC-SHA256 with 8bytes salt, we're discussing what hashing schema use. – Artegon Mar 16 '18 at 17:40
  • 1
    I'm confused about what your question is. Can you restate it? – schroeder Mar 16 '18 at 17:50
  • 1
    what operation on a raw password are you talking about? – dandavis Mar 16 '18 at 23:25
  • 1
    @eckes PBKDF2 is not faster as they both have configurable hardness. The real difference is that PBKDF2 is not memory-hard, whereas scrypt is. – forest Mar 17 '18 at 1:03

This "Onion" construct can be dangerous and should only be done if you have enough reviewers, it does however add multiple favorable properties compared to simple hashing:

The first unsalted MD5 can be done by clients or frontend servers. It normalizes charset and length and obfuscates passwords early on without being too CPU intensive.

The salt is read from the user database so it is not present on the client, this is was the first HMAC adds.

The crypto service (or better HSM) defends against brute force (as the secret key is not known). In fact this predates NIST recommendations to do exactly this. This peppering is not often done as it requires complicated system setup (HSM or process isolation) - something Facebook can afford.

Since the pepper step could be compromised by insiders, the data is then passed to scrypt, a function designed to make brute force testing of passwords more expensive.

The final step might not be needed, or maybe it is used to add some diversification (SHA2 instead of SHA1).

It looks a bit like snake oil overdo but the steps can be reasonable explained. If you compare it with the (much weaker) glibc-SHA2 Voodoo it is really clean.

BTW1: memorable Authenticator are generally a bad thing, such schemes can only reduce the risk of handling them.

BTW2: collision weakness of SHA1 does not apply to HMAC constructs and the short MD5 hash size does not hurt much here (as passwords almost always have even less entropy). It would be more risky for key derivation, but that’s not the task at hand.


In one of the comments you wrote:

I'm asking if something like it makes sense now in 2018. We're going to use PBKDF2 HMAC-SHA-256 with 8 bytes salt, we're discussing what hashing schema use.

The answer to that is no. The only part that should be replicated from the FaceBook solution is using a memory-hard function and the cryptoservice peppering. The MD5 and HMAC parts don't add to security. (They are fairly harmless though.)

You should not be using PBKDF2. In order you should prefer:

  1. Using a binding to the official native optimized implementation of Argon2
    • Refer to the Argon2 spec's "Recommended parameters" section for how to choose parameters.
    • The choice between Argon2d, Argon2i, and Argon2id may be up for debate. The current official recommendation is Argon2i for people that don't know which one to choose.
  2. Update your software so you can choose 1
  3. Protecting encrypted data using a password and can't use Argon2? Use a binding to a native optimized scrypt implementation. Set the single cost parameter high enough to use a lot of RAM and time. If it seems safe to reduce the time scrypt runs then reconsider. That also reduces the RAM-based cost.
  4. Protecting a few passwords, can't use Argon2, and can tolerate slow responses? Use scrypt with the same cost parameters as 4. If you're trying to protect admin accounts then prioritize using very strong passwords and encryption first.
  5. Protecting many users' account passwords and can't use Argon2? Use a library that uses a binding to native optimized bcrypt. Make sure the library correctly works around all of the original bcrypt algorithm's quirks. (The password will get truncated if it's too long or contains a null character.)
  6. Use a binding to native optimized PBKDF2. Don't use a derived key length greater than the underlying hash function's output length.
  7. Don't implement your own password hashing function. And especially don't run that implementation in an interpreter where it will be much slower. Update!

As for whether the FaceBook method is security by obscurity. No. But the HMAC parts and probably the MD5 part are redundant. The cryptoservice part probably uses an HSM. This should allow password hashes to be encrypted/decrypted without necessarily exposing the encryption key to the type of hackers that can steal a password-hash-database. Using mainstream encryption algorithms with a secret key does not count as obscurity. The password still needs to be hashed in case the key is ever leaked. That's what scrypt is for, but now Argon2 should be preferred.

Edit: See comments. As presented in the slide, the password does not get encrypted. HMAC is one way, just like hashing. The alternative of encrypting after hashing is useful because it allows the key to be replaced. Users need to enter their password if you change the key with this FaceBook setup, in addition to the salt or scrypt parameters. If you encrypt the hash then you can decrypt and re-encrypt it without requiring the user to enter their password. (If your key is ever leaked... But you can't rehash a password without the original.)

Also use 20 bytes of salt. Or at least 16.

  • Aside: I scrapped a post where I explained why the redundant steps were not harmful. And why the other steps were needed. I was also going to speculate why the were there, too. @eckes speculation that MD5 was part of client side hashing is reasonable. But client side hashing with a fast hash isn't useful for anything besides maybe side-channel related defenses. – Future Security Aug 22 '18 at 21:55
  • HMAC is not encryption, but besides that good answer! – AndrolGenhald Aug 22 '18 at 21:59
  • @AndrolGenhald Oops! That mix up is a huge pet peeve of mine. (Actually it's probably justified as quite a serious misconception.) I was working from memory and didn't notice HMAC in the line just before the red one. FB did use HMAC, but the should have use encrypt(secret, scrypt(password, salt)). That way keys can be replaced without users entering their password. (At which point it may as well be changed.) I remembered this slide and could have sworn they did it the second way. – Future Security Aug 22 '18 at 22:13
  • Just to be clear, you're suggesting encryption after scrypt/Argon2, whereas the slide shows an HMAC before scrypt, correct? Encryption before hashing wouldn't allow changing the key either. The benefit seems pretty small though, changing the key without changing passwords only matters if the encryption key is leaked without the hashes also being leaked. – AndrolGenhald Aug 22 '18 at 22:46

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.