Hey guys…
Just wanted to make a few comments regarding passwords and security.
The ideal situation is to have a password saved in the database that CANNOT be converted back to plain text under any circumstance.
So, the best practice would be to do something like this:
First of all, set an encryption key in your config.php…
and make it nice and random using a random string generator like this one (make it 32 characters, upper and lower case, including numbers. (as recommended by the user guide)
$config['encryption_key'] = "NeO5C88iv7uo09U2E20iJF0iUiz8R9zm";
Now write this down, and put it somewhere safe… and I mean physically write it down… like analogue, on paper….
Because all your passwords are going to use this, and if ever you lose your config.php file, you must restore it and put in the same key.
Now, let’s look at the library.
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;
}
Using the ‘encryption_key’ at the end of the password means that your generated sha1 string will not be the same as the sha1 string for just the password on its own. (which stops dictionary sha1 attacks).
In the ‘good old days’, when the famous ‘PHPNuke’ was extremely popular, people would find SQL injection holes to run their own queries:
$search = $_POST['search'];
$query = 'select * from articles where title='$search';
But, if you post the search term:
'; select * from users where id = '1
the final sql would be:
select * from articles where title=''; select * from users where id = '1';
Then, by finding the password, (which was only encrypted using MD5($password) without a salt, the intruder could use a dictionary attack like:
$stolen_md5 = 'ainofdifdofij'; // Yes, I know an MD5 is only 0-9 and a-f chars.
foreach ($dictionary as $word)
{
if (MD5($word) == $stolen_md5)
{
echo 'password is: '.$word;
exit;
}
}
So, by using a salt (the encryption key tagged on the end of your password)... the result sha1 is nothing like the sha1 for the password on its own. Stopping dictionary attacks.
And, the password, even if retrieved from the DB could not be converted back to a ‘real’ string, because sha1 is a 1-way hashing algorithm.
Simply using $this->encrypt->encode() is dangerous, because if someone gained your key, they have the means to convert your passwords back to plain text. (granted, it’s not easy… but still possible).
when you insert a user:
$data = array('username' => $username, 'password' => $this->_prep_password($password));
$this->db->insert('users', $data);
So, there’s a little example of a ‘very good’ practice when it comes to passwords and databases…
With an explanation into ‘why’ do it this way.
Hope this is useful.