Tags: security, webdevelopment, programming, websites.
By lucb1e on 2014-02-11 22:01:50 +0100
It's so easy to bash Adobe for encrypting passwords instead of hashing them. The entire security community did, and of course they were right. Encryption is by definition reversible, so it was stupid of Adobe to encrypt passwords instead of hashing them, right? Right?
Or maybe not. As time passes and not a single password from an Adobe user has been leaked, aside from the ones solved in crossword puzzles
, I was starting to doubt our judgment. No passwords cracked in months, that is really good compared to some other hacks (LinkedIn anyone?).
So I started thinking. Perhaps we ought to do password encryption on top of hashing. It can't make things worse, right? Are we wrong to advocate only hashing passwords?
To make a long story short, my conclusion is that we should keep hashing passwords instead of encrypting them. Adobe admins are still morons. This is my reasoning:
Adobe just got lucky that it was an old backup that got stolen. If live systems had been compromised, the encryption key would likely have been breached too and everyone's password would now be in the clear.
We can add a secret key to hashes which makes it impossible to bruteforce, too. Just like with Adobe now. No need to apply encryption, only in hashing context your secret key is called pepper*. This way we still have the upside of hashes being irreversible by design while symmetric encryption
* Pepper is like salt, but not the same. A salt can be publicly known as long as each user has a unique salt (so salts can be safely stored in the database
). Pepper however is supposed to remain secret. Oftentimes when a password database is leaked, the pepper key will also be leaked. But not always. When you store the pepper in a config file on disk instead of in the database, it will not be known when attackers can merely do SQL injection.
Also be sure to make it random enough. If the attacker knows his own password is "test" and your pepper is "Hi!", he will only have to compute the hash for X+"test", and since X is only 3 characters, he figured out hash("Hi!test") in no-time.
** Symmetric encryption and peppered passwords are by no means impossible to bruteforce, that's why I added the word "impractical". It's not currently possible to guess a random 128 bits key. A long and random enough pepper will have the same effect: as long as the pepper remains unknown, no password can be bruteforced (not even '1234').
1. Store passwords in the database, together with
2. some information that is unique to that user (the salt).
3. Store an additional pepper value on disk.
4. Use algorithms designed for storing passwords to store passwords. (Wow breaking news!) Sha-512 was never designed to store passwords; bcrypt and pbkdf2 are.
5. Do not use password hints. We have enough crossword puzzles, thank you.
Implementation to create a new user:
$pepper = '169f66fbf12bae560674254b6c51df85'; // on disk
$salt = openssl_random_pseudo_bytes(24);
$passwd = hash_pbkdf2('sha256', $_POST['pwd'],
$salt . $pepper, 9001);
'username' => $_POST['user'],
'password' => $passwd,
'email' => $email,
'salt' => $salt
With this system we have all the advantages we could reasonably have, and our security will be better than Adobe's, Linkedin's and Sony's, to name just a few. And it should be because theirs was, well, horribly insecure as you've seen.
Tip: If you ever need to change the number of iterations/workload of the chosen password hashing algorithm or need to change the pepper, use a wrapper construction like this
PS. Also, please use https correctly
. That article takes 8 minutes to read for the Average American Adult. Come on, next time you implement https, do it. It doesn't even take 10 minutes. Free certificates can be obtained at StartSSL.com
. You also don't need a unique IP because of SNI