A lightweight, very secure, codeIgniter authentication library...

zondag 6 december 2009
0 reacties
For my 'dayjob'-cms I wrote a very lightweight CodeIgniter authentication library. Right now it contains a few options:

  1. Registration
  2. Login 
  3. Logout
  4. Groups
  5. Very Secure Hashed Passwords
Want the code? Twitter me. (@fabdrol)
Most existing authentication systems on websites have a few weaknesses.

  • Encryption (2 way)
  • Password retrieval
  • Weak passwords
I'll start with encryption. Basically there's two ways to do so. The first is encryption, the second is hashing.

Encryption works sorta like this: You send your password, your password is encrypted using a key, and the key is used to decrypt the password back to it's original form. Not so secure, since when somebody finds out about the key, or knows the algoritm, you're passwords are in the open.

Hashing is more secure. You 'hash' a password, and it becomes this very unreadable string (like 58cb9c42406324cce492640a0c20d8da) and to check if a user entered the correct password, you will hash the entered password and compare it to the hash in the database.

Code example:


$db = $this->db;

$in_mail = $this->post->input('email', true); // second parameter checks
$in_pass = $this->post->input('password', true); // for xss scripting

$db->where('email', $in_mail);
$db_get = $db->get('users');

if($db_get->num_rows() == 1) {
$db_row = $db_get->row();
} else {
echo "user doesn't exist";
exit();
}

if($db_row->password == sha1($in_pass)) {
// password true, we used sha1 as hashing function
// do login logic and stuff
echo "you're logged in";
}


One big problem: no matter what, the hashing of my password: 'f@bdrolrules!' (obviously without the quotes) always returns the same hashed string: '97e2163bbd1139bfb695031767249fb06c56d112'. (also without the quotes). So if the girl next door (I live in a student house, next door lives this very beautiful girl) happens to think of me like I do, and her password to my great app is also 'f@bdrolrules!', those hashes would be the same. Not really secure, 'cause when I use this password all over the internet, the internet will be flooded with this hash '97e2163bbd1139bfb695031767249fb06c56d112' connected to my name in lot's of databases.

Well, most people wouldn't see that as a big risk, but it actually is. It's much more secure to 'salt' it, meaning that every time you register with that one password, the hash will be different.

The code below is a simple, yet very secure, method for hashing password. Unlike the code before, this should work on any PHP setup, not just in CodeIgniter.


private function _hash($mail, $pass, $salt = false) {
if($salt == false) {
// no salt supplied, so we will generate a new one
$salt = $this->_salt();
}

// $private_key: a 32 char string only known inside your code
// write it down, without it every password in your db will be useless
$private_key = '678bb87f4bfb15f5ed3bf49f722e1c15';

$unhashed = $mail . $pass . $private_key . $salt;
$hashed = sha1($unhashed);

// return the hash AND the salt, for saving into the db.
return array('secure_password' => $hashed, 'salt' => $salt);
}

private function _salt() {
// function to do some stuff and generate a hash that nobody can guess.
// and I mean nobody, even not the beautiful girl next door ;-)

$rand = time().mt_rand();
$uniek = uniqid($rand, true);
return sha1($uniek);
}


So, that's nice. But how do we check and register stuff then?


public function register($mail, $pass) {
$hashed = $this->_hash($mail, $pass);

$user['email'] = $mail;
$user['password'] = $hashed['secure_password'];
$user['salt'] = $hashed['salt'];

// saving the req. data for authentication:
// email (= username), password -- in ultra secure hashed form -- and salt, to check passwords.
}

public function check_pass($mail, $pass) {
$db_salt = $this->_get_salt_from_db_where_email_is_supplied_email($mail);
$db_pass = $this->_get_pass_from_db_where_email_is_supplied_email($mail);

// run hash function, supplying the salt (saved in database)
$hash_arr = $this->_hash($mail, $pass, $db_salt);

// check hashed supplied password against hashed password from DB
if($hash_arr['secure_password'] === $db_pass) {
// using triple === so not only the contents of the hash are the same,
// also the type (string) needs to be the same.

echo "logged in";
// do session magic and stuff
}
}


A bit clear now? twitter me for questions. (@fabdrol)

Writing a CMS in one day...

0 reacties
I've come to this point where I'm able to write a fully featured content management system in less than a day. At least so it seems. Geeky!


Q: How the f*ck did that happen?!


A: 
That's a good question. But before I will answer it, something else. Is it a good or bad thing? You could say, it's not bad to be able to write a full cms in that short amount of time. On the other hand, the fact that I came to this point in my life... Well, it says a thing or two about my geekyness.

Now, you might wonder why I make such a point of that. Maybe you're a startup web developer only dreaming of being able to do this, or maybe you're way more experienced and you think I'm talking trash now. But no. The fact that I would devote one whole day to write something trivial like a CMS, that's just plain stupid. Apart from the lost time, time I could have spent in a club chasing girls for instance, it's not good for my business either.

In fact, it's really bad. Because I already have a good and working CMS for my clients. So, why build another one from (almost) scratch? I really don't know. I didn't had my laptop at hand (was at my parents' place, and used my dad's MacBook Pro) and I guess I was to lazy to download a fresh copy from my web server.  Besides from that, It was kinda fun.

Imagine it like you are a caveman, and you just invented the wheel. But your neighbour just invented beer, and after one night of drinking, laughing and chasing some women's flesh, you wake up wondering where you left your wheel. So, hang-over-y as you are, you chop a new tree and make a new wheel... A better one!

A better one.
Yes, A better CMS. Although, it's not as seasoned as my other CMS, it's built much more modular, making the system more scalable and easier to expand when needed.

Still, I think my geek-o-meter went up a level, yesterday. Not good, or is it?