http://stackoverflow.com/questions/16891729/best-practices-s...
http://stackoverflow.com/questions/16891729/best-practices-s...
Your pepper will be a long, random key that is known to your app server but not your database server. If you store passwords as:
bcrypt(bcrypt(password, salt), pepper)
then you spend a lot of cycles bcrypting your long, random key, which is pointless (it should already be long enough to be un-brute-forceable), and you lose the ability to rotate keys or ever stop using this scheme in the future. There's also (in theory) some risk that nested bcrypt() doesn't work predictably.If you store passwords instead as:
encrypt(bcrypt(password, salt), pepper)
then you can routinely rotate peppers through a simple one-time decrypt-and-encrypt step on your app server, instead of endlessly nesting peppers as suggested in the filippo.io blog post.The rest of it is more of a qualitative question -- what's the risk that someone gains access to your DB but not your app server, vs. the risk that in implementing the pepper, you somehow screw up and store something easily crackable?
And, no, I am not being facetious by saying nobody knows how to do that. I am being quite literal. Have you ever done that? Do you know how? Do you even know what you would google to figure out how?
I'm yet to see my favorite library of course's documentation on a HSM. How do you do that in e.g. PHP with MySQL? MVC with MS SQL? Java with Oracle?
Edit: There's even a project to literally do this directly from PHP[3]
[1] http://stackoverflow.com/questions/10796485/interfacing-with...
[2] http://en.wikipedia.org/wiki/PKCS_11
[3] http://stackoverflow.com/questions/3231293/how-to-interface-...
You don't get your own HSM but it's MUCH cheaper ($1/key/month) and more scalable and available than an HSM.
I have not used either myself, but I would imagine the documentation is quite good.
The question is irrelevant anyway, because if someone gets access to your app server, they get the secret in both cases (pepper and encryption). So the first risk there is present in both cases, which just makes this a static "what's the risk that you screw up in implementing the pepper?"
So yes, S+P protection won't save you if the app server is completely compromised, but it does protect you in case DB only is.
And the ability to S+P seems pretty simple to implement and document. Why is everyone panicking that it's hard to do?
$2a$12$GhvMmNVjRW29ulnudl.LbuAnUtN/LRfe1JsBm1Xu6LE3059z5Tr8m
$2a means it's using bcrypt version 2a
$12 means 12 rounds
GhvMmNVjRW29ulnudl.Lbu is the salt
AnUtN/LRfe1JsBm1Xu6LE3059z5Tr8m is the checksum
But upon reflection I believe you were instead using the term "pepper" to include the encryption approach as well and merely trying to question whether the added security of requiring an app server compromise is worth the risk that you still screw it up somehow. And to that I'd say that it's not difficult to apply an existing block cipher algorithm when storing/retrieving password hashes so I think the risk there is low.
> Why is everyone panicking that it's hard to do?
Everybody's panicking because the originally proposed pepper implementation is a really bad idea. That approach has not been researched for security implications, and there are many reasons to believe that composing hash operations without using a specially-defined operation like HMAC is bad, and adding static bits to the salt or password (e.g. if you use 'pepper.salt' for the scrypt salt or 'pepper.password' for the password) is also bad.
However, I believe the approach of using a block cipher to encrypt your hashes with an app-wide password is reasonable. It's not composing operations badly (encrypting a 256-bit string, or whatever scrypt emits, is perfectly reasonable given a secure key) or otherwise providing an attack vector on the hash algorithm.
The biggest risk I can see with this approach is you have to make sure the pepper is stored securely on your app server, never visible to the database server (and never accidentally committed to an open-source repo, if you're using an open-source server). Not just that, but you have to make sure that you don't accidentally lose it either (or you'll have instantly lost all your accounts). But this is a solvable problem.
1) You should not invent your own algorithm. That's a given. That's why you use bcrypt/scrypt.
2) It's not abusing the algorithm, it's using a longer salt (in the concatenation case).
3) There's nothing wrong with nesting algorithms (just remember to use hex/base64 encodings, not binary). For example Facebook passes passwords through half a dozen algorithms. They call it the "onion". And it includes a pepper.
4) As for being effective, I think the SQL injection case speaks for itself.
5) As for rotation - just don't do it. You pepper gets compromised? Who cares, add a new one on top of the old one.
Also, I'm confused at how the proposed alternative would be harder to get wrong:
> Encrypt The Output Hash Prior To Storage
salt = urandom(16)
pepper = "oFMLjbFr2Bb3XR)aKKst@kBF}tHD9q"
# or, getenv('PEPPER')
hashed_password = scrypt(password, salt + pepper)
store(hashed_password, salt)
That is an algorithm, which composes bcrypt with pepper.The idea of not using key-rotation alone is insane, but lets just focus on your last point
Also, I'm confused at how the proposed alternative would be harder to get wrong
Really? AES literally has hardware support, and can be done in a single call, and has been studied for years. How can that reasonably be considered "harder" to get wrong than something proposed by some random guy on the interwebs?Outside of Peer-Review, what reason would anyone have to use the pepper scheme? As others have posted, there are several community members who's opinions do matter due to extensive research and body of work
For password hashing purposes, salt doesn't need to be uniformly random, the only requirement for salt is to be unique and unpredictable to the attacker (see http://crypto.stackexchange.com/questions/6119/hashing-passw...). Most password hashing functions use a cryptographic hash on salt.
This particular function, scrypt, uses one-round PBKDF2-HMAC-SHA256 to mix password and salt:
https://github.com/golang/crypto/blob/master/scrypt/scrypt.g...
PBKDF2 feeds salt, basically, into SHA256:
https://github.com/golang/crypto/blob/master/pbkdf2/pbkdf2.g...
But PBKDFs like bcrypt and scrypt are not designed to keep the salt parameter secret; in fact they assume the attacker knows the salt. And so if they happen to reveal the salt to the attacker, this is not considered a bug in the algorithm and won't have been flagged or fixed by cryptographers.
XOR could also result in NULL bytes anywhere in the hash input, which could drastically weaken passwords,. For example, bcrypt ignores any password characters after the first NULL byte. This is especially bad if the attacker can supply their own passwords, doubly so if they can observe the output, since they can then easily brute-force individual bytes of the secret and use that knowledge to intentionally create NULL bytes in the hash input.
> XOR doesn't decrease the keyspace (or change it in any interesting way), so any attack on XOR is an attack on bcrypt
I wouldn't make any statement like this unless you've actually gone through the steps to prove it.
Can you be kind enough to explain with a very simple example?
I would appreciate understanding your point - Thank you
(It's also possible to brute-force more than one byte at a time; it would just take longer. For example if the shortest password the attacker can observe is 6 bytes then they would need to try 2^48 possibilities.)
The real downside is that there's a better, proven way to do the same effective thing, which is make a database-only compromise require additional work, without rolling your own crypto. It also supports doing things retroactively for real (not some of the hacks being discussed in this thread) and key-rotation. All the upsides, with none of the downsides.
Please do not ever consider "rolling your own crypto" a walk in the park. Unless you have a serious security background and some actual cryptography education and research never, never, NEVER do this. It is not negligible, and it is not safe.
scrypt(scrypt(scrypt(scrypt(password, salt), pepper2013), pepper2014), pepper2015)
https://blog.filippo.io/salt-and-pepper/