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+

<?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.

Post your comment

Comments

  • Chong Santiago 03/01/2014 5:02pm (4 years ago) Gravatar for Chong Santiago

    Appreciate the recommendation. Let me try it out.

RSS feed for comments on this page | RSS feed for all comments

Copywrite © 2017 Kevin Phillips All rights are reserved.

Proudly supporting opensource software