Quick Warning: I started to write this article, then went and consulted with one of my co-workers. He explained to me the bcrypt library. PHP implements bcrypt as the crypt() function. When using the blowfish algorithm in bcrypt, an argument can be passed for the complexity of the hash, where each increment increases the complexity of the hash by an order of magnitude. So, one should probably simply use bcrypt instead of implementing the encryption I describe here.
If this article is greek to you, check out my introduction to Encryption, Hashing, and Salting.
I recently heard that Envato’s Tuts+ Premium was hacked on June 26th, and a database of username/passwords were taken. The worst part of all, this site wasn’t encrypting the passwords at all! This is the absolute worst-case situation for having a database of username/passwords stolen. There has been a lot of user database compromises lately. Last.fm was hacked and became public on June 7th (MD5 no salt), LinkedIn was hacked on June 6th (SHA1 no salt), eHarmony was hacked as well on June 6th (MD5 no salt).
What’s the big deal about having hashed passwords stolen? When passwords are encrypted with a common one-way hashing function, attackers can keep a database of the encrypted values as well as their plaintext counterparts. Such a database is called a rainbow table.
This just really shows that apps storing user credentials need to employ better encryption methods.
Here’s kind of the existing levels of password storage and their usefulness:
Plaintext < Reversible Encryption < One-Way Hash < App-Wide Salting < Per-Account Salts
But, today I am proposing a new technique, which is per-account encryption algorithms. It sounds a little crazy, and I’m not sure if it is even a good idea (please provide some criticism). Here’s basically how it works. Each user has a minimum of three pieces of data tied to them. Username, Password_Data, Password_Algorithm. When a user account is created, the Password_Algorithm is generated randomly. Here’s an example of two different password algorithm’s which two unique users may have:
Of course, there would be a bunch of restrictions. Depth of functions would probably not want to exceed 4 or so. Anytime there is a hash function, the password should be contained within the input string somewhere. Total length of the algorithm string shouldn’t exceed a certain number of characters.
Running these complex algorithms would cause authentication to slow down. Which is a good thing. It also means that attempts at running the algorithm many times against all possible passwords will be even slower.
Hashing a hash reduces entropy, so in theory it increases the likely hood of collisions, but not knowing the algorithm ahead of time makes it pretty dang hard to find such collisions.
Let me know what you think of my crazy idea below. Keep in mind that bcrypt is probably better anyways.