I am Using PHP version 5.4 and I have looked around for a while now for a hashing mecanism but I can't get it to work. The tricky part is validating the hashed password with another one the user tries, what am I doing wrong here?
//and yes I am using password as name in this example
$password_entered ="cucumberball";
$password_hash = crypt($password_entered);
mysql_set_charset('utf8');
pdoConnect();
//insert hashed pass (same name and pass(hashed) for user)
$stmt = $pdo->prepare("insert into user (name,password) values (:name,:password)");
$stmt->bindParam(':name', $password_entered);
$stmt->bindParam(':password', $password_hash);
$stmt->execute();
//retriving password from db and checking if its correct with the login password provided
$stmt = $pdo->prepare("select password from user where name = :name LIMIT 1;");
$stmt->bindParam(':name', $password_entered);
$stmt->execute();
$user = $stmt->fetch(PDO::FETCH_OBJ);
if(crypt($password_entered, $password_hash) == $user->password) {
// password is correct
echo "WORKS";
}else{
echo "did not work";
}
When you're comparing you are salting when encrypting the password and the password from the database is only encrypted.
if(crypt($password_entered, $password_hash) == $user->password) {
Also, according to the documentation you should be comparing like this
You should pass the entire results of crypt() as the salt for
comparing a password, to avoid problems when different hashing
algorithms are used. (As it says above, standard DES-based password
hashing uses a 2-character salt, but MD5-based hashing uses 12.)
if (hash_equals($hashed_password, crypt($user_input, $hashed_password))) {
echo "Password verified!";
Fix this if statement:
if(hash_equals(crypt($password_entered, $password_hash), $password_hash))
{
echo "WORKS";
}
Or as there is no hash_equals in PHP 5.4:
if(crypt($password_entered, $password_hash) == $password_hash)
{
echo "WORKS";
}
But without hash_equals, your hashes are vulnerable to timing attack.
Also you may want to read this manual.
Related
I am using sha1 for my password security. I have stored password in this way in register.php
// secure password
$salt = openssl_random_pseudo_bytes(20);
$secured_password = sha1($password . $salt);
//Send it to mysql table
$result = $access->registerUser($username, $secured_password, $salt, $email, $fullname);
This all is working fine.
Problem is here:
In my login.php
$password = htmlentities($_POST["password"]);
$secure_password = $user["password"];
$salt = $user["salt"];
// 4.2 Check if entered passwords match with password from database
if ($secure_password == sha1($password . $salt)) {
//do something
} else {
//do something
}
I am always getting as password does not match.
where am I going wrong?
First is first. NEVER USE SHA OR MCRYPT TO STORE YOUR PASSWORD.
EDIT : The password_hash() function generates a long password hash, so make sure that your column in the mysql is a VARCHAR of 500 space
All these useless practises is the root reason why almost many websites get hacked. To tackle the situation, php did a lot of research and then at last came with the most secure function called the password_hash(). I am not more onto explaining about password_hash() here as there are already many documents on the internet.
You can always hash a password like this
<?php
$securePassword = password_hash($_POST['password'], PASSWORD_DEFAULT);
$query = $db->query('INSERT INTO users ......');
?>
And, to verify the password, you can simply use this function
<?php
$passwordHash = $query['password']; //Password from database
$userPassword = $_POST['password']; //Password from form
if(password_verify($userPassword, $passwordHash)) {
echo 'Password is correct, logged in!';
} else {
echo 'Password is wrong, try again';
}
?>
And, answer for your question.
PLEASE DON'T USE SHA OR MCRYPT OR BCRYPT. IF YOU WANNA GET YOUR WEBSITE HACKED, THEN CONTINUE. OR USE password_hash()
The reason you don't get the hash genereated each time because the openssl_random_pseudo_bytes() generates random numbers each time. So each time, during execution, the function returns different numbers and you get your sha result wrong and thus giving a FALSE alert.
PLEASE, AGAIN. I BEG YOU TO USE password_hash() FUNCTION
For more information on password_hash() and password_verify() :
http://php.net/manual/en/function.password-hash.php
http://php.net/manual/en/function.password-verify.php
im doing a tutorial about how to make a php mysql login form.
now the tutorial is actualy made to good and i wold like to alter it a bit and change the login password to store cleartext instead of the hash. the hash line looks like this:
$new_password = password_hash($upass, PASSWORD_DEFAULT);
i made:
$new_password = $upass;
out of it. and it now saves the cleartext to the database but the login doesn't work.
the login part looks like this and i don't see the part where i expect the hashed-password to be converted and matched...
public function doLogin($uname,$upass)
{
try
{
$stmt = $this->conn->prepare("SELECT user_id, user_name, user_pass FROM users WHERE user_name=:uname");
$stmt->execute(array(':uname'=>$uname));
$userRow=$stmt->fetch(PDO::FETCH_ASSOC);
if($stmt->rowCount() == 1)
{
if(password_verify($upass, $userRow['user_pass']))
{
$_SESSION['user_session'] = $userRow['user_id'];
return true;
}
else
{
return false;
}
}
}
catch(PDOException $e)
{
echo $e->getMessage();
}
}
The line:
if(password_verify($upass, $userRow['user_pass']))
Checks the hash of the password against the given password. As you've removed the hashing function it's comparing an un-hashed password against a clear text password.
Change it to:
if($upass == $userRow['user_pass'])
That should fix it.
Although you really should not be storing clear text passwords.
If you're not hashing the passwords anymore then you can't verify the hash
if(password_verify($upass, $userRow['user_pass']))
Should be
if($upass == $userRow['user_pass'])
Understand that this is a very bad idea. You might not understand why hashing passwords is important
For any reason, your database may be compromised and its data may be obtained by someone else. If the passwords are in what we call plain text, you will have leaked a piece of sensitive information that your users have trusted you with: their password (which is very likely to be a password shared in multiple services). This is a very serious issue.
I have a issue regarding logging in with password being hashed in database.
My current script just tells me 'bad password' message even when its correct.
$s = $mysqli->query("SELECT * FROM `users` WHERE email`='".$_POST['email']."'") or die();
$i = $s->fetch_assoc();
if($_POST['password'] == sha1($i['password'])) {
echo "works";
} else {
echo "bad password";
}
You are doing it the wrong way round. The database password is already hashed I hope but the user enters a plain text password, so you need to hash what the user enters and see if that matches the hash you have on the database
$s = $mysqli->query("SELECT * FROM `users` WHERE `email`='{$_POST['email']}'") or die();
$i = $s->fetch_assoc();
if(sha1($_POST['password']) == $i['password']) {
echo "works";
} else {
echo "bad password";
}
However
Please dont roll your own password hashing. PHP provides password_hash()
and password_verify() please use them, I might want to use your site one day
And here are some good ideas about passwords
If you are using a PHP version prior to 5.5 there is a compatibility pack available here
Also
Your script is at risk of SQL Injection Attack
Have a look at what happened to Little Bobby Tables Even
if you are escaping inputs, its not safe!
Use prepared statement and parameterized statements
Here is an example of how you can verify sha with mysql safely.
<?php
// Basic php MYSQL authentication with crypted password
$username = $_POST['username'];
$password = $_POST['password'];
$salt = "CrazyassLongSALTThatMakesYourUsersPasswordVeryLong123!!312567__asdSdas";
$password = hash('sha256', $salt.$password);
//echo $password;
// Mysql connection
$mysqli = new mysqli("localhost","mysqluser","mysqlpassword","mysqldatabase");
$stmt = $mysqli->prepare('SELECT userid FROM Users WHERE password = ? AND username = ?');
// (ss -> string, string) Always bind parameters and use prepared statement to improve security
$stmt->bind_param("ss", $password, $username);
$stmt->execute();
$stmt->bind_result($userid );
if (!empty($stmt->fetch())) {
// if fetch is not empty we have results and password hash was correct
echo "User was found";
} else
echo "User was not found";
$mysqli->close();
?>
When the user signs up the php 5.5 password hashing api is used where the salt is part of the hashed password and does no have to be stored separately. When a user logs in you compare the password they entered ($password) to the hashed password stored in the database ($hash). Therefore you compare them using:
<?php
if (password_verify($password, $hash)) {
// Success!
}
else {
// Invalid credentials
}
The problem with this is that you can't hash the password and then see if both the email and password exist in the database using code like:
if ($stmt = $mysqli->prepare("SELECT id, username, password, salt
FROM members
WHERE email = ?
LIMIT 1")) {
$stmt->bind_param('s', $email); // Bind "$email" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
// get variables from result.
$stmt->bind_result($user_id, $username, $db_password, $salt);
$stmt->fetch();
// hash the password with the unique salt.
$password = hash('sha512', $password . $salt);
if ($stmt->num_rows == 1) {
I was considering fetching the password for a set email and setting it the value of $hash and then running the first piece of code, but I believe that it would be open to hacking via sel injection.
So how would I check if a email and password are correct in order to validate a login? Thanks :)
My login form isn't recognising existing users. The passwords I have stored in the database are encrypted using PHP's crypt() function. When the user registers their password is also encrypted and inserted into the database.
As you can see in the code below it checks to see if the password entered below matches, but whenever I enter in a password that is stored in the database with the corresponding username it says that the user does not exist.
I'm new to PDO and this is my first time using it, normally if I just use MySQL it works fine, but for some reason this isn't, I have changed the code a bit yet it still does not work. Anyone know why/where/what I'm doing wrong with the code.
include "connect.php";
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users WHERE username=:username";
$statement = $db->prepare($sql);
$statement->bindValue(':username',$username,PDO::PARAM_STR);
if($statement->execute())
{
if($statement->rowCount() == 1)
{
$row = $statement->fetch(PDO::FETCH_ASSOC);
if(crypt($password, $row['username']) == $row['user_password'])
{
$username = $row['username'];
$email = $row['email'];
$_SESSION['username'] = $username;
$_SESSION['email'] = $email;
$_SESSION['logged_in'] = 1;
header("Location: index.php");
exit;
}
else
{
include "error_login.php";
}
}
else
{
include "error_login.php";
}
}
if(crypt($password, $row['username']) == $row['user_password'])
Should be
if(crypt($password) == $row['user_password'])
To verify a password with its stored hash-value, you need to know the salt and the algorithm that was used to generate the hash-value before. This salt can be extracted from the stored hash-value, because crypt() stores it as part of the resulting string.
if (crypt($password, $row['user_password']) === $row['user_password'])
PHP 5.5 will have it's own functions password_hash() and password_verify() ready, to simplify generating BCrypt hashes. I strongly recommend to use this excellent api, or it's compatibility pack for earlier PHP versions. The usage is very straightforward:
// 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);