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.