How do I use password hashing with PDO to make my code more secure? [closed]

My code is actually working but it's not at all secure, I don't want to use MD5 as it's not all that secure. I've been looking up password hashing but I'm not sure how I would incorporate it into my code.

Login:

require_once __DIR__.'/config.php';
session_start();

$dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_USERNAME, DB_USERNAME, DB_PASSWORD);

$sql = "SELECT * FROM users WHERE username = :u AND password = :p";
$query = $dbh->prepare($sql); // prepare
$params = array(":u" => $_POST['username'], ":p" => $_POST['password']);
$query->execute($params); // execute

$results = $query->fetchAll(); // then fetch


//hash passwords pls

if (count($results) > 0 ){
$firstrow = $results[0];
$_SESSION['username'] = $firstrow['username'];
echo "Hello $username you have successfully logged in";
//header ("location:.php");
}
else{
echo "Login Has Failed";
return;
} 

Register:

$dbh = new PDO('mysql:host=' . DB_HOST . ';dbname=' . DB_USERNAME, DB_USERNAME, DB_PASSWORD);

$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];

$stmt = $dbh->prepare("insert into users set username='".$username."', email='".$email."', password='".$password."' ");
$stmt->execute();
echo "<p>Thank you, you are registered</p>";

Could anyone show me how to incorporate it into the code I have?


Solution 1:

Just use a library. Seriously. They exist for a reason.

  • PHP 5.5+: use password_hash()
  • PHP 5.3.7+: use password-compat (a compatibility pack for above)
  • All others: use phpass

Don't do it yourself. If you're creating your own salt, YOU'RE DOING IT WRONG. You should be using a library that handles that for you.

$dbh = new PDO(...);

$username = $_POST["username"];
$email = $_POST["email"];
$password = $_POST["password"];
$hash = password_hash($password, PASSWORD_DEFAULT);

$stmt = $dbh->prepare("insert into users set username=?, email=?, password=?");
$stmt->execute([$username, $email, $hash]);

And on login:

$sql = "SELECT * FROM users WHERE username = ?";
$stmt = $dbh->prepare($sql);
$result = $stmt->execute([$_POST['username']]);
$users = $result->fetchAll();
if (isset($users[0]) {
    if (password_verify($_POST['password'], $users[0]->password) {
        // valid login
    } else {
        // invalid password
    }
} else {
    // invalid username
}

Solution 2:

About making your code more secure:

  • You should ALWAYS validate user entries, even from a POST method which can be changed by using firebug before submitting the form. As you are inserting the user input in a query, it's much more important.

About your question in general

As I advised you in the comment, use PHPass or already made APIs which will do the job for you.

You'll hash the username, pass and salt at account creation time and insert the hash in the database.

At authentication time, you'll regenerate a hash with the given login + password input and the information you added to generate the salt.

If both generated hashes match, then the user is authenticated.

EDIT: Yes password_hash is good also.