Handling Passwords In CodeIgniter
After an extremely long debate over at the CodeIgniter Forums, I’ve decided to compile the ‘outcome’ of this discussion here, and show you all the best practices for storing passwords in CI.
First of all, we need to make sure that the password sent from the user to us is encrypted, so that prying eyes cant get hold of it at this stage. So, the simple solution is to use SSL.
SSL allows https request data between the client and server, which is encrypted and very secure.
Now with that out of the way, we need to store the user’s password in the database.
Some people are currently using CodeIgniter’s ‘encryption’ library to store the passwords in the database. However, a password stored in the database should always be saved with 1-way encryption… so there is no-way to convert it back to the original plain-text version.
The solution, is a salted hash.
Essentially, you should use a 1-way hasing algorithm (like sha1), and ’salt’ the process.
Let me explain:
First we need a ’salt’… which is basically like a random bit of data we use with every password hash… we’ll use CodeIgniter’s ‘encryption_key’ config item to store this.
This should be 32 characters long, and upper and lowercase letters with numbers for good measure too.
$config['encryption_key'] = "NeO5C88iv7uo09U2E20iJF0iUiz8R9zm";
Now that we have our encryption key set… we build a little function for ‘prepping’ the password before we insert/select it from the database:
function _prep_password($password) { return sha1($password.$this->config->item('encryption_key')); } function login($username, $password) { $this->db->where('username', $username)l $this->db->where('password', $this->_prep_password($password)); $query = $this->db->get('users', 1); if ( $query->num_rows() == 1) { // set your cookies and sessions etc here return true; } return false; } function register($username, $password) { $data = array('username' => $username, 'password' => $this->_prep_password($password)); $this->db->insert('users', $data); }
So, what happens here, is that the password we save is modified using the sha1() function… but, we append our key to the password inside of this function so that we don’t end up with the ’standard’ hash for that string…
This way, we avoid the possibility of dictionary attacks.
And, that’s it!
It’s simple, but exceptionally secure.
After this long debate, one of the forum members: adamp1, posted this little gem:
Let me just throw my view in. I have done a cryptography course at degree level. let me just say one thing, if you have a two way encryption algorithm it can be broken very easily. You don’t even need the key, if you know how it works (the algorithm) most can be broken by simple processes.
If someone really wants some data you store they will be able to get it, doesn’t matter how much you encrypt it. The only way you can stop it is to make the process so hard the data isn’t worth it to decrypt it.
I store my passwords using a SHA-1 with salt method. I would advice you all to do the same. DO NOT use two way encryption just so the password can be made into ****’s. This is crazy, just say to the client NO. Your the expert they should listen to you, and if they still refuse print out a random length string of **’s or something.
So just to clarify, use SHA-1 with salt, its the best there is at the moment. I know SHA-1 has been broken but unless your a crypto-geek its probably the best and easiest to use.


















February 17th, 2008 at 11:00 pm
Excellent post Elliot and something I have covered once before on my blog as well: Handling Forgotten Passwords.
February 18th, 2008 at 3:30 am
I always use one-way encryption in both my personal and professional projects.
Normally, the client doesn’t bother with how passwords are stored (that’s my job), as long as I keep his data perfectly safe.
However, I don’t approve of adamp1’s point:
), that could even be considered a breach of your contract.
In the rare case, that your client requires that you store passwords using two-way-encryption, you’d better not tell him you did so, if you didn’t. In Holland (the best country in the world
Not convinced? Naturally, when passords are stored using two-way encryption, your client will require that you can retrieve his password (which he forgot…again) instantly…now you’ve got yourself a neat, little problem.
February 18th, 2008 at 4:15 am
if you have to use 2-way encryption, I’d do it using mysql’s aes_encrypt function
February 18th, 2008 at 12:30 pm
[...] Handling Passwords In CodeIgniter [...]
February 18th, 2008 at 3:18 pm
I’m getting my PhD in cryptographic hash functions in about a month, have google alerts set up on the keyword ‘SHA-1′, and for some reason have felt compelled to point out some minor issues on otherwise very helpful posts like these.
- SHA-1 is currently only theoretically `broken,’ although I would bet that collisions are found within the next year and a half. Even so, with salts and/or keyed hashes, there is little threat to this system. SHA-256 or SHA-512 are more secure alternatives for those truly paranoid.
- Salted passwords usually use a distinct salt for each password. This scheme above seems to have one global salt. If you’re going to use a global salt, it is a good idea to treat it as a key because if it is found, a dictionary attack then becomes possible. (There are a whole host of issues with key management, though (http://en.wikipedia.org/wiki/Key_management).)
- IF you go with the global key AND an attacker doesn’t find the key, then you’re probably OK.
- Encrypting passwords with a non-one-way function like SHA-1 is discouraged because, again, you need to manage keys. Just know the can of worms you open when you agree to do key management.
- Or you can use a different salt (ideally 16+ characters) with each user, and not worry about keeping these secure because they still prevent a dictionary attack. And make sure your salts are generated with a good RNG (openssl rand -base64 16, eg).
February 18th, 2008 at 3:20 pm
I misspoke in the second-to-last bullet. It should read - “…with a non-one-way function like AES in some mode of operation is discouraged…”
February 18th, 2008 at 4:02 pm
You mentioned using a different salt for every user…
How about this idea?
Take their name and the global_salt… and sha1 that to produce a unique salt for that user…
Use that to salt up the password hash.
February 18th, 2008 at 9:07 pm
Using the username instead of an individual salt will effectively thwart dictionary attacks, with a couple of very small caveats.
- The space of usernames is likely, in practice, much smaller than the space of salts generated with “openssl rand -base64 16″. Maybe this isn’t a such a big deal, but my paranoid security side has to ask the question of whether or not the same technique is used 10 years from now when computers have, say, 100 times as much processing power…
- The system needs to gracefully handle a user changing usernames while keeping the same password. This isn’t a difficult problem to overcome, but is worth mentioning.
Another possibility altogether I forgot to mention: using SSL to transfer the password, although secure, will require expensive public-key crypto operations. With this as the case, you might think of scrapping SSL and this custom password hash and use SRP (http://srp.stanford.edu/). It is a well-thought-out and vetted protocol that also allows the exchange of a shared secret. Weak passwords are protected, even with a very powerful adversary.
It might seem like using something like SRP akin is using a tank where a hatchback will do, but that never stopped James Bond from using the tank.
February 20th, 2008 at 1:43 am
Elliot, I take the timestamp of when the user was entered into the db and use it together with the global salt. At least now I don’t have to anticipate the user changing her username as the timestamp never changes.
February 28th, 2008 at 4:35 pm
I just use CodeIgniter’s string helper to create a random string of X characters long and store that with the user’s record - giving each user a different salt.
May 2nd, 2008 at 4:44 am
[...] Handling Passwords In CodeIgniter [...]
June 27th, 2008 at 8:14 am
[...] Handling Passwords In CodeIgniter [...]
September 12th, 2008 at 10:03 pm
[...] Handling Passwords In CodeIgniter [...]