Posted by & filed under Security.

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:

SHA3(MD5($pass+"0NWOV_8")+SHA2("JE48LWV"+$pass)+SHA1(MD5($pass+"OWND87")+$pass)+$pass+"UEND73D"+$pass)
SHA2(SHA3($pass+"68W")+$pass+"UWOM969"+MD5(MD5($pass+"joweoi20")+"OWJO89"))

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.

The syntax for the algorithm might not be the easiest to parse, and I suspect there could be a better format for this, such as some sort of Reverse Polish Notation. Ideally, this algorithm syntax should be easily parseable and executable by multiple languages (PHP, JavaScript, Ruby, Python, you name it).

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.

Thomas Hunter II

Thomas is the author of Advanced Microservices and a prolific public speaker with a passion for reducing complex problems into simple language and diagrams. His career includes working at Fortune 50's in the Midwest, co-founding a successful startup, and everything in between.
(Visited 72 times, 1 visits today)