Better password hashing for Codeigniter

I’ve been looking for a more secure way to encrypt (well hash because it’s one way) passwords.

This is my adaptation of Openwall‘s phpass. What I’ve done is stripped out all the backward php compatible code to make this a super slim files.

Note that this will only work on php 5.3+

in application/library create a new file auth.php

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Auth {

    public function hash($password, $work_factor = 6) {
        if (version_compare(PHP_VERSION, '5.3') < 0) {
            throw new Exception('Auth Library requires PHP 5.3 or above');
        }
        return crypt($password, self::generate_blowfish_salt($work_factor));
    }

    public function check($password, $stored_hash) {
        if (version_compare(PHP_VERSION, '5.3') < 0) {
            throw new Exception('Auth Library requires PHP 5.3 or above');
        }

        return crypt($password, $stored_hash) == $stored_hash;
    }

    private function generate_blowfish_salt($work_factor) {

        $random = openssl_random_pseudo_bytes(16);

        $itoa64 = './ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';

        $output =  '$2a$';
        $output .= chr(ord('0') + $work_factor / 10);
        $output .= chr(ord('0') + $work_factor % 10);
        $output .= '$';

        $i = 0;
        do {
            $c1 = ord($random[$i++]);
            $output .= $itoa64[$c1 >> 2];
            $c1 = ($c1 & 0x03) << 4;
            if ($i >= 16) {
                $output .= $itoa64[$c1];
                break;
            }

            $c2 = ord($random[$i++]);
            $c1 |= $c2 >> 4;
            $output .= $itoa64[$c1];
            $c1 = ($c2 & 0x0f) << 2;

            $c2 = ord($random[$i++]);
            $c1 |= $c2 >> 6;
            $output .= $itoa64[$c1];
            $output .= $itoa64[$c2 & 0x3f];
        } while (1);

        return $output;
    }

}

You can now call this library just like any other library in codeigniter from your controller.

$this->load->library('auth');

function login() {

  $this->load->library('form_validation');

  $this->form_validation->set_rules('username', 'Username', 'required|min_length[4]|max_length[20]|xss_clean');

  $this->form_validation->set_rules('password', 'Password', 'required|min_length[4]|max_length[20]|strip_tags');

  if($this->form_validation->run() == FALSE) {

    $this->login_form();

  } else {

    // Just for the purpose of this demo I'm running the database call here but normally I would run this in a model

    $result = $this->db->select('password')->get_where('users', array('username' => $this->input->post('username'))->row();

    // Now call the check function from the Auth Library

    if($has_passed = $this->auth->check($this->input->post('password'), $result->password)) {

      //Do your stuff here for authenticated users like sessions

    } else {

      $this->session->set_flashdata('error_message', 'Incorrect username or password');

      redirect('/ "to the login page"); // Use redirect so you flash message will show

}

If you want to know why I’ve used strip_tags on the password not xss_clean read this.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>