I am working with a specific encryption ( PBKDF2 ) for some reasons. I am now building the website and I am having an issue with the Log In system. The Registration page works perfectly has desired.
I don't have any output of errors when I try to log in and still the password does not match.
Here is my registration.php :
<?php
require '../global.php';
$pdo = New Database();
$account->IPisBanned($_SERVER['REMOTE_ADDR']);
$account->isConnected();
if(!empty($_POST['username']) AND !empty($_POST['email']) AND !empty($_POST['password']) AND !empty($_POST['password_confirmation'])) {
$bdd = $pdo->query('SELECT id FROM users WHERE username = ?', [$core->F_HTML($_POST['username'])]);
if($bdd->rowCount() == 0) {
if(preg_match('`^([a-zA-Z0-9-=?!@]{3,15})$`', $core->F_HTML($_POST['username']))) {
$bdd2 = $pdo->query('SELECT id FROM users WHERE email = ?', [$core->F_HTML($_POST['email'])]);
if($bdd2->rowCount() == 0) {
if(filter_var($core->F_HTML($_POST['email']), FILTER_VALIDATE_EMAIL)) {
if($_POST['password'] == $_POST['password_confirmation']) {
if(strlen($_POST['password']) >= 6 AND strlen($_POST['password_confirmation']) >= 6) {
$iterations = 10000;
$length = 40;
$secret = "at_least_16_byte";
$salt = $secret.$_POST['username'];
$hash = hash_pbkdf2("sha1", $_POST['password'], $salt, $iterations, $length);
$hash = strtoupper($hash);
$bdd3 = $pdo->query('INSERT INTO users (username, password, mail, account_created, ip_reg) VALUES (?, ?, ?, ?, ?)', [$core->F_HTML($_POST['username']), $core->F_HTML($hash), $core->F_HTML($_POST['email']), time(), $_SERVER['REMOTE_ADDR']]);
$_SESSION['id'] = $pdo->lastInsertId();
echo 'success';
} else {
echo 'Passwords does not match.';
}
} else {
echo 'Password too short.';
}
} else {
echo 'Invalid email address.';
}
} else {
echo 'This Email is already used by another account.';
}
} else {
echo 'Invalid username.';
}
} else {
echo 'Username already in use.';
}
} else {
echo 'Required fields are emtpy.';
}
?>
And here is my login.php :
<?php
require '../global.php';
$pdo = New Database();
$account->IPisBanned($_SERVER['REMOTE_ADDR']);
$account->isConnected();
if(!empty($_POST['username']) AND !empty($_POST['password'])) {
$bdd = $pdo->query('SELECT * FROM users WHERE username = ?', [$core->F_HTML($_POST['username'])]);
$iterations = 10000;
$length = 40;
$secret = "at_least_16_byte";
$salt = $secret.$_POST['username'];
$hash = hash_pbkdf2("sha1", $_POST['password'], $salt, $iterations, $length);
$hash = strtoupper($hash);
if($bdd->rowcount() == 1) {
$req = $bdd->fetch();
if(password_verify($hash, $req['password'])) {
$account->UserisBanned($core->F_HTML($_POST['username']));
$_SESSION['id'] = $req['id'];
$account->Update($_SESSION['id']);
echo 'success';
} else {
echo 'The password is incorrect.';
}
} else {
echo 'The username does not exist.';
}
} else {
echo 'The required fields are empty.';
}
?>
I am strongly confused, I spent hours trying to fix this but I really can't.
Thank you for your time :)
It seems that password_verify expects the first param to be the user's plain text password.
Try this:
password_verify($_POST['password'], $req['password'])
NOTE: this means you probably need to drop the strtoupper
as well.
https://www.php.net/manual/en/function.password-verify.php
Note that password_hash() returns the algorithm, cost and salt as part of the returned hash. Therefore, all information that's needed to verify the hash is included in it. This allows the verify function to verify the hash without needing separate storage for the salt or algorithm information.
/**
* (PHP 5 >= 5.5.0, PHP 5)<br/>
*
* Checks if the given hash matches the given options.
* @link https://secure.php.net/manual/en/function.password-verify.php
* @param string $password The user's password.
* @param string $hash A hash created by password_hash().
* @return boolean Returns TRUE if the password and hash match, or FALSE otherwise.
* @since 5.5.0
*/
function password_verify ($password, $hash) {}
password_verify
and do:`if ($hash === $req['password'])`