Simple password entry

advertisements

I'm looking for a simple (or as simple as possible) yet secure method for hashing and salting a users password when submitting it to the database and then retrieving from the database. Having spent the past 3 hours researching, there are literally hundreds of different methods that each person will say is the best method.

I'm looking for a relatively simple method that will also keep users accounts secure. Obviously the term secure can be interpreted differently, but i just want it, at the very least, be very difficult for a would-be hacker (or whatever you'd call these saddo's) to gain access to a users account.

I appreciate that i should have at least tried a few things, but they all seem so convoluted and overly secure for my purpose.

I tried using password_hash() but it appears i'm running an earlier PHP version than 5.5. I understand there are issues with the code below, but it's simply a starting point for a person project i'm working on in order to better learn PHP.

Current registration form

$username = $_POST['username'];
$password = $_POST['password'];

try {   

    $result = $db->prepare("INSERT INTO
                            user_info
                            SET
                            username = :user,
                            pass = :pass
                            ");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
}

catch (Exception $e) {
    echo "Could not create username";
}

if (isset($_POST['submit'])) {
    foreach ($_POST as $field) {
        if (empty($field)) {
            $fail = true;
        }
        else {
            $continue = false;
        }
    }
    if ($field == $fail) {
        echo "You must enter a username and/or password";
    }
    else {
        echo "Your account has been successfully created.";
    }
     }

The login logic

$username = $_POST['username'];
$password = $_POST['password'];

try {   

    $result = $db->prepare("SELECT username, pass FROM user_info WHERE username = :user AND BINARY pass = :pass");
    $result->bindParam(':user', $username);
    $result->bindParam(':pass', $password);
    $result->execute();
    $rows = $result->fetch(PDO::FETCH_NUM);
}

catch (Exception $e) {
    echo "Could not retrieve data from database";
    exit();
}

if ($password = $rows) {
    session_start();
    $_SESSION['username'] = $_POST['username'];
    $_SESSION['loggedin'] = true;
    include("inc/redirect.php");

} else {
    if (isset($_POST['login'])) {
        echo "Username or password incorrect (passwords are case sensitive)";
    }
}


With password_hash() you are on the right track. For PHP versions 5.3.7 - 5.5 you can use the compatibility pack, later when you switch to a newer PHP version, you can simply remove this php file from your project and the code will still run.

// Hash a new password for storing in the database.
// The function automatically generates a cryptographically safe salt.
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT);

// Check if the hash of the entered login password, matches the stored hash.
// The salt and the cost factor will be extracted from $existingHashFromDb.
$isPasswordCorrect = password_verify($password, $existingHashFromDb);

Even for lower PHP versions than 5.3.7 you can use the compatibility pack‌​. You only have to edit line 55 and change the algorithm from sprintf("$2y$%02d$", $cost); to sprintf("$2a$%02d$", $cost);. This is of course not optimal, but it is the best you can do for PHP between 5.3 and 5.3.7.

The problem with other algorithms like SHA* or MD5 is, that they are ways too fast. It is possible to calculate about 3 Giga SHA-1 per second with common hardware, that makes brute-forcing too easy. To test a whole english dictionary you would need only a fraction of a millisecond. That's why one should use a hash algorithm with a cost factor like BCrypt or PBKDF2, they allow to control the necessary time to calculate a single hash.