0

I'm learning about PHP's hashing and salting functions and wanted to try it out, so I created a local database and table with two columns (username and password) in phpmyadmin and populated it with a single username and hashed password.
Now I'm wondering, is there a better way to do what I've done, or something I shouldn't be doing?
(I know having specific error messages is bad, this is just for testing purposes.)

Database: db_users
Table: users
username: username
password: $2y$11$uJiGb3suyiupJNn9MuHNpu7dt6BwB9kS6I4fHDutknggio5PeJ17u

$DB_NAME = "db_users";
$TABLE_NAME = "users";
// The submitted values from the username and password textboxes
$username = $_POST["username"];
$password = $_POST["password"];
// Hash and salt options
$options = [
    'cost' => 11,
    'salt' => mcrypt_create_iv(22, MCRYPT_DEV_URANDOM),
];

$connection = new PDO("mysql:host=localhost", "root", "password");

$sql = $connection->prepare("
    SELECT username 
    FROM $DB_NAME.$TABLE_NAME 
    WHERE (username=:user);");
$sql->bindParam(":user", $username);
$sql->execute();
$rows = $sql->fetch(PDO::FETCH_NUM);

// Check if username exists in database
if ($rows > 0) {
    // Check if passwords match
    $sql = $connection->prepare("
        SELECT password 
        FROM $DB_NAME.$TABLE_NAME 
        WHERE (username=:user);");
    $sql->bindParam(":user", $username);
    $sql->execute();

    if (password_verify($password, $sql->fetch()[0]) > 0) {
        echo "Username and password match";
    } else {
        echo "Username and password do not match";
    }
} else {
    echo "Username does not exist";
}
Isaac Bennetch
  • 11,830
  • 2
  • 32
  • 43
Joseph Webber
  • 2,010
  • 1
  • 19
  • 38
  • 6
    A better way would be to generate a random salt, store the salt in your database and use it to compare when a user tries to log in. This gives more protection against rainbow tables. – Stefan Mar 05 '15 at 15:12
  • 2
    You should not return whether a user exists or not. This already gives a potential attacker information about correct usernames (so he "only" needs to find a password). Just return "user/pass do not match". – joe776 Mar 05 '15 at 15:14
  • @joe776 I stated "I know having specific error messages is bad, this is just for testing purposes". – Joseph Webber Mar 05 '15 at 15:17
  • @Fred-ii- Syntax, validation, security, the whole deal. – Joseph Webber Mar 05 '15 at 15:22
  • No need for 2 queries - select both fields in 1st query. – Steve Mar 05 '15 at 15:22
  • I can't see anything wrong with this, unless somebody gets a hold of your login credentials. However, using prepared statements doesn't offer a guarantee against injection; XSS injection is another factor that could play a role. The [`password_hash()`](http://www.php.net/manual/en/function.password-hash.php) function provides a built-in salting mechanism, so you could get rid of what you're using now and just use the built-in salting method, *if you want to.* – Funk Forty Niner Mar 05 '15 at 15:27
  • Have a read about what I said above in regards to prepared statements/injection, XSS, etc. http://stackoverflow.com/q/134099/ – Funk Forty Niner Mar 05 '15 at 15:29

0 Answers0