PHP Bytesize : Passsword Hashing

Part of a new series to increase the frequency of the posts here at RecursiveIterator, I’m going to start posting shorter quick tip posts.

Hashing. Encrypting. Cyphering. These are music to the media’s ears when they think of programmers and hackers.

In reality hashing is generally used for data that we want to simply do a comparison with, and we’re not actually too bothered about the original data.

Consider the humble password, when a user enters it, we need to make sure that the password matches the password for the username in the DB.

We don’t strictly care what that password is, just the match.

Next let’s imagine a hacker makes off with the user table somehow, with the passwords. If these are stored as entered, then they can quite easily login and access that users account, make changes and essentially balls things up for everyone. Bad times eh?

So what we want is to hash the password, store this in the DB (so that the password is all but useless to an intruder), and have a process that hashes the input before doing a comparison.

For example let’s say I has a password, such as ‘password’ (unique I know!), upon adding this to the DB we convert it to, lets go with ‘p455w0rd’.

When I login, I enter ‘password’, this is run through the converting function before comparing the result with what is in the DB.

seamus

So say ‘Johnny No Legs’ the devlish hacker, with eye-patch and two wooden legs, gains access to our DB and gets these details.

With a wry grin he enters the password ‘p455w0rd’ and slams his mouse button down on the login button.
Our system converts the entered value, and ah ha!

The result doesn’t match! Foiled again ‘Johnny’.

Now there are multiple ways of achieving this, however did you know that PHP has a built in function for this?

<?php
  //Hash the string 'password' using the bCrypt algorithm
  $password = password_hash('password', PASSWORD_DEFAULT);
  //password_verify(), hashes the entered password, 
  // and compares this with the hash stored in the password variable, 
  // returning a boolean
  if(password_verify($entered_password, $password)) {
    echo 'Correct Password';
  }
  else {
    echo 'Invalid Password';
  }
?>

These handy functions wrap around PHPs own crypt function, simplifying your code, and improving readability.

The beauty of this is, as PHP continues development through versions, improvements to this function won’t require you to refactor your code.
PHP 7 for instance will have an update to how secure this is behind the scenes, without you having to modify your code.

In reality you might you something like this…

<?php
  /**
   * get_user_row, returns a row from the DB, or false
   * @param $DB         object  instantiated PDO object
   * @param $username   string  username to search for
   *
   * @return mixed
   **/
  function get_user_row($DB, $username){
    // Select the data from the table where the username matches
    $statement = $DB->prepare('SELECT * from users WHERE username = :username');
    // Bind the username to our prepared SQL statement
    $statement->bindParam(':username', $username, PDO::PARAM_STR, 100);
    $statement->execute();
    // fetch all the rows, but only return a row if there is only 1 row
    $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
    return (count($rows) === 1) $rows[0] : false;
  }

  /**
   * check_credentials verifies the login credentials
   * @param   $DB         object  instantiated PDO object
   * @param   $username   string  The username of the user
   * @param   $password   string  The password of the user
   *
   * @return boolean
   **/
  function check_credentials($DB, $username, $password) {
    $username = filter_var($username, FILTER_SANITIZE_STRING, FILTER_FLAG_STRIP_HIGH);
    $user = get_user_row($DB, $username);
    return ($user) ? password_verify($password, $user['password']) : false;
  }

  // Create a new pdo object
  $pdo = new PDO('mysql:host=example.com;dbname=database', 'user', 'password');
  // call the check_credentials function with the pdo object, and the username and password
  if (check_credentials($pdo, $_POST['username'], $_POST['password']))
    echo 'Valid Credentials';
  else
    echo 'Invalid Credentials';
?>

Obviously the above is a demonstration and you’d, more likely, use OOP, a controller for the logic, and a user model and a database class for data access.

This however should give you a better understanding of how this is used, rather than a simple if case and variable assignment.

Give it a whirl, you may find it improves the maintainability of your code

– and the future you will pat you on the back, and may buy you a beer, I’ll have a Thatchers if you’re buying.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s